FindViewById在自定义相对布局上返回null

Bar*_*ğlu 3 android android-custom-view android-relativelayout

在init方法中,findViewById在R.id.disable_view_content上返回null。

public class DisableView extends RelativeLayout {

    private View content;
    private View disableView;
    private int disableBackgroundColor;
    private boolean isEnabled;

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

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

    public DisableView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainAttributes(context, attrs);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public DisableView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        obtainAttributes(context, attrs);
        init();
    }

    private void obtainAttributes(Context context, AttributeSet attributeSet) {
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attributeSet, R.styleable.DisableView, 0, 0);
        disableBackgroundColor = typedArray.getColor(R.styleable.DisableView_disableBackground, 0x00000000);
        isEnabled = typedArray.getBoolean(R.styleable.DisableView_enabled, false);
        typedArray.recycle();
    }

    private void init() {
        content = findViewById(R.id.disable_view_content);
        disableView = new View(getContext());
        RelativeLayout.LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        lp.addRule(RelativeLayout.ALIGN_TOP, R.id.disable_view_content);
        lp.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.disable_view_content);
        lp.addRule(RelativeLayout.ALIGN_LEFT, R.id.disable_view_content);
        lp.addRule(RelativeLayout.ALIGN_TOP, R.id.disable_view_content);
        disableView.setBackgroundResource(disableBackgroundColor);
        disableView.setLayoutParams(lp);
        setEnabled(isEnabled);
    }

    public void setEnabled(boolean enabled) {
        content.setEnabled(enabled);
        if(enabled) disableView.setVisibility(View.GONE);
        else disableView.setVisibility(View.VISIBLE);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是xml

<com....view.common.DisableView
        android:id="@+id/..._disableView_...Disable"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:id="@id/disable_view_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:id="@+id/..._textView_..."
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_rect_green"
                android:gravity="center"
                android:paddingTop="18dp"
                android:paddingBottom="18dp"
                android:layout_marginBottom="12dp"
                android:textSize="@dimen/size_text"
                android:text="@string/..."
                android:textColor="@android:color/white"
                android:duplicateParentState="true"/>
        </LinearLayout>
    </com....view.common.DisableView>
Run Code Online (Sandbox Code Playgroud)

id disable_view_content位于attr.xml中

<resources>
    <item type="id" name="disable_view_content"/>
</resources>
Run Code Online (Sandbox Code Playgroud)

一切似乎都很好,id为disable_view_content的视图是DisableView的直接子级。但是无论是在编辑模式还是在应用程序上,我都会得到一个空指针,因为引用内容为空。

编辑:这是堆栈跟踪:

 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setEnabled(boolean)' on a null object reference
            at com....view.common.DisableView.setEnabled(DisableView.java:71)
            at com....view.common.DisableView.init(DisableView.java:67)
            at com....view.common.DisableView.<init>(DisableView.java:35)
Run Code Online (Sandbox Code Playgroud)

Tan*_*.7x 5

findViewById()在View的生命周期中打电话太早了。

init()直接从你的构造函数调用,你甚至创造了一个布局自己的视图之前。此时,您的视图没有布局,也没有子级。

在调用其中一种方法之后,最早可以访问子视图addView()

  • 我相信重写_View.onFinishInflate()_方法将是开始处理子视图的最佳位置之一。 (4认同)