(Turn) algorithm series - recursive and non-recursive implementation of traversing all controls

Topic description

Given the root node of the layout, it is required to set the background of all controls of type Button to red without recursion.

analyze

For the layout in Android, there are two types of nodes, one is the ViewGroup layout, and the other is the View control, which is organized according to a tree-like structure (note that it is not a binary tree).
For the traversal of the control, it can be transformed into the traversal of the tree. There are recursive and non-recursive ways to traverse the tree, and the non-recursive way can be divided into depth-first traversal and breadth-first traversal.

accomplish

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:background="#abcdef"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#156ec7"
        android:orientation="horizontal"
        android:padding="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="text1"
            android:textColor="#ffffff" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="text2"
            android:textColor="#ffffff" />


    </LinearLayout>


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#5d9726"
        android:padding="10dp">

        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button 2" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/btn"
            android:padding="5dp"
            android:text="text3"
            android:textColor="#ffffff"

            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/btn"
            android:layout_toRightOf="@id/tv"
            android:padding="5dp"
            android:text="text4"
            android:textColor="#ffffff" />

    </RelativeLayout>

</LinearLayout>

 

The interface effect and the corresponding tree structure are as follows:

The node type with color is viewGroup

layout abstract tree structure

Specific algorithm implementation

The following methods implement the traversal results of three methods, and readers can refer to them.

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewGroup root = (ViewGroup) findViewById(R.id.rootView);
        travelTree3(root);
    }
    // recursively traverse the tree

    private void travelTree1(View root) {
        if (root instanceof ViewGroup) {
            int childCount = ((ViewGroup) root).getChildCount();
            for (int i = 0; i < childCount; i++) {
                travelTree1(((ViewGroup) root).getChildAt(i));
            }
        } else if (root instanceof View) {
            Log.i("visitView", root.toString());
            if (root instanceof Button)
                root.setBackgroundColor(Color.parseColor("#ff0000"));
        }
    }

    //Non-recursive breadth traversal, using the queue data structure
    private void travelTree2(View root) {
        ArrayDeque queue = new ArrayDeque();
        queue.addLast(root);
        while (!queue.isEmpty()) {
            // get the head of the team
            View front = (View) queue.getFirst();
            //If it is viewGroup, make the child node into the queue
            if (front instanceof ViewGroup) {
                int childCount = ((ViewGroup) front).getChildCount();
                for (int i = 0; i < childCount; i++) {
                    queue.addLast(((ViewGroup) front).getChildAt(i));
                }

            }
            //If the head of the queue is of View type, output
            else if (front instanceof View)
                Log.i("visitView", front.toString());
            // The head of the team goes out of the queue
            queue.pollFirst();
        }
    }

    //Non-recursive depth traversal, using stack data structure

    private void travelTree3(View root) {

        ArrayDeque stack = new ArrayDeque();
        stack.addLast(root);
        while (!stack.isEmpty()) {
            // get the top of the stack
            View top = (View) stack.getLast();
            // pop the stack
            stack.pollLast();
            //If it is viewGroup, push the child node to the stack
            if (top instanceof ViewGroup) {
                int childCount = ((ViewGroup) top).getChildCount();
                for (int i = childCount - 1; i >= 0; i--) {
                    stack.addLast(((ViewGroup) top).getChildAt(i));
                }
            }
            //If the top of the stack is a View type, output
            else if (top instanceof View)
                Log.i("visitView", top.toString());

        }
    }


}

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326213578&siteId=291194637