I create a tree and come to a standstill when connecting children and parents. Below is a screen layout, you need to connect Zakharov with Ivanov.

enter image description here

and here, in fact, as displayed:

enter image description here

The markup does not represent anything:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:orientation="horizontal"> <TextView android:id="@+id/spacer" android:layout_width="1dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginBottom="0dp" android:textAppearance="?android:attr/textAppearanceLarge" /> <RelativeLayout android:layout_width="wrap_content" android:layout_height="match_parent"> <ImageView android:id="@+id/arrows" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:clickable="true"/> </RelativeLayout> <FrameLayout android:layout_width="wrap_content" android:layout_height="match_parent"> <ImageView android:id="@+id/arrow" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:clickable="true"/> </FrameLayout> <TextView android:id="@+id/content" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginBottom="5dp" android:layout_weight="1" android:divider="@null" android:ellipsize="none" android:paddingLeft="6dp" android:paddingRight="6dp" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> 

Actually draw the lines like this:

 @Override public View getView(int position, View convertView, ViewGroup parent) { TreeListViewHolder holder = null; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.tree_view_cell, parent, false); holder = new TreeListViewHolder(); holder.content = (TextView) convertView.findViewById(R.id.content);//выводим родителей и детей holder.arrow = (ImageView) convertView.findViewById(R.id.arrow);//стрела holder.arrowstatick = (ImageView) convertView.findViewById(R.id.arrows);//стрела //((ImageView)convertView.findViewById(R.id.arrows)).setOnClickListener(mArrowClickListener);//обрабокта нажатия на узел дерева //((TextView)convertView.findViewById(R.id.content)).setOnClickListener(mArrowClickListener);//обрабокта нажатия на узел дерева convertView.setTag(holder); } else { holder = (TreeListViewHolder) convertView.getTag(); } TreeViewNode node = displayNodes.get(position); holder.content.setText(node.getNodeName()); ArrayList<Integer> lvl = new ArrayList<>(); lvl.clear(); lvl.add(node.getNodeLevel()); for (Integer integer : lvl) { if (integer == 0){//если список развернут holder.arrow.setImageResource(0); holder.arrowstatick.setImageResource(0); } if (integer >= 1){//если список развернут holder.arrow.setImageResource(R.drawable.ic_t); //holder.arrowstatick.setImageResource(R.drawable.ic_i); } if (lvl.size() == integer) { holder.arrow.setImageResource(R.drawable.ic_t); } for (TreeViewData data : dataList) { for (TreeViewData viewData : dataList) { if (data.getParentID() == viewData.getID() && data.getParentID() != -1) { //не работает //holder.arrow.setImageResource(R.drawable.ic_l); } } } setNewWidth((integer * 60) + 1); } Log.d("newWidth", "- " + newWidth); ((TextView)convertView.findViewById(R.id.spacer)).getLayoutParams().width = getNewWidth(); //((ImageView)convertView.findViewById(R.id.arrows)).getLayoutParams().width = getNewWidth();//настраиваем выравнивание ((ImageView)convertView.findViewById(R.id.arrows)).jumpDrawablesToCurrentState(); if (getNewWidth() < 73) { Log.d("getNewWidth", "- " + getNewWidth()); //((ImageView)convertView.findViewById(R.id.arrows)).setImageDrawable(null); } else { //((ImageView)convertView.findViewById(R.id.arrows)).setImageDrawable(getResources().getDrawable(R.drawable.ic_i)); //((ImageView)convertView.findViewById(R.id.arrows2)).setImageDrawable(getResources().getDrawable(R.drawable.ic_i)); } ((ImageView)convertView.findViewById(R.id.arrows)).requestLayout(); ((TextView)convertView.findViewById(R.id.spacer)).requestLayout(); return convertView; } } 

Here's how to fill:

 data.add(new TreeViewData(0, "Захаров ", 1, -1)); /*--------------------------------------------------------------------*/ //корни data.add(new TreeViewData(1, "Иванов 1", 2, 1)); data.add(new TreeViewData(1, "Иванов 2", 3, 1)); data.add(new TreeViewData(1, "Иванов 3", 4, 1)); data.add(new TreeViewData(1, "Иванов 4", 5, 1)); /*--------------------------------------------------------------------*/ data.add(new TreeViewData(2, "Адвокатовская 1", 9, 2)); data.add(new TreeViewData(2, "Адвокатовская 2", 10, 2)); data.add(new TreeViewData(2, "Адвокатовская 3", 11, 3)); data.add(new TreeViewData(2, "Адвокатовская 4", 12, 3)); data.add(new TreeViewData(2, "Адвокатовская 5", 13, 4)); data.add(new TreeViewData(2, "Адвокатовская 6", 14, 4)); data.add(new TreeViewData(3, "Адвокатовская 6.1", 15, 14)); data.add(new TreeViewData(3, "Адвокатовская 6.2", 16, 14)); 

I will repeat the question:

How to connect children and parents with lines from ListView ? Or rather, Zakharov and Ivanov, that is, to draw another line.

    1 answer 1

    You need to implement a loop on all ancestors of the current element. For each ancestor, check if he has a brother (sibling) below. If an ancestor has a brother, then add a picture with a vertical line for the current element, if not, add an empty space (picture or empty view, as convenient) as an indent. The additional indents that you have, as I understand it, setNewWidth implemented via setNewWidth are not needed.

    Threat Similarly, it is necessary to check for an element - whether it is the last one in the list of brothers, and if it is the latter, display a picture-corner, and not |- .

    UPD

    Layout layout / tree_view_cell.xml:

     <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:id="@+id/arrows"> </LinearLayout> <ImageView android:id="@+id/arrow" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:clickable="true"/> <TextView android:id="@+id/content" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginBottom="5dp" android:layout_weight="1" android:divider="@null" android:ellipsize="none" android:paddingLeft="6dp" android:paddingRight="6dp" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> 

    Drawing:

     @Override public View getView(int position, View convertView, ViewGroup parent) { TreeListViewHolder holder = null; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.tree_view_cell, parent, false); holder = new TreeListViewHolder(); holder.content = (TextView) convertView.findViewById(R.id.content);//выводим родителей и детей holder.arrows = (LinearLayout) convertView.findViewById(R.id.arrows);//стрелки линии и т.д. holder.arrow = (ImageView)convertView.findViewById(R.id.arrow);// уголок или стрелка convertView.setTag(holder); } else { holder = (TreeListViewHolder) convertView.getTag(); } TreeViewNode node = displayNodes.get(position); holder.content.setText(node.getNodeName()); TreeViewNode parent = node.getParent(); holder.arrows.removeAllViews(); while(parent!=null){ // для всех родителей ImageView spacer = new ImageView(holder.arrows.getContext()); if(parent.hasNext()){ // у родителя есть братья ниже spacer.setImageResource(R.drawable.vert_line); //линия } else { spacer.setImageResource(R.drawable.empty_box_same_size_as_vert_line); //пусто } holder.arrows.addView(spacer, 0); //идем в обратном порядке, поэтому всегда в начало вставляем parent = parent.getParent(); } if(node.isLeaf()){ // лист if(node.hasNext()){ // есть братья ниже holder.arrow.setImageResource(R.drawable.ic_t);// |- } else { holder.arrow.setImageResource(R.drawable.ic_l);// |_ } } else { // аналогично для узлов, у которых есть дети. // всеразличные ветвления на развернутость, наличие братьев ниже в зависимости нужны или нет соответствующие картинки для них } return convertView; } 

    This will require the implementation of methods

    • hasNext - are there any brothers below.

       public boolean hasNext(){ // соответствующие проверки на null надо добавить return parent.children.size()>node.index+1; } 
    • isLeaf - are there any children

       public boolean isLeaf(){ return children.size()>0; } 
    • probably still expanded, etc.
    • I tried it this way, but I still can't draw a vertical line - upward
    • @upward added an example. - Yura Ivanov
    • so I did, just following your logic, you will come back to my version, here is the test project yadi.sk/d/CAcqVZgp3E3uWZ - upward
    • etNewWidth sets the nesting level, if you remove it, that tree does not work - upward
    • It is difficult to come to your option, because you have a node structure that does not contain data about parents, and it is this information that is needed to solve the problem in question. In addition, the snippet that I gave in the answer is not enough to simply insert into your code so that everything magically works. It does not even compile. This is just a demonstration of the algorithm, read the pseudocode. The level of nesting to resolve the issue is generally not needed - Yura Ivanov