在自定义复合控件中使用时,Inflater 静默失败

Inflater silently fails when used in a custom compound control

当我在 xml 中使用自定义复合视图时,它工作得很好。但是当我尝试在代码中创建它时,它显示空白 space.In 这种情况,似乎 inflation 从未完成,因为 OnFinishInflate() 没有被调用。日志中没有关于此的消息。

这里是复合控件:

public class AdvancedColorPickerView extends LinearLayout {
//data...

public AdvancedColorPickerView(Context context) {
    super(context);
    init(context);
}

public AdvancedColorPickerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public AdvancedColorPickerView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

private void init(Context context) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.pdf_advanced_color_picker, this);

}


@Override
protected void onFinishInflate() {
    super.onFinishInflate();

    // NEVER EXECUTED when the view is programmatically created
    // some code doing stuff with the views...

}

//more code...

}

布局:

<?xml version="1.0" encoding="utf-8"?>
<merge>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/pdf_color_tab_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <view class = "com.package.ui.AdvancedColorPickerView$NoTouchViewPager"
        android:id="@+id/pdf_color_view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
</merge>

我应该怎么做才能以编程方式成功创建此视图?

编辑:

布局,视图可以正常工作:

<com.package.ui.AdvancedColorPickerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

编辑 2: 我用来以编程方式创建复合视图的代码:

    AdvancedColorPickerView advancedColorPicker = new AdvancedColorPickerView(parent.getContext());
    advancedColorPicker.setLayoutParams(new AdvancedColorPickerView.LayoutParams(AdvancedColorPickerView.LayoutParams.MATCH_PARENT, AdvancedColorPickerView.LayoutParams.MATCH_PARENT));
    advancedColorPicker.setColor(getColor());
    advancedColorPicker.setOnColorSelectListener(new AdvancedColorPickerView.OnColorSelectListener() {
        @Override
        public void onColorSelected(int color) {
            //some code
        }
    });

然后在某个时候我将此视图与其他视图一起添加到容器中并显示它。但我想这并不重要,因为充气机的问题出现在上面代码的第一行。

这是文档告诉我们的关于 onFinishInflate() 的内容:

Finalize inflating a view from XML. This is called as the last phase of inflation, after all child views have been added.

声明该方法仅在从 XML 膨胀时调用。 我希望创建复合视图,当输入 init() 时,将膨胀包含的视图,在完成时调用它们的 onFinishInflate() 方法,然后调用复合视图的 onFinishInflate()。但是,当以编程方式创建视图时,后者永远不会发生,因为它永远不会被膨胀。没有 XML 带有参数来膨胀复合视图本身,它是构造的。包含的视图是要显式膨胀的视图(在 init() 中)并且它们的 onFinishInflate() 方法按预期调用。所以 inflation 实际上并没有失败。

通过创建函数 build() 解决了问题,该函数包含我最初打算在 onFinishInflate() 中使用的所有代码。现在我从 onFinishInflate() 调用 build() ,当复合控件从 XML 膨胀时发生,一次从 onAttachedToWindow() 调用,它处理以编程方式处理视图的场景创建。 build() 我正在检查,确保代码没有被调用两次。

代码如下:

public class AdvancedColorPickerView extends LinearLayout {
//data...
public AdvancedColorPickerView(Context context) {
    super(context);
    init(context);
}

public AdvancedColorPickerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public AdvancedColorPickerView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

private void init(Context context) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    inflater.inflate(R.layout.pdf_advanced_color_picker, this);
}

private int isBuilt;

private void build()
   {
if(isBuilt)
    return;

    isBuilt = true;
// some code doing stuff with the views...
    return;
}

@Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
build();
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    build();
}

//more code...

}

请注意,onAttachedToWindow() 仅保证在绘制视图之前执行,而不是在测量之前执行。在这种特定情况下,这是一个不错的选择,但对于其他情况,您可能希望使用其他事件。