Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android-任何活动的rootview层次结构中存在的所有视图的相对路径生成器_Android_Android Layout - Fatal编程技术网

Android-任何活动的rootview层次结构中存在的所有视图的相对路径生成器

Android-任何活动的rootview层次结构中存在的所有视图的相对路径生成器,android,android-layout,Android,Android Layout,背景 在android布局文件中,有一个或多个UI元素和视图组。有时我们不需要为视图提供id值(唯一标识符)。在这种情况下,我们无法通过说findViewByid()来找到视图。因此,我们不能操纵它们 问题是 我们如何为任何活动的所有视图生成路径,示例如下: content>LinearLayout-0>RelativeLayout-3>LinearLayout-0>TextView-2 上面这行的意思是 内容是主要布局 线性布局是最顶层的布局 RelativeLayout-3是最顶层布局的第三

背景

在android布局文件中,有一个或多个UI元素和视图组。有时我们不需要为视图提供
id
值(唯一标识符)。在这种情况下,我们无法通过说
findViewByid()
来找到视图。因此,我们不能操纵它们

问题是

我们如何为任何活动的所有视图生成路径,示例如下:

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

上面这行的意思是

  • 内容是主要布局
  • 线性布局是最顶层的布局
  • RelativeLayout-3是最顶层布局的第三个子级
  • 线性布局是第三个亲戚的孩子
  • TexView-2是LinearLayout的子级,它是最顶层LinearLayout的第三个相对子级
  • 基本上我在寻找如下函数:

    String path = getViewPath(view);
    

    用例:

    实际上,服务器会通过添加视图路径向移动应用程序广播一些命令


    然后移动应用程序将从路径中找到视图并更改视图的属性

    我认为最简单的解决方案是使用
    视图组和方法


    因此,您可以将每个所需的
    视图
    转换为
    视图组
    ,并可以调用上述方法。但是,这不会返回
    字符串
    路径。但是您仍然可以获得一个相对的层次结构,并按照您的特定用例进行工作

    在上述问题的解决方案下面,我创建了获取视图路径的方法和按路径获取视图的方法

    干杯

        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;
      }
    }
    
    package.com.test;
    导入android.app.Activity;
    导入android.util.Log;
    导入android.view.view;
    导入android.view.ViewGroup;
    导入android.view.ViewParent;
    导入android.view.Window;
    导入java.util.array;
    公共类CustomViewIdManager{
    私有静态最终字符串活动\u类\u分隔符=“@”;
    私有静态最终字符串视图_SEPARATOR=“>”;
    私有静态最终字符串视图_位置_分隔符=“:”;
    私有静态最终字符串MAIN\u CONTENT\u LAYOUT\u NAME=“CONTENT”;
    /**
    *在活动层次结构中查找给定的视图路径
    *
    *@param视图
    *@param活动
    *@返回路径给定视图
    */
    公共静态字符串GenerateViewPathinaActivityViewWhierArchy(视图、活动){
    字符串路径=”;
    视图当前视图=视图;
    ViewParent-currentParent;
    做{
    currentParent=currentView.getParent();
    if(currentView.getId()==Window.ID\u ANDROID\u内容){
    path=activity.getLocalClassName()+活动\类\分隔符+主\内容\布局\名称+路径;
    打破
    }否则{
    路径=视图\分隔符+currentView.getClass().getSimpleName()+视图\位置\分隔符+getSelfIndexInParent((视图)currentParent,currentView)+路径;
    }
    currentView=(视图)currentView.getParent();
    }虽然(正确);
    返回路径;
    }
    /**
    *通过活动视图层次结构中的给定路径查找视图
    *@param路径
    *@param活动
    *@返回
    */
    公共静态视图findViewByCustomPath(字符串路径、活动){
    String[]ActivitySpliting=path.split(活动\类\分隔符);
    字符串[]ViewSpliting=ActivitySpliting[1]。拆分(视图分隔符);
    查看查看者=空;
    if(视图拆分[0]。相等信号案例(主内容\布局\名称)){
    viewLooker=ViewUtil.getContentView(活动);
    }
    返回取景器(取景器,数组。copyOfRange(取景器分割,1,取景器分割。长度));
    }
    公共静态取景器(视图,字符串[]restPath){
    查看视图返回;
    字符串singleView=restPath[0];
    String[]viewPositionSpliting=singleView.split(视图位置分隔符);
    viewToSendBack=((ViewGroup)视图).getChildAt(Integer.parseInt(ViewPositionsSpliting[1]);
    如果(restPath.length>1){
    返回取景器(viewToSendBack,Arrays.copyOfRange(restPath,1,restPath.length));
    }否则{
    返回viewToSendBack;
    }
    }
    /**
    *这将计算内部视图中的自身位置
    *
    *@param父级
    *@param视图
    *@child返回索引
    */
    公共静态int getSelfIndexInParent(视图父对象,视图视图){
    int指数=-1;
    if(视图组的父实例){
    ViewGroup viewParent=(ViewGroup)父对象;
    对于(int i=0;i
    没有必要重新发明轮子。如果您需要对视图的引用,除了创建视图路径之外,还有很多方法可以获得。如果希望从视图中引用,请执行以下操作:

    从Xml: 如果您的视图是使用
    XML
    创建的,那么引用这些
    View
    的最佳方法是设置一个id,如:

        android:id="@+id/my_id"
    
    当您想在我们使用的代码中引用该
    视图时:

        (AnyParentOfTheView).findViewById(R.id.my_id);
    
    来自代码(动态): 如果您的视图是动态创建的,那么我们不能使用方法
    (Parent).findViewById(int-id)

    或者

    当您动态创建视图时,我们可以使用我们称之为标记的内容来引用它们。与ID不同,标记是在代码中动态设置到视图的。标记可以是任何Java
    对象
    ,但我们通常使用字符串,但您可以将标记与任何
    对象
    关联,然后使用方法
    findViewWithTag(对象标记)

    例如:

        .......
        TextView myTextView=new TextView(this);
        myTextView.setTag("txt");
        .......
    
    当我们想在代码中引用我们的
    TextView
    时,我们调用如下方法:

        TextView myTextView=(TextView)findViewWithTag("txt");
    
    这样,我们就可以引用我们的
    视图
    ,因此如果您想要
    文本视图
    ,您可以这样做。
    View
    类甚至支持在代码中获取视图标记的方法,如:

        String myTag=myTextView.getTag();
    
    针对您的用例的最佳方法是:

        setTag(Object obj)
        setTag (int key, Object tag)
        getTag(int key)
        getTag()
        findViewWithTag()
    
    给ge
        setTag(Object obj)
        setTag (int key, Object tag)
        getTag(int key)
        getTag()
        findViewWithTag()