0

The title for this question might be poor, but but it was hard to nail down a title. So here is the question.

I have an application that opens a database and creates a custom ListView based on the contents. So there are a few files involved in this process:

Main.java - opens the database and stores the List<MyClass> of contents
main.xml - main activity layout with the ListView
MyAdapter.java - extends BaseAdapter and calls MyAdapterView based on the context
MyAdapaterView.java - inflates the View from MyAdapater based on row.xml
row.xml - layout of each custom row of the ListView

This works fine. I am new to Android, but structurally this seems to be how everyone recommends building custom ListViews.

How do I retrieve data from the ListView? For instance, part of the row is a checkbox. If the user presses the checkbox to activate/deactivate the particular row, how do I notify the main application about that?

Thanks,

EDIT:

Main.java

public class MyApplication extends Activity 
    implements OnItemClickListener, OnItemLongClickListener
{
    private List<MyClass> objects;
    private ListView lvObjects;
    private MyAdapter myAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        objects = new ArrayList<MyClass>(); // setup the list
        lvObjects = (ListView)findViewById(R.id.lvObjectList);
        lvObjects.setOnItemClickListener(this);
        lvObjects.setOnItemLongClickListener(this);

        loadDatabase(DATABASE);

        myAdapter = new MyAdapter(this, objects);
        lvObjects.setAdapter(myAdapter); 
    }

    ...

    public void onItemClick(AdapterView<?> parent, View v, int position, long id) 
    {       
        // This is executed when an item in the ListView is short pressed
    }

    public void onItemLongClick(AdapterView<?> parent, View v, int position, long id) 
    {
        // This is executed when an item in the ListView is long pressed

        registerForContextMenu(lvObjects);
        v.showContextMenu();
    }

MyAdapter.java

public class MyAdapter extends BaseAdapter
{
    private Context context;
    private List<MyClass> list;

    public RuleAdapter(Context context, List<MyClass> list)
    {
        this.context = context;
        this.list = list;
    }

    ...

    public View getView(int position, View view, ViewGroup viewGroup) 
    {
        MyClass entry = list.get(position);
        return new MyAdapterView(context,entry);
    }
}

MyAdapterView.java

public class MyAdapterView extends LinearLayout
{   
    public MyAdapterView(Context context, MyClass entry) 
    {
        super(context);

        this.setOrientation(VERTICAL);
        this.setTag(entry);

        View v = inflate(context, R.layout.row, null);

        // Set fields based on entry object

        // When this box is checked or unchecked, a message needs to go
        // back to Main.java so the database can be updated
        CheckBox cbActive = (CheckBox)v.findViewById(R.id.cbActive);

        addView(v);
    }
}
linsek
  • 3,334
  • 9
  • 42
  • 55

2 Answers2

1

How do I retrieve data from the ListView?

If you want to know which item in the ListView was clicked, you use an OnItemClickListener and Listview.setOnItemClickListener. There's an example of this in the Hello ListView tutorial.

Once you know which item is selected, you then know the position of that item in the overall Adapter, and you have the View. You can use the View to get sub-elements if needed, generally though the position is enough to let you know what part of your "model" was clicked. In your example it would tell you exactly which item in your List<MyClass> was clicked.

If you want to distinguish between the list item being clicked, and a focusable view in the list item (like a checkbox), then that's a little more involved. The checkbox, by default, will hikack the focus from the list item. You can toggle this though and make it false, depending on what you're trying to do. See this question for more info.

If you need to distinguish between the ListView item click and the CheckBox click, there are several ways. One way is to just maintain the state of whether or not an item is clicked inside the adapter.

For example:

MovieAdapter

MyMovies (ListView)

Then you just use the normal "onListItemClick" and the adapter to tell what is clicked and what isn't. (This is just one way to do this, there are several.)

Community
  • 1
  • 1
Charlie Collins
  • 8,806
  • 4
  • 32
  • 41
  • Right, the CheckBox takes the focus of the ListView row so in the XML file I set the CheckBox to `android:focusable="false"`. This works and allows me to listen to the ListViews short and long clicks. But now, how do I listen for both the CheckBox and the row? When the row is pressed a ContextMenu pops up which works appropriately. But when the CheckBox is either checked or unchecked, I need to send a message back to the application to update the database. How do I do that without the `onClickListener` being activated? – linsek Dec 10 '10 at 19:37
  • I updated the answer with one example I've worked on recently. I am not sure it's exactly what you're asking, but it uses checkbox in listview and should get you going in the right direction (maybe). – Charlie Collins Dec 10 '10 at 19:51
  • @Charlie - I updated my post with the main application. I did look through the example you referenced, but I'm not entirely sure that is what I am looking for. The problem is I need three different processes to take place. 1- When the ListView row is short pressed, perform some execution. 2- When the ListView row is long pressed, pull up a context menu. 3- When the CheckBox in the row is either checked or unchecked, update the database that this object is either going to be active, or inactive. I am already implementing onItemClick and onItemLongClick to satisfy the first two. – linsek Dec 10 '10 at 20:18
  • cont. so how do I add a third listener that is linked to the CheckBox in the row? – linsek Dec 10 '10 at 20:19
  • There are multiple ways. You can get the state of the checkbox from the "View" the onItemClick returns, something like ((CheckBox) view.findViewById(R.whatever_checkbox_id)), or, and I find this more elegant, you can just keep track of that state in the Adapter. That's what the example I included does. It maintains the state of whether or not something is checked in the adapter (and there it can be retrieved in onItemClick too, or it can just do the "update the database" part itself. – Charlie Collins Dec 10 '10 at 20:31
  • See the MovieAdapter "isInCollection" method. You could call that whatever you want, "isChecked" for example. And then, in onItemClick, you have the position, just call adapter.isChecked -- and based on that state do whatever "update the database" you need. Also keep in mind all the database stuff should be in a separate Thread (AsyncTask), but that's a different matter ;). – Charlie Collins Dec 10 '10 at 20:33
  • I actually took a different approach. I had never seen CheckedTextView before until I looked at your examples. So I implemented that and was able to get it working good. The only glitch was for some reason, if I have text with the CheckedTextView, the text seems to 'blink' when I press the CTV... unsure what that is. – linsek Dec 14 '10 at 01:51
0

So you have a custom cursoradapter that creates the views? When you create the view in getView(), just set up a listener on that view to listen for whatever you want. Probably onClick

Falmarri
  • 47,727
  • 41
  • 151
  • 191
  • No, it is not a CursorAdapter. Could you explain how to setup a listener in getView()? I've edited the post to contain my Adapter and AdapterView. Thanks – linsek Dec 10 '10 at 18:05