Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.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
Java Android:如何使用LayoutFlater避免视图组加倍_Java_Android_Xml_Android Layout_Layout Inflater - Fatal编程技术网

Java Android:如何使用LayoutFlater避免视图组加倍

Java Android:如何使用LayoutFlater避免视图组加倍,java,android,xml,android-layout,layout-inflater,Java,Android,Xml,Android Layout,Layout Inflater,我找到了一个解决方案 非常感谢cyroxis的建设性批评和建议,这些批评和建议引导我走向了正确的方向。起初我认为这不是公认的答案,但经过一番思考后,我确信这是正确的 尽管如此,我还是想提供一些与我的案例更为精确的补充信息 你可以在这篇文章的底部找到解决方案文本 原始问题 我的第一个问题是::-)让我们开始: 我想知道在扩展视图组(例如LinearLayout)的自定义类中使用LayoutInflater时,是否有一种简单的方法(可能通过API?!)来避免不必要的深度视图层次结构 比如说 这是一个

我找到了一个解决方案

非常感谢cyroxis的建设性批评和建议,这些批评和建议引导我走向了正确的方向。起初我认为这不是公认的答案,但经过一番思考后,我确信这是正确的

尽管如此,我还是想提供一些与我的案例更为精确的补充信息

你可以在这篇文章的底部找到解决方案文本

原始问题

我的第一个问题是::-)让我们开始:

我想知道在扩展视图组(例如LinearLayout)的自定义类中使用LayoutInflater时,是否有一种简单的方法(可能通过API?!)来避免不必要的深度视图层次结构

比如说

这是一个Android xml布局文件“my_xml_layout.xml”

这很好,现在我一方面可以在MyCustomView中访问所有子组件,并且可以简单地将MyCustomView添加为视图,例如活动或片段布局

但是:现在在布局层次结构中有两个LinearLayout节点。一个来自布局xml文件,另一个来自MyCustomView父视图组类

那么,我该如何删除一个冗余的视图组(但保留xml文件的视图组的属性值不变)

我以前实现这一点的方法是键入大量代码,将xml布局膨胀为局部变量,并从中提取每个子组件,以便再次将其附加到java视图组

还是我做错了?除了在xml编辑器中设计外,还有其他方法可以编程复杂视图的行为吗

非常感谢你的想法

谢谢大家!

马丁

更新#1

令人遗憾的是,cyroxis建议的解决方案并非如此。让我解释一下我的观察结果(对不起,我的英语不好,如果我犯了错误,请纠正我-这有助于我提高英语技能:-):

根据我的经验,只有在使用所有onDraw和onMeasure实现在Java代码中创建完全定制的视图时,使用完整的限定符名称才有意义。然后,要将自定义视图包含到xml布局层次结构中,必须这样做,并在布局文件中使用完整的限定符名称。在可设置样式的xml文件中还定义了其他属性之后,您可以简单地配置自定义视图,而无需更改Java代码中的一行

尽管如此,我还是尝试使用完整的限定符来测试我是否遗漏了一些东西,或者我的知识是否落后于Android API的实现功能。但是没有,我找不到使用完整限定符名称可以帮助我解决问题的配置。更糟糕的是,Android Studio在开发的这一阶段对限定符名称的更改非常敏感,并且在启用预览渲染器并且出现语法错误或一些奇怪的依赖循环时经常崩溃。;-)

需要明确的是:用完整的限定符名称封装整个布局结构通常是可行的(就不破坏IDE而言),但不会“简单地”合并子视图,而不需要再次调用LayoutInflater—cyroxis希望避免的

说到“合并”:合并标签是我发现的最接近我所希望的行为方式的东西。使用merge封装布局并在自定义视图类中扩展布局确实节省了一级布局层次结构,但这是以直观的xml布局工作流为代价的,因为布局编辑器不再具有视图组信息来设置合并的子视图位置(但它在运行时起作用)

为了明确我的立场:我希望能够使用Android的标准视图组成一个更复杂的视图,然后用Java代码编排所有子组件,创建一个奇特的新视图,我可以在其他xml布局文件、活动和片段中重用它。在我看来,在活动或片段中编程组合视图的逻辑不是一个好的选择,因为它使得代码对于任何进一步的活动或片段都是多余的。创建静态方法,或者完全松散的类,这些类需要一个实例到复杂视图中的一个、部分或所有布局组件,这符合易于维护的代码和封装模块的思想

我将在这里提供另一个我已经使用了很长时间的解决方案,在几个小时内。这让我想知道我是否是为数不多的真正为这个问题烦恼的人之一

更新#2

我做了一些进一步的调查,发现了一些有趣的东西——也许它与cyroxis的解决方案有很多共同之处:

  • 我将完整的限定符名称添加到组合xml视图最顶层的视图组中,指向我的Java类(如cyroxis所说)
  • 我使用“include”指令将xml布局添加到片段的布局xml文件中

  • 结果是,渲染器(和我的设备)正确显示合成视图。所以我假设它从我的Java类中获取了视图组信息(实际上它是一个线性布局),因为这是唯一注意到这一点的地方

    现在:如果是这种情况,如何访问不同的子组件

    this.getChildAt(...) 
    
    不适合我

    第二项意见:

    如果我不是通过include指令而是直接使用

    <net.martinmajewski.challengeme.views.panels.HintActivationPanel/>
    
    
    
    我得到了一个没有任何维度的不可见节点。 因此,布局属性此时在Java类中不可用

    到目前为止,我的Java类没有做什么特别的事情。它只实现三个构造函数,并且(如上所述)尝试访问子组件

    解决方案

    先决条件:

    • 创建一个布局xml文件,其中包含要组合到单个复杂视图中的所有(标准Android)视图。这是您视图的设计阶段
    • 你创造
      this.getChildAt(...) 
      
      <net.martinmajewski.challengeme.views.panels.HintActivationPanel/>
      
      <?xml version="1.0" encoding="utf-8"?>
      <com.package.MyCustomView xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical" android:layout_width="match_parent"
          android:layout_height="match_parent">
      
          <TextView
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="New Text"
              android:id="@+id/textView" />
      
          <ImageView
              android:layout_width="64dp"
              android:layout_height="64dp"
              android:id="@+id/imageView"
              android:layout_gravity="center_horizontal" />
      
          <Button
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="New Button"
              android:id="@+id/button"
              android:layout_gravity="center_horizontal" />
      </LinearLayout>
      
      public class MyCustomView extends LinearLayout {
      
        // Note: I am not inflating the layout here
      
        public void foo() {
            // Do some foo
        }
      
        public void setTitle(String text) {
            findViewById(R.id.textView).setText(text);
        }
        ....
      
      }
      
       MyCustomView view = (MyCustomView) LayoutInflater.from(context).inflate(R.layout.my_xml_layout, parent, true);
       view.foo(); // Do some foo
       view.setTitle("Hello Word!!!");