Can Poyrazoğlu
Can Poyrazoğlu

Reputation: 34780

findViewById not working for specific view

I have an activity loaded from XML, with views having IDs as usual:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="80dp"
    android:layout_height="110dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <FrameLayout
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/white_circle">

            <com.myapp.views.CircleImageView
                android:id="@+id/imageView"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </FrameLayout>

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="16dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="-12dp"
            android:background="@drawable/price_background">

            <TextView
                android:id="@+id/priceView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:text="0.1 BTC"
                android:textAllCaps="true"
                android:textColor="@color/white"
                android:textSize="10sp"
                android:textStyle="bold" />

        </FrameLayout>

        <TextView
            android:id="@+id/nameView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="2dp"
            android:gravity="center_horizontal"
            android:lineSpacingMultiplier="0.8"
            android:lines="2"
            android:text="Bacon Cheeseburger"
            android:textSize="10sp" />
    </LinearLayout>
</FrameLayout>

I'm trying to reference three views in code:

public ItemViewHolder(View itemView) {
    super(itemView);
    nameView = itemView.findViewById(R.id.nameView);
    priceView = itemView.findViewById(R.id.priceView);
    imageView = itemView.findViewById(R.id.imageView);
}

nameView and priceView are referenced correctly, however, imageView isn't being referenced and is null:

enter image description here

Why can't I reference imageView?

(If I traverse the view tree, it is there.)

UPDATE: I did both Clean Project and Invalidate Caches/Restart, the problem persists.

UPDATE 2: ItemViewHolder is derived from RecyclerView.ViewHolder. CircleImageView is derived from FrameLayout (not ImageView). This XML is the layout of my view holder.

UPDATE 3: Here is my circle view's constructor:

public class CircleImageView extends FrameLayout {

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

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

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

    ...
}

Also, as Subzero noted, I've checked the ID property (mID field) of the view, and it's -1, which seems to be the cause of the problem. I have no idea why it is -1 though.

Upvotes: 2

Views: 1952

Answers (3)

Languoguang
Languoguang

Reputation: 2224

I like Use this as follows, hope it is helpful.

public class CircleImageView extends FrameLayout {

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

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

    public CircleImageView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    ...
}

Upvotes: 1

Mike M.
Mike M.

Reputation: 39191

Change the super call in your two-parameter constructor to:

super(context, attrs);

When a View is inflated from a layout, the XML attributes and their values are passed into the two-parameter constructor via the AttributeSet. If you don't pass that to the superclass, the id you've specified in the XML is never set on the View, so findViewById() won't find it with the given ID.

Upvotes: 6

Theophrast
Theophrast

Reputation: 26

I think the problem is, that your imageView in layout.xml is a custom view (com.myapp.views.CircleImageView), not a regular android ImageView. Try cast to ImageView, if the class extends imageview

ImageView iv = (ImageView) itemView.findViewById(R.id.imageView));

or use it as your custom view

CircleImageView iv = (CircleImageView) itemView.findViewById(R.id.imageView));

Upvotes: 0

Related Questions