findviewbyid - 具有嵌套视图的自定义视图

时间:2018-02-21 14:20:14

标签: android android-custom-view

我有以下代码,我的问题是findviewbyid返回null。

    <es.ric.firebase.chat.core.views.chatbox.ChatBox
        android:id="@+id/chatbox"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <LinearLayout
            android:id="@+id/ll_text"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <EditText
                    android:id="@+id/messageEditText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="5dp"
                    android:layout_gravity="center_vertical"
                    android:paddingLeft="15dp"
                    android:hint="Escribir mensaje"
                    android:background="@drawable/background_chat"/>

                <ImageButton
                    android:id="@+id/bt_upload_picture"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/ic_insert_photo_black_24dp"
                    android:background="@android:color/transparent"
                    android:layout_alignParentEnd="true"
                    android:layout_centerInParent="true"
                    android:layout_marginRight="10dp"/>

            </RelativeLayout>




            <ImageButton
                android:id="@+id/sendButton"
                android:layout_width="36dp"
                android:layout_height="36dp"
                android:src="@drawable/ic_send_white_24dp"
                android:background="@drawable/background_circle"
                android:layout_gravity="bottom"/>

        </LinearLayout>

    </es.ric.firebase.chat.core.views.chatbox.ChatBox>

Java类。

public class ChatBox extends LinearLayout {

    enum State { MODE_MESSAGE, MODE_AUDIO, MODE_RECORDING }

    private EditText messageEditText;
    private ImageButton bt_upload_picture;
    private ImageButton sendButton;
    private WeakReference<ChatBoxListener> weak_listener;

    private State state;

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

    public ChatBox(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ChatBox(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ChatBox(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }


    private void init(){

        messageEditText = findViewById(R.id.messageEditText);
        bt_upload_picture = findViewById(R.id.bt_upload_picture);
        sendButton = findViewById(R.id.sendButton);
    }
}

3 个答案:

答案 0 :(得分:1)

它无法找到视图,因为您的视图尚未存在。在init函数时,只创建了对象。

您需要提供一个globalLayoutListener,它会在您的布局准备好后通知您。为此,请执行ViewTreeObserver.OnGlobalLayoutListener

在init函数中附加监听器

private void init(){
    this.getViewTreeObserver().addOnGlobalLayoutListener(this)
}

最后在onGlobalLayout中调用findViewById

@Override
public void onGlobalLayout(){
    messageEditText = findViewById(R.id.messageEditText);
    bt_upload_picture = findViewById(R.id.bt_upload_picture);
    sendButton = findViewById(R.id.sendButton);
}

答案 1 :(得分:0)

您可以在调用onFinishInflate方法后访问子视图:

@Override
protected void onFinishInflate() {
  init();
}

答案 2 :(得分:0)

当您的自定义视图构造函数运行并且您调用init()时,子视图尚未实例化,也不会添加到您的ChatBox布局中。

从viewgroup到具有相同布局声明的特定子节点的依赖关系无论如何都不是一个好主意。 ChatBox与使用它之间存在不必要的耦合。

你可以等待通货膨胀结束,但出于依赖性的原因,我会将其重构为以下内容:

  1. 从您使用ChatBox的布局中拉出子视图,并将其移动到自己的布局中。

  2. ChatBox夸大该布局并将视图添加到自身。 (使用this作为inflate()的第二个根视图参数。)

  3. 之后,您可以在ChatBox内找到孩子。