findViewById returns null in custom View after inflate

时光怂恿深爱的人放手 提交于 2019-12-12 10:54:56

问题


I have a custom RelativeLayout and I inflate an xml res file in it. This works fine if I use the custom layout in an xml file and set it as contentview, but if I try to add it in the code with new LocationItem(this) and addChild() the findViewById method always returns null in the constructor of the custom RelativeLayout.

Here is the code:

public class LocationItem extends RelativeLayout {

private String parcelType;
private int countIntoBox, countFromBox;

private RelativeLayout deliveryContainer, pickupContainer;

private TextView countPickup, countDelivery;

public LocationItem(Context context) {
    this(context, null);
}

public LocationItem(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public LocationItem(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    inflate(getContext(), R.layout.list_item_location, this);
    deliveryContainer = (RelativeLayout) findViewById(R.id.rl_location_delivery_container);
    pickupContainer = (RelativeLayout) findViewById(R.id.rl_location_pickup_container);
    countPickup = (TextView) findViewById(R.id.tv_location_pickup_count);
    countDelivery = (TextView) findViewById(R.id.tv_location_delivery_count);

    countPickup.setOnClickListener(getShowNumberPickerListener());
    countDelivery.setOnClickListener(getShowNumberPickerListener());
}

private OnClickListener getShowNumberPickerListener() {
    return new OnClickListener() {
        @Override
        public void onClick(View view) {
            showNumberPickerDialog(view);
        }
    };
} ...
}

Add custom view in activity

mRootLayoutLocations.addView(new LocationItem(this));

The view is inflated correctly, because I can see it, but when I try to access a view inside the custom view the app crashes with a NullPointerException.


回答1:


Ok i inflated the view into a View(holder)

View v = inflate(getContext(), R.layout.list_item_location, this); 

and then access the views via v.findViewById. Now it's working.

Code:

View v = inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) v.findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) v.findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) v.findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) v.findViewById(R.id.tv_location_delivery_count);

countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());



回答2:


You need to be using appropriate constructors, not overloading them.

public class LocationItem extends RelativeLayout {

    private String parcelType;
    private int countIntoBox, countFromBox;

    private RelativeLayout deliveryContainer, pickupContainer;

    private TextView countPickup, countDelivery;

    public LocationItem(Context context) {
        super(context);
        init(context, null, 0);
    }

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

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

    private void init(Context context, AttributeSet attrs, int defStyle) {
        inflate(getContext(), R.layout.list_item_location, this);
        deliveryContainer = (RelativeLayout) findViewById(R.id.rl_location_delivery_container);
        pickupContainer = (RelativeLayout) findViewById(R.id.rl_location_pickup_container);
        countPickup = (TextView) findViewById(R.id.tv_location_pickup_count);
        countDelivery = (TextView) findViewById(R.id.tv_location_delivery_count);

        countPickup.setOnClickListener(getShowNumberPickerListener());
        countDelivery.setOnClickListener(getShowNumberPickerListener());
    }

    private OnClickListener getShowNumberPickerListener() {
        return new OnClickListener() {
            @Override
            public void onClick(View view) {
                showNumberPickerDialog(view);
            }
        };
    }

    ...
}



回答3:


I fear you must inflate the view instead of finding it from nowhere. The method

findindViewById(int Id)

must be called within the Actvity's onCreate or with a view within which the child view/widget you are trying to find is resides in.

If all of the child views resides in a single xml file(within single parent root)

View rootView=(View) LayoutInflater.from(context).inflate(R.layout.list_item_location);
pickupContainer = (RelativeLayout) rootview.findViewById(R.id.rl_location_pickup_container);



回答4:


this should work

public LocationItem(Context context, AttributeSet attrs, int defStyle) {
   super(context, attrs, defStyle);
   this = inflate(getContext(), R.layout.list_item_location,null);
   ...



回答5:


you can try this. init views in the method onFinishInflate().This method will be called called as the last phase of inflation, after all child views have been added.So you can avoid NPE.



来源:https://stackoverflow.com/questions/30001062/findviewbyid-returns-null-in-custom-view-after-inflate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!