Git Product home page Git Product logo

graphview's Introduction

GraphView

Android GraphView is used to display data in graph structures.

alt Logo

Overview

The library can be used within RecyclerView and currently works with small graphs only.

This project is currently experimental and the API subject to breaking changes without notice.

Download

The library is only available on MavenCentral. Please add this code to your build.gradle file on project level:

allprojects {
  repositories {
    ...
    mavenCentral()
  }
}

And add the dependency to the build.gradle file within the app module:

dependencies {
    implementation 'dev.bandb.graphview:graphview:0.8.1'
}

Layouts

Tree

Uses Walker's algorithm with Buchheim's runtime improvements (BuchheimWalkerLayoutManager class). Currently only the TreeEdgeDecoration can be used to draw the edges. Supports different orientations. All you have to do is using the BuchheimWalkerConfiguration.Builder.setOrientation(int) with either ORIENTATION_LEFT_RIGHT, ORIENTATION_RIGHT_LEFT, ORIENTATION_TOP_BOTTOM and ORIENTATION_BOTTOM_TOP (default). Furthermore parameters like sibling-, level-, subtree separation can be set.

Directed graph

Directed graph drawing by simulating attraction/repulsion forces. For this the algorithm by Fruchterman and Reingold (FruchtermanReingoldLayoutManager class) was implemented. To draw the edges you can use ArrowEdgeDecoration or StraightEdgeDecoration.

Layered graph

Algorithm from Sugiyama et al. for drawing multilayer graphs, taking advantage of the hierarchical structure of the graph (SugiyamaLayoutManager class). Currently only the SugiyamaArrowEdgeDecoration can be used to draw the edges. You can also set the parameters for node and level separation using the SugiyamaConfiguration.Builder.

Usage

GraphView must be integrated with RecyclerView. For this you’ll need to add a RecyclerView to your layout and create an item layout like usually when working with RecyclerView.

<com.otaliastudios.zoom.ZoomLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:hasClickableChildren="true">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</com.otaliastudios.zoom.ZoomLayout>

Currently GraphView must be used together with a Zoom Engine like ZoomLayout. To change the zoom values just use the different attributes described in the ZoomLayout project site.

To create a graph, we need to instantiate the Graph class. Next submit your graph to your Adapter, for that you must extend from the AbstractGraphAdapter class.

private void setupGraphView {
    val recycler = findViewById(R.id.recycler)

    // 1. Set a layout manager of the ones described above that the RecyclerView will use.
    val configuration = BuchheimWalkerConfiguration.Builder()
                    .setSiblingSeparation(100)
                    .setLevelSeparation(100)
                    .setSubtreeSeparation(100)
                    .setOrientation(BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM)
                    .build()
    recycler.layoutManager = BuchheimWalkerLayoutManager(context, configuration)

    // 2. Attach item decorations to draw edges
    recycler.addItemDecoration(TreeEdgeDecoration())

    // 3. Build your graph
    val graph = Graph()
    val node1 = Node("Parent")
    val node2 = Node("Child 1")
    val node3 = Node("Child 2")

    graph.addEdge(node1, node2)
    graph.addEdge(node1, node3)

    // 4. You will need a simple Adapter/ViewHolder.
    // 4.1 Your Adapter class should extend from `AbstractGraphAdapter`
    adapter = object : AbstractGraphAdapter<NodeViewHolder>() {

        // 4.2 ViewHolder should extend from `RecyclerView.ViewHolder`
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NodeViewHolder {
            val view = LayoutInflater.from(parent.context)
                    .inflate(R.layout.node, parent, false)
            return NodeViewHolder(view)
        }

        override fun onBindViewHolder(holder: NodeViewHolder, position: Int) {
            holder.textView.text = getNodeData(position).toString()
        }
    }.apply {
        // 4.3 Submit the graph
        this.submitGraph(graph)
        recycler.adapter = this
    }
}

Customization

You can change the edge design by supplying your custom paint object to your edge decorator.

    val edgeStyle = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        strokeWidth = 5f
        color = Color.BLACK
        style = Paint.Style.STROKE
        strokeJoin = Paint.Join.ROUND
        pathEffect = CornerPathEffect(10f) 
    }
    
    recyclerView.addItemDecoration(TreeEdgeDecoration(edgeStyle))

