Дочерние элементы пользовательского представления имеют значение null после увеличения представления в Android

#java #android #android-custom-view #layout-inflater

#java #Android #android-custom-view #макет-надуватель

Вопрос:

Я работаю над приложением для Android. У меня есть пользовательский вид и макет следующим образом:

 <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>
 

И это класс Java:

 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());        
    }
}
 

И вот как я раздуваю представление (я попробовал оба следующих вызова):

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

Проблема, с которой я сталкиваюсь, заключается в том, что при вызове view.setCard(card) я вижу, что TextView имеет значение null, хотя я ожидаю, что оно будет установлено в методе init(..) . Кто-нибудь может сказать мне, что он неправильно настроен? Заранее спасибо.

Комментарии:

1. Покажите код для действия, пожалуйста

Ответ №1:

Спасибо вам за ваши ответы. Оказывается, init(context) не должен вызываться в конструкторе. Правильное место для его вызова находится в onFinishInflate(). Следующее изменение помогло исправить это:

 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());        
    }
}
 

Комментарии:

1. Это было именно так для меня. Должно быть выше в результатах Google.

Ответ №2:

Вместо использования корневого элемента

 com.hello.view.card.inner.SimpleCardView
 

попробуйте использовать

 <merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:id="@ id/simple_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</merge>
 

затем в вашем методе инициализации

 LayoutInflater.from(context).inflate(R.layout.card_simple, this);
setOrientation(LinearLayout.VERTICAL);
textView = (TextView)findViewById(R.id.simple_label);
 

Когда вы используете представление в других макетах, именно там вы захотите поместить

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

и любые свойства, которые ему нужны, его идентификатор, его ширина / высота и т.д.