Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Relative path generator of all view present inside rootview hierarchy of any Activity

Background

In android layout file there or lot of UI elements and view group. Sometimes we do not need to give id value ( unique identifier ) to views. In such scenarios we can't find the view by saying findViewByid(). hence we cannot manipulate them.

Question is

How we can generate a path for all view of any activity, Example is below:

content>LinearLayout-0>RelativeLayout-3>LinearLayout-0>TextView-2

The meaning of above line is

  1. Content is main layout
  2. LinearLayoutis top most layout
  3. RelativeLayout-3 is 3rd child of top most layout
  4. LinearLayout is child of 3rd RelativeLayout
  5. TexView-2 is child of LinearLayout which is 3rd RelativeLayout child of topmost LinearLayout.

So basically I'm looking for function like below:

String path = getViewPath(view);

and

View view = findViewByPath(path)

Use case:

Actually server will broadcast some command to mobile app by menting path of view ,

then mobile app will find the view from the path and change the property of the views

like image 317
Lavekush Agrawal Avatar asked Sep 15 '17 09:09

Lavekush Agrawal


1 Answers

Below the solution for above question, I have created both method for getting view path, and getting view by path.

Cheers!!!

    package com.test;

import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;

import java.util.Arrays;


public class CustomViewIdManager {


  private static final String ACTIVITY_CLASS_SEPARATOR = "@";
  private static final String VIEW_SEPARATOR = ">";
  private static final String VIEW_POSITION_SEPARATOR = ":";
  private static final String MAIN_CONTENT_LAYOUT_NAME = "content";


  /**
   * Find given view path in activity hierarchy
   *
   * @param view
   * @param activity
   * @return Path given view
   */
  public static String generateViewPathInActivityViewHierarchy(View view, Activity activity) {

    String path = "";
    View currentView = view;
    ViewParent currentParent;

    do {
      currentParent = currentView.getParent();
      if (currentView.getId() == Window.ID_ANDROID_CONTENT) {
        path = activity.getLocalClassName() + ACTIVITY_CLASS_SEPARATOR + MAIN_CONTENT_LAYOUT_NAME + path;
        break;
      } else {
        path = VIEW_SEPARATOR + currentView.getClass().getSimpleName() + VIEW_POSITION_SEPARATOR + getSelfIndexInParent((View) currentParent, currentView) + path;
      }
      currentView = (View) currentView.getParent();
    } while (true);

    return path;
  }


  /**
   * Finding the view by given path in activity view hierarchy
   * @param path
   * @param activity
   * @return
     */
  public static View findViewByCustomPath(String path, Activity activity) {

    String[] activitySplitting = path.split(ACTIVITY_CLASS_SEPARATOR);
    String[] viewSplitting = activitySplitting[1].split(VIEW_SEPARATOR);

    View viewLooker = null;

    if (viewSplitting[0].equalsIgnoreCase(MAIN_CONTENT_LAYOUT_NAME)) {
      viewLooker = ViewUtil.getContentView(activity);
    }

    return viewFinder(viewLooker, Arrays.copyOfRange(viewSplitting, 1, viewSplitting.length));

  }

  public static View viewFinder(View view, String[] restPath) {

    View viewToSendBack;

    String singleView = restPath[0];
    String[] viewPositioningSplitting = singleView.split(VIEW_POSITION_SEPARATOR);
    viewToSendBack = ((ViewGroup) view).getChildAt(Integer.parseInt(viewPositioningSplitting[1]));

    if (restPath.length > 1) {
      return viewFinder(viewToSendBack, Arrays.copyOfRange(restPath, 1, restPath.length));
    } else {
      return viewToSendBack;
    }
  }


  /**
   * This will calculate the self position inside view
   *
   * @param parent
   * @param view
   * @return index of child
   */
  public static int getSelfIndexInParent(View parent, View view) {

    int index = -1;
    if (parent instanceof ViewGroup) {
      ViewGroup viewParent = (ViewGroup) parent;

      for (int i = 0; i < viewParent.getChildCount(); ++i) {
        View child = viewParent.getChildAt(i);
        ++index;

        if (child == view) {
          return index;
        }
      }
    }

    return index;
  }
}
like image 51
Lavekush Agrawal Avatar answered Sep 28 '22 06:09

Lavekush Agrawal