If you want that your nodes are all the same size you can set useMaxSize to true. The biggest node defines the size for all the other nodes.

    recyclerView.layoutManager = BuchheimWalkerLayoutManager(this, configuration).apply { 
        useMaxSize = true
    }

Examples

Rooted Tree

alt Example

Directed Graph

alt Example

Layered Graph

alt Example

License

Copyright 2019 - 2021 Block & Block

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

graphview's People

Contributors

dennisblock avatar gregorblock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphview's Issues

Changing positions of nodes

Hello, I am trying to plot the Nodes with custom x, y values but I notice that using the getters and setters from the Node objects, doesn't change their final position when displayed on the phone. Is it possible to change or modify the vector and/or position values of the Node object, so that I can display them where I want?

Thank you very much!

Make TreeAdapter Public

Right now, TreeAdapter is package-private. That seems to cause problems for Kotlin.

If I have a TreeView named tree, and I try tree.adapter = MySubclassofBaseTreeAdapter(), I get a warning:

Type TreeAdapter<(raw) Any!>! is inaccessible in this context due to: public/*package*/ interface TreeAdapter<VH : Any!> : Adapter, TreeNodeObserver defined in de.blox.treeview in file TreeAdapter.class

If I use tree.setAdapter(MySubclassofBaseTreeAdapter()), it compiles, but I crash at runtime:

java.lang.IllegalAccessError: Illegal class access: 'com.commonsware.android.MyTreeFragment' attempting to access 'de.blox.treeview.TreeAdapter' (declaration of 'com.commonsware.android.MyTreeFragment' appears in ...)

Basically, the method signature of setAdapter() refers to a type (TreeAdapter) that is inaccessible to us. Apparently, plain Java can get past this, but Kotlin appears to not like it. IMHO, it's also strange to have a public method relying on a non-public type.

If possible, please make TreeAdapter public.

Thanks for considering this!

onItemClickListener position issue

When the tree view is zoomed in adapter's onItemClickLisener picks the lastly selected position item instead of the new position. Also when the tree view is zoom out onItemClickListener not even triggering. It's really an awesome library.. it would be much better if it is has improved onClick listener/ onItemClick Listener.

Pair of node as root node

Currently working on Family tree app, where Father and Mother should be in root node and their offspring in the child node. Would be very helpful if this library could create "Pair of node as root node".

Thanks

card view class not found exception

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.altrastudios.stepper, PID: 23686
android.view.InflateException: Binary XML file line #0: Binary XML file line #0: Error inflating class android.support.v7.widget.CardView
Caused by: android.view.InflateException: Binary XML file line #0: Error inflating class android.support.v7.widget.CardView
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v7.widget.CardView" on path: DexPathList[]

Null pointer Exception at 'int de.blox.graphview.tree.BuchheimWalkerNodeData.getDepth()'

Following is the code used:

GraphView graphView = findViewById(R.id.graph);
List<Parent> parent_list = response.body();
Graph graph = new Graph();
    for(int h = 0; h < parent_list.size();h++) {
            Node node1 = new Node(parent_list.get(h).name);
            Node node2 = new Node(parent_list.get(h).user_id);
            graph.addEdge(node1, node2);
      }
final BaseGraphAdapter<ViewHolder> adapter = new BaseGraphAdapter<ViewHolder>(graph) {

            @NonNull
            @Override
            public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.node, parent, false);
                return new SimpleViewHolder(view);
            }

            @Override
            public void onBindViewHolder(ViewHolder viewHolder, Object data, int position) {
                ((SimpleViewHolder)viewHolder).textView.setText(data.toString());
            }
        };
        graphView.setAdapter(adapter);

        // set the algorithm here
        final BuchheimWalkerConfiguration configuration = new BuchheimWalkerConfiguration.Builder()
                .setSiblingSeparation(100)
                .setLevelSeparation(300)
                .setSubtreeSeparation(300)
                .setOrientation(BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM)
                .build();
        adapter.setAlgorithm(new BuchheimWalkerAlgorithm(configuration));

