Ben
Ben

Reputation: 767

Custom list adapter onClick method returning a null view id

In creating a custom list adapter to be able to click different elements in a single row entry and start different activities, I ran across a problem where my findViewById() method was returning null. Additionally, only the first item in my ListView calls the onClick method; the other rows don't register clicks.

public class CustomListAdapter extends SimpleAdapter implements View.OnClickListener {

Context context;
TextView habitId;
Intent intent;

public CustomListAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
    super(context, data, resource, from, to);
    this.context = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;

    if (v == null) {
        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.habit_entry, null);
    }

    TextView tv = (TextView) v.findViewById(R.id.habitTitle);
    tv.setOnClickListener(this);

    ImageView iv = (ImageView) v.findViewById(R.id.plus);
    iv.setOnClickListener(this);

    return super.getView(position, convertView, parent);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.habitTitle:
            Log.d("Test", "habitid = " + v.findViewById(R.id.habitId));
            break;
        case R.id.plus:
            Log.d("Test", "plus clicked");
        default:
            break;
    }
}

When the code is run, the habitTitle case of onClick prints

D/NULL: habitid = null

habit_entry

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"
    android:src="@drawable/ic_plus"
    android:id="@+id/plus"
    android:scaleType="centerCrop"
    android:paddingRight="20dp"
    android:paddingLeft="20dp"
    android:background="#9bfcff" />

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="New Text"
    android:id="@+id/habitId"
    android:visibility="gone" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="difficulty"
    android:id="@+id/habitDifficulty"
    android:gravity="right"
    android:paddingLeft="15dp"
    android:layout_alignParentBottom="true"
    android:layout_alignRight="@+id/habitTitle"
    android:layout_alignEnd="@+id/habitTitle"
    android:layout_marginRight="30dp"
    android:layout_marginEnd="30dp" />

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@id/plus"
    android:layout_above="@id/habitDifficulty"
    android:layout_alignWithParentIfMissing="true"
    android:text="Your new habits go here!"
    android:id="@+id/habitTitle"
    android:padding="5dp"
    android:textColor="#444444"
    android:textSize="20sp"
    android:textStyle="bold"
    android:layout_alignParentStart="false"
    android:gravity="right"
    android:allowUndo="true" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:text="frequency"
    android:id="@+id/habitFrequency"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" />


</RelativeLayout>

call in MainActivity

if(habitList.size() != 0) {
        ListView listView = (ListView) findViewById(android.R.id.list);

        ListAdapter adapter = new CustomListAdapter(
                this, habitList, R.layout.habit_entry, new String[]{"habitId", "title", "difficulty", "frequency"}, new int[]{
                R.id.habitId, R.id.habitTitle, R.id.habitDifficulty, R.id.habitFrequency});

        listView.setAdapter(adapter);
    }

The list populates perfectly, so I'm not sure why I'm having so much trouble with my adapter.

Upvotes: 2

Views: 439

Answers (2)

George Mulligan
George Mulligan

Reputation: 11903

I see a couple problems here. You are inflating the View yourself and then returning the View returned by calling super.getView(position, convertView, parent);. You should instead rely on super.getView(position, convertView, parent); to create the View for you since you are using the default implementation like this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = super.getView(position, convertView, parent);

    v.findViewById(R.id.habitTitle)
            .setOnClickListener(this);

    v.findViewById(R.id.plus)
            .setOnClickListener(this);

    return v;
}

Also v.findViewById(R.id.habitId)); is returning null inside onClick() because the variable v itself is the TextView with id = R.id.habitId.

Upvotes: 1

Rockney
Rockney

Reputation: 10650

You set the visibility of the habitId textview to gone. The textview will not be inflated and is null. You can read more information about visibility in the android documentation

Upvotes: 0

Related Questions