Reputation: 506
When I use the custom compound view in xml, it works just fine. But when I try to create it in code, it shows blank space.In this case, it seems that inflation has never finished, since OnFinishInflate()
is not called. There is no message in the log about that.
Here is the compound control:
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...
}
The layout:
<?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>
What should I do to successfully create this view programmatically?
EDIT:
Layout, that the view works properly with:
<com.package.ui.AdvancedColorPickerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
EDIT 2: The code I'm using to programmatically create the compound view:
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
}
});
Then at some point I add this view to a container along with others and show it. But I guess this doesn't matter because the problem with the inflater arises in the first row of the code above.
Upvotes: 2
Views: 574
Reputation: 506
Here is what the documentation tells us about onFinishInflate()
:
Finalize inflating a view from XML. This is called as the last phase of inflation, after all child views have been added.
It is stated that the method is called only when inflating from XML.
I expected that creating the compund view, when enters init()
, will inflate the contained views, calling their onFinishInflate()
methods when it's done and after that calling the compound view's onFinishInflate()
. But the latter never happens when the view is created programmatically because it was never meant to be inflated. There is no XML with parameters to inflate the compound view itself, it is constructed. The contained views are the ones to be explicitly inflated (in init()
) and their onFinishInflate()
methods are called as expected. So the inflation doesn't actually fail.
The problem was solved by creating a function build()
that contains all the code I originaly intended to use in onFinishInflate()
. Now I call build()
from onFinishInflate()
which happens when the compound control is inflated from an XML, and once from onAttachedToWindow()
which is taking care of the scenario where the view is programmatically created. In build()
I'm doing a check, making sure that the code is not called twice.
Here's the code:
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...
}
Note that onAttachedToWindow()
is only guaranteed to be executed before drawing of the view, not before measuring for example. In this specific case it is a good choice but for other scenarios you might want to use another event.
Upvotes: 2