How to fix this issue ? As the graphview loads correctly without using for loop.

Does minSdkVersion really need to be 16?

It's really nice to see this library. I'm wondering for such a library for a long time.

For my case, there is a problem because my app has minSdkVersion 15 while this library is 16.
So... Is it really necessary for GraphView to have minSdkVersion set to 16? I thought most SDK updates are not related to what this library is supposed to provide, so this is not necessary.

Request feature: Add bucle line support

This library is interesting to create flow diagrams:
It is possible to add that a node can link to another node in order to create a loop?
And customize every node with change background shape?
Connect lines with arrow?

Display Text

There's any possibility to add texts in between the nodes?
Something like this:
image

Update node data

Each Node carries some data, and the data is used to generate the view.

How can I update the data and let the view reflect that (i.e. re-draw that particular node [and maybe its edges])?

Zoom feature

Hello.

I like the library but it is in early stages of development. It would be very good if the view has also zooming capabilities.

Thank you so much for this library.

ZoomIn/Out

Hi,

First thanks a lot for this amazing work!
Could you please implement zoomIn/Out ?

Thanks again,
Thibo

Graph elements overlapping

On adding multiple elements like 4 or 5, it overlaps and it's very confusing. Is there anything I can do?
In the given picture Children of A4 and A5 are overlapping.
Screenshot_20190501-193244

Change node layout and create nodes from data source

@NadeemRawther
Please open a new issue instead of spaming your question in unrelated issues. I'm gonna delete your other comments.

Original question:

how can i add two or three text data on this node and how can i make it dynamically create node and make edges according to the data coming from server

horizontal tree support?

Is it possible to start from the left side(parent) to the right side(nodes)? if possible kindly help me to modify the codes or tell me what should I do to aim horizontal tree. Thanks in advance it will really helps.

click on node is not working

I want to click on particular node and navigate to another screen. But when i click on particular node it is not working.

  • click worked in some else in the screen instead of particular node.

Unable access in Kotlin project

I have created kotlin project and i have install this library in that project but i am not able access its functionality,

import de.blox.graphview.sample.GraphActivity
import de.blox.graphview.sample.R

It showing error for "sample" is missing

can anyone guide me how can i access this library in kotlin project?

Delete the node what has a child node.

Hi. I got a problem when deleting a node in the Graph. It works with the node doesn't have any child node, but when I delete the node has some child node below it, I received the error message :
"java.lang.NullPointerException: Attempt to invoke virtual method 'int de.blox.graphview.tree.BuchheimWalkerNodeData.getDepth()' on a null object reference"
How can I resolve it?

GraphView Height

This libraray is good i have used this and also custmize this according to requirement but the one thing that i am unable to correct is height of graph view. I want to show this graph view in dialogFragment and the height of fragment is wrapContent and height of graphView is also wrap content but it is still showimg on full screen. Any idea how can i reduce its height or how can i correct its height according to my graph.

Adapter delegate pattern

Not so much an issue as a question...

Have you considered using the 'adapter delegate' pattern? It could enhance flexibility and could keep the adapter cleaner. I have used a project called Groupie in the past that I have found very useful in separating my presentation code from the domain model.

Coloring node

Color the node outside onBindViewHolder method, so the default color is not blue.

Create checks for each algorithm

Check if the graph meets its expectations for each algorithm. E.g. the tree algorithm can't handle nodes which are not connected to each other.

Display Title with tree

Is It possible to display Title with Tree like Bellow Example

1f2203eb-a103-4760-a655-ddacbd98ef3a

When i zoom tree display title like this

639cd8a5-3937-4902-b118-6014c8e26593

Change size of node

Hi,
Thanks a lot for the wonderful library. Great work on it.
Just had a query, and I didn't know where else to ask.

Is it possible to change the size of a node? XML or programatically?
Changing the node layout's size parameters didn't seem to help.

Thanks,
Nikhil

java.lang.OutOfMemoryError: Failed to allocate a 4000000008 byte allocation with 16777216 free bytes and 167MB until OOM

I have json response with ParentId and memberId . I want to draw the member graph. Please help me to find the solution . Getting following ERROR.:

D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.draw.hierarchyloginregistrationpages, PID: 20459
java.lang.OutOfMemoryError: Failed to allocate a 4000000008 byte allocation with 16777216 free bytes and 167MB until OOM
at com.draw.hierarchyloginregistrationpages.Pages.MemberGraph2.onCreate(MemberGraph2.java:45)
at android.app.Activity.performCreate(Activity.java:6303)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2402)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509)
at android.app.ActivityThread.access$1000(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:5527)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
E/MQSEventManagerDelegate: failed to get MQSService.
I/Process: Sending signal. PID: 20459 SIG: 9
Application terminated.

*************************** DONT HAVE ANY LOOP IN THE DATA ***********************

Please give some code snippet. Thanks in Advance

values.txt

Draw single node

Could you tell me how to draw a node which doesn't have the parent node?

How to Dynamic Node Create

Hello friends.
I'm facing a problem while creating node dynamically. I have 2 column on my database

  1. id
  2. parentId

i want to create dynamically node using 'id' as node name and use it on graph create.
i need help how can i do that dynamically ?

Shuffle Edges

This library is really good, but I wanted to ask if there's any way to shuffle the edges?
I'm constructing BINARY TREE so if I enter values "35, 242, 23" it works like this:

binarytree

addEdge() method will be called twice with node containing "35" as SOURCE NODE. So

addEdge(src: 35, dest: 242)
addEdge(src: 35, dest: 23)

Coding for binary tree is working perfectly, and programmatically 23 is left child of 35 only, but as its edge gets added after 242, it shows node on the right hand side of "node 35" as shown in the above screenshot.

So, is there any way to shuffle the edges? or swap the indexes in the LIST OF EDGES to properly visualize the binary tree

Tree Center issue

I am not able to display tree in center of view, also not able to scroll in center
device-2018-12-04-144344

Multiple parents

I would like to be able to display multiple parents, such as a 1 - 2 - 1 structure.

Not able to display the TreeView

The tree view is not displaying. Below is my code.
I actually use it in a coordinatorLayout associated with a fragment.
Bellow is my code to initiate the TreeView.
`@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_my_with_tree_view, container, false);
    ...
	initTreeView(view);
}
TreeView customTreeView;
private void initTreeView(View view) {
customTreeView = view.findViewById(R.id.treeView);
BaseTreeAdapter adapter = new BaseTreeAdapter<ViewHolder>(mainActivity, R.layout.tree_view_node) {
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(View view) {
            return new ViewHolder(view);
        }
        @Override
        public void onBindViewHolder(ViewHolder viewHolder, Object data, int position) {
            viewHolder.mTextView.setText(data.toString());
            //viewHolder.mTextViewDetails.setText(data.toString());
        }
    };
    customTreeView.setAdapter(adapter);

    // example tree
    rootNode = new TreeNode(getNodeText());
    rootNode.addChild(new TreeNode(getNodeText()));
    final TreeNode child3 = new TreeNode(getNodeText());
    child3.addChild(new TreeNode(getNodeText()));
    final TreeNode child6 = new TreeNode(getNodeText());
    child6.addChild(new TreeNode(getNodeText()));
    child6.addChild(new TreeNode(getNodeText()));
    child3.addChild(child6);
    rootNode.addChild(child3);
    adapter.setRootNode(rootNode);
}
private int nodeCount = 0;
private String getNodeText() {
    return "Referee " + nodeCount++;
}`

Please can anyone tell me what is missing ?

How to add nodes dynamically from firebase

Tried this but app crashes. I also want to add mulitple child nodes to a parent and I cant guess how to do that dynamically.

databaseReference = FirebaseDatabase.getInstance().getReference("family_members/");
databaseReference.addValueEventListener(new ValueEventListener() {
@OverRide
public void onDataChange(DataSnapshot snapshot) {

            for (DataSnapshot postSnapshot : snapshot.getChildren()) {

                FamMembers memberUploadInfo = postSnapshot.getValue(FamMembers.class);

                if(memberUploadInfo.getFname().equals("pp")) {
                    node1 = new Node(memberUploadInfo.getFname());
                    node2 = new Node(memberUploadInfo.getChildren());

                }


            }

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });
    graph.addEdge(node1,node2);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.