如果他们不需要定制,那么为您的布局创建支持子类是不是主动?

时间:2017-07-21 14:46:13

标签: android android-custom-view android-layout

我是Android的新手,最近开始采用该模式来创建基于布局文件的自动布局加载自定义视图。在布局中,您使用'合并'标记为根,然后在视图的构造函数中,将该布局扩展到自己,这样您基本上就是合并控件的根。在膨胀之后,仍然在构造函数中,您可以从布局中找到子控件并将它们分配给自定义类中的私有字段,这样即使使用回收器视图,它们也始终可用。

与包含布局的对比。在这种情况下,布局必须定义一个根元素(可以是您的自定义控件,但在这种情况下,您将将布局扩展到您自己,并且必须将控件查找移动到onFinishInflate )否则它最终会有相同的视图层次结构。

简而言之,而不是......

<include layout="@layout/layout_myCustomControl" />

你现在可以这样做......

<com.mydomain.MyCustomControl />

但是我发现自动加载自定义控件版本更加灵活和可维护。第二个优点不仅在于您可以在引用XML布局中使用自定义属性(您可以使用&#39; include&#39;版本),但它也为您提供了一个管理的中心位置代码以及布局管理/控制查找。

所以现在我可以这样做......

<com.mydomain.MyCustomControl
    app:myCustomAttribute="Foo" />

如果控件必须有代码备份其行为,那么它很好地封装在自定义视图中。

以下是自动加载版本的示例布局......

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is static text in the header" />

    <TextView android:id="@+id/dateTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</merge>

这是使用它的班级......

public class MainHeader extends LinearLayout
{
    TextView dateTextView;

    public MainHeader(Context context, @Nullable AttributeSet attrs)
    {
        super(context, attrs);

        setOrientation(VERTICAL);

        LayoutInflater.from(context).inflate(R.layout.header_main, this);

        dateTextView = (TextView)findViewById(R.id.dateTextView);

        dateTextView.setText(<<Code for setting date goes here>>);
    }
}

但我想知道的是,布局是否纯粹是静态的 - 比如说保持静态图像和固定文本 - 使用自定义视图来表示它仍然是一种好习惯吗?为了保持一致性,我说是的,如果我想在将来扩展它,你已经为它做好了准备并且必须在一个地方这样做,无论它使用了多少个地方。相反,如果您将布局直接包含在20个位置,则可能需要更新所有20个(取决于实际更改/需要的内容)。

自定义视图方法的优点:

  1. 管理布局加载和控制查找的中心位置
  2. 可以隐式/内部支持支持代码以更新视图。
  3. 在其他布局文件中引用时可以使用属性
  4. 更好的封装(您可以通过直接方法隐藏布局本身暴露行为)
  5. 可以简单地成为新的&#39; d&#39;在代码中,布局将自动加载。不需要充气或铸造。
  6. 自定义视图方法的缺点

    1. 在布局文件中使用时,您现在还必须指定宽度和高度,使用量更加冗长。
    2. 可以为您的项目添加额外的课程(并非总是,但有时候。)
    3. 同样,在我看来,这似乎是一个明智的选择,但我想知道是否有一个首选的&#39; Androidy&#39;方式,还是仅仅是每个开发人员的偏好?

2 个答案:

答案 0 :(得分:0)

这种方法会在视图树中添加额外的级别。所以你只是让UI树变得更加复杂,没有任何理由。从另一方面来说,您可以按照以下步骤消除这种副作用:

  1. <merge />只能用作XML布局的根标记
  2. 在以<merge />开头的布局展开时,您必须指定父级 ViewGroup您必须将attachToRoot设置为true(请参阅 inflate()方法的文档)
  3. 就是这样。

答案 1 :(得分:0)

显然我想出的并不是那么独特!这里有一篇文章详细解释了这个确切的场景,以及每个场景的优缺点。看起来他们也得出了同样的结论。

TrickyAndroid: Protip. Inflating layout for your custom view