Search code examples
javaandroidandroid-custom-viewlayout-inflater

Custom View children are null after inflating the view in Android


I am working on an Android app. I have a custom view and layout as follows:

<com.hello.view.card.inner.SimpleCardView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/card_simple_linear_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

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

</com.hello.view.card.inner.SimpleCardView>

And this is the Java class:

public class SimpleCardView extends LinearLayout {
    protected SimpleCard card = null;
    protected TextView textView;

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

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

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

    protected void init(Context context) {
        textView = (TextView)findViewById(R.id.simple_label);
    }

    public void setCard(SimpleCard card) {
        this.card = card;
        textView.setText(card.getMessage());        
    }
}

And this is how I am inflating the view (I tried both following calls):

SimpleCardView view = (SimpleCardView)inflater.inflate(R.layout.card_simple, null);
//SimpleCardView view = (SimpleCardView)inflater.inflate(R.layout.card_simple, parent);
view.setCard(card);

The problem I am having is when view.setCard(card) is called, I see that textView is null, even though I am expecting it to be set in the init(..) method. Can anyone tell me what it not being set correctly? Thanks in advance.


Solution

  • Thank you for your answers. It turns out init(context) should not be called in the constructor. The right place to call it is in onFinishInflate(). The following change helped fix it:

    public class SimpleCardView extends LinearLayout {
        protected SimpleCard card = null;
        protected TextView textView;
    
        public SimpleCardView(Context context) {
            super(context);     
        }
    
        public SimpleCardView(Context context, AttributeSet attrs) {
            super(context, attrs);      
        }
    
        public SimpleCardView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            init(getContext());
        }
    
        protected void init(Context context) {
            textView = (TextView)findViewById(R.id.simple_label);
        }
    
        public void setCard(SimpleCard card) {
            this.card = card;
            textView.setText(card.getMessage());        
        }
    }