Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listview and CustomAdapter extending SimpleCursorAdapter

I wish to manipulate background colors of selected row in my ListView which from reading I need to extend with a CustomAdapter. My main adapter is of the type SimpleCursorAdapter so I have modified a CustomAdapter that extended ArrayAdapter to SimpleCursorAdapter.

My problem is that the listview is blank when using the CustomAdapter but if do not extend and use the SimpleCursorAdapter the listview has rows / items. Logcat shows a problem in my CustomAdapter see below.

This is my main activity code:

phrasesdb helper = new phrasesdb(this);
database = helper.getWritableDatabase();
data = database.query("phrases", fields, null, null, null, null, fields[0] + " COLLATE NOCASE ASC");
//WORKING SimpleCursorAdapter
//dataSource = new SimpleCursorAdapter(this, R.layout.phrases, data, fields, new int[] { R.id.phrase });

//NOT WORKING
dataSource = new CustomAdapter(this, R.layout.phrases, data, fields, new int[] { R.id.phrase });

view = getListView();
setListAdapter(dataSource);

This is the Custom Adapter class and I have marked the position where logcat errors:

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

public class CustomAdapter extends SimpleCursorAdapter {

protected static final int NO_SELECTED_COLOR = 0xFF191919;
protected static final int SELECTED_COLOR = 0xFF3366CC;

Cursor items;
private LayoutInflater mInflater;
private int viewResourceId;
private int selectedPosition;


public CustomAdapter(Context context, int resourceId, Cursor data, String[] fields, int[] is) {
    super(context, resourceId, data, fields, is);
    mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    viewResourceId = resourceId;
    items = data;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
    TextView tv = (TextView)convertView;
    if (tv == null) {
  //WHEN DEBUGGING THIS IS WHERE LOGCAT ERROR MESSAGES STARTS
        tv = (TextView)mInflater.inflate(viewResourceId, null);
    }
    tv.setText(items.getString(position));



    // Change the background color
    if (position==selectedPosition) tv.setBackgroundColor(SELECTED_COLOR);
    else tv.setBackgroundColor(NO_SELECTED_COLOR);

    return tv;
}

public void setSelected(int position) {
    selectedPosition = position;
}
}

And this is LogCat:

10-18 13:33:17.869: E/ListView(28378): android.widget.LinearLayout 10-18 13:33:17.869: E/ListView(28378): java.lang.ClassCastException: android.widget.LinearLayout 10-18 13:33:17.869: E/ListView(28378): at com.xxx.xxx.CustomAdapter.getView(CustomAdapter.java:49) 10-18 13:33:17.869: E/ListView(28378): at android.widget.AbsListView.obtainView(AbsListView.java:1449) 10-18 13:33:17.869: E/ListView(28378): at android.widget.ListView.makeAndAddView(ListView.java:1801) 10-18 13:33:17.869: E/ListView(28378): at android.widget.ListView.fillSpecific(ListView.java:1339) 10-18 13:33:17.869: E/ListView(28378): at android.widget.ListView.layoutChildren(ListView.java:1637) 10-18 13:33:17.869: E/ListView(28378): at android.widget.AbsListView.onLayout(AbsListView.java:1279) 10-18 13:33:17.869: E/ListView(28378): at android.view.View.layout(View.java:7321) 10-18 13:33:17.869: E/ListView(28378): at android.widget.FrameLayout.onLayout(FrameLayout.java:338) 10-18 13:33:17.869: E/ListView(28378): at android.view.View.layout(View.java:7321) 10-18 13:33:17.869: E/ListView(28378): at android.widget.FrameLayout.onLayout(FrameLayout.java:338) 10-18 13:33:17.869: E/ListView(28378): at android.view.View.layout(View.java:7321) 10-18 13:33:17.869: E/ListView(28378): at android.view.ViewRoot.performTraversals(ViewRoot.java:1217) 10-18 13:33:17.869: E/ListView(28378): at android.view.ViewRoot.handleMessage(ViewRoot.java:1991) 10-18 13:33:17.869: E/ListView(28378): at android.os.Handler.dispatchMessage(Handler.java:99) 10-18 13:33:17.869: E/ListView(28378): at android.os.Looper.loop(Looper.java:150) 10-18 13:33:17.869: E/ListView(28378): at android.app.ActivityThread.main(ActivityThread.java:4385) 10-18 13:33:17.869: E/ListView(28378): at java.lang.reflect.Method.invokeNative(Native Method) 10-18 13:33:17.869: E/ListView(28378): at java.lang.reflect.Method.invoke(Method.java:507) 10-18 13:33:17.869: E/ListView(28378): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849) 10-18 13:33:17.869: E/ListView(28378): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607) 10-18 13:33:17.869: E/ListView(28378): at dalvik.system.NativeStart.main(Native Method)

This is the layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/rowLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal">
<TextView
android:id="@+id/phrase" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_marginLeft="2dp" 
android:layout_marginRight="2dp" 
android:focusable="false" 
android:focusableInTouchMode="false" 
android:text="@string/wordforphrases"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="visible"/>

</LinearLayout>

Logcat is indicating something to do with LinearLayout but I cannot figure out where I have gone wrong.

Please would anyone be able to piont me in the right direction?

thanks Mark

Update: After changing to match inflate as per Sardor's idea (thankyou):

tv = (TextView)mInflater.inflate(viewResourceId, parent);

I now get this error

10-18 15:23:22.083: E/ListView(28931): addView(View, LayoutParams) is not supported in AdapterView
10-18 15:23:22.083: E/ListView(28931): java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView
10-18 15:23:22.083: E/ListView(28931):  at android.widget.AdapterView.addView(AdapterView.java:461)
10-18 15:23:22.083: E/ListView(28931):  at android.view.LayoutInflater.inflate(LayoutInflater.java:416)
10-18 15:23:22.083: E/ListView(28931):  at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
10-18 15:23:22.083: E/ListView(28931):  at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
10-18 15:23:22.083: E/ListView(28931):  at com.xxx.xxx.CustomAdapter.getView(CustomAdapter.java:36)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.AbsListView.obtainView(AbsListView.java:1449)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.ListView.makeAndAddView(ListView.java:1801)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.ListView.fillSpecific(ListView.java:1339)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.ListView.layoutChildren(ListView.java:1637)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.AbsListView.onLayout(AbsListView.java:1279)
10-18 15:23:22.083: E/ListView(28931):  at android.view.View.layout(View.java:7321)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-18 15:23:22.083: E/ListView(28931):  at android.view.View.layout(View.java:7321)
10-18 15:23:22.083: E/ListView(28931):  at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-18 15:23:22.083: E/ListView(28931):  at android.view.View.layout(View.java:7321)
10-18 15:23:22.083: E/ListView(28931):  at android.view.ViewRoot.performTraversals(ViewRoot.java:1217)
10-18 15:23:22.083: E/ListView(28931):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1991)
10-18 15:23:22.083: E/ListView(28931):  at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 15:23:22.083: E/ListView(28931):  at android.os.Looper.loop(Looper.java:150)
10-18 15:23:22.083: E/ListView(28931):  at android.app.ActivityThread.main(ActivityThread.java:4385)
10-18 15:23:22.083: E/ListView(28931):  at java.lang.reflect.Method.invokeNative(Native Method)
10-18 15:23:22.083: E/ListView(28931):  at java.lang.reflect.Method.invoke(Method.java:507)
10-18 15:23:22.083: E/ListView(28931):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
10-18 15:23:22.083: E/ListView(28931):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
10-18 15:23:22.083: E/ListView(28931):  at dalvik.system.NativeStart.main(Native Method)
10-18 15:23:22.093: D/View(28931): onTouchEvent: viewFlags: 0x18244001

When checking parent it is seeing the TextView.

Any other thoughts please?

like image 697
Mark Avatar asked Oct 18 '12 13:10

Mark


People also ask

What is list view?

A list view is an adapter view that does not know the details, such as type and contents, of the views it contains. Instead list view requests views on demand from a ListAdapter as needed, such as to display new views as the user scrolls up or down. In order to display items in the list, call setAdapter(android.

How to update ListView item in android?

Android App Development for Beginners This example demonstrates how do I dynamically update a ListView in android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.


1 Answers

Okay I finally got it to work...

The issue here is that if your custom adapters data is from a Cursor then you must use bindView and newView in the extended SimpleCursorAdapter class instead of getView.

I'll post my working code for anyone else who may come across this issue...

public class CustomAdapter extends SimpleCursorAdapter {

private int mSelectedPosition;
Cursor items;
private Context context;
private int layout;

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    Cursor c = getCursor();

    final LayoutInflater inflater = LayoutInflater.from(context);
    View v = inflater.inflate(layout, parent, false);

    int nameCol = c.getColumnIndex("phrase");
    String name = c.getString(nameCol);

    TextView name_text = (TextView) v.findViewById(R.id.phrase);
    if (name_text != null) {
        name_text.setText(name);
    }
    return v;
}


public CustomAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
    super(context, layout, c, from, to);
    this.context = context;
    this.layout = layout;
}


@Override
public void bindView(View v, Context context, Cursor c) {

    int nameCol = c.getColumnIndex("phrase");
    String name = c.getString(nameCol);


    TextView name_text = (TextView) v.findViewById(R.id.phrase);
    if (name_text != null) {
        name_text.setText(name);
    }

    //name_text.setTextColor(Color.GREEN);

    int position = c.getPosition(); 
    if (mSelectedPosition == position) {
       v.setBackgroundResource(R.drawable.listviewbackground);
       v.getBackground().setDither(true);
    } else {
       v.setBackgroundColor(Color.BLACK);
    }

}


public void setSelectedPosition(int position) {
    mSelectedPosition = position;
    notifyDataSetChanged();

}

And

  Cursor data;
  static final String fields[] = { "phrase", BaseColumns._ID };

  dataSource = new CustomAdapter(this, R.layout.phrases, data, fields, new int[] { R.id.phrase });
  view = getListView();
  setListAdapter(dataSource);
like image 191
Mark Avatar answered Nov 02 '22 10:11

Mark