Skip to main content

Android: How to fire onListItemClick in Listactivity with buttons in list?



I have a simple ListActivity that uses a custom ListAdapter to generate the views in the list. Normally the ListAdapter would just fill the views with TextViews, but now I want to put a button there as well.





It is my understanding and experience however that putting a focusable view in the list item prevents the firing of onListItemClick() in the ListActivity when the list item is clicked. The button still functions normally within the list item, but when something besides the button is pressed, I want onListItemClick to be triggered.





How can I make this work?


Comments

  1. I hope I can help here. I assume that you have custom layout for listView items, and this layout consists of button and some other views - like TextView, ImageView or whatever. Now you want to have different event fired on button click and different event fired on everything else clicked.

    You can achieve that without using onListItemClick() of your ListActivity. Here is what you have to do:

    You are using custom layout, so probably you are overriding getView() method from your custom adapter. The trick is to set the different listeners for your button and different for the whole view (your row). Take a look at the example:





    private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
    List<String> objects) {
    super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    String text = getItem(position);
    if (null == convertView) {
    convertView = mInflater.inflate(R.layout.custom_row, null);
    }
    //take the Button and set listener. It will be invoked when you click the button.
    Button btn = (Button) convertView.findViewById(R.id.button);
    btn.setOnClickListener(this);
    //set the text... not important
    TextView tv = (TextView) convertView.findViewById(R.id.text);
    tv.setText(text);
    //!!! and this is the most important part: you are settin listener for the whole row
    convertView.setOnClickListener(new OnItemClickListener(position));
    return convertView;
    }

    @Override
    public void onClick(View v) {
    Log.v(TAG, "Row button clicked");
    }
    }




    Your OnItemClickListener class could be declared like here:


    private class OnItemClickListener implements OnClickListener{
    private int mPosition;
    OnItemClickListener(int position){
    mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
    Log.v(TAG, "onItemClick at position" + mPosition);
    }
    }


    Of course you will probably add some more parameters to OnItemClickListener constructor. And one important thing - implementation of getView shown above is pretty ugly, normally you should use ViewHolder pattern to avoid findViewById calls.. but you probably already know that.
    My custom_row.xml file is RelativeLayout with Button of id "button", TextView of id "text" and ImageView of id "image" - just to make things clear.
    Regards!

    ReplyDelete
  2. When a custom ListView contains focusable elements, onListItemClick won't work (I think it's the expected behavior). Just remove the focus from the custom view, it will do the trick:

    For example:

    public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
    super(context);

    mText.setFocusable(false);
    mText.setFocusableInTouchMode(false);

    mCheckBox.setFocusable(false);
    mCheckBox.setFocusableInTouchMode(false);

    }
    }

    ReplyDelete
  3. I have the same problem: OnListItemClick not fired ! [SOLVED]
    That's happen on class that extend ListActivity,
    with a layout for ListActivity that content TextBox and ListView nested into LinearLayout
    and another layout for the rows (a CheckBox and TextBox nested into LineraLayout).

    That's code:

    res/layout/configpage.xml (main for ListActivity)

    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <TextView
    android:id="@+id/selection"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="pippo" />
    <ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:drawSelectorOnTop="false"
    android:background="#aaFFaa" >
    </ListView>
    <LinearLayout>

    res/layout/row.xml (layout for single row)
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <CheckBox
    android:id="@+id/img"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    **android:focusable="false"**
    **android:focusableInTouchMode="false"** />

    <TextView
    android:id="@+id/testo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    **android:focusable="false"**
    **android:focusableInTouchMode="false"** />
    </LinearLayout>


    src/.../.../ConfigPage.java

    public class ConfigPage extends ListActivity
    {
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.configpage);
    // loaded from res/value/strings
    String[] azioni = getResources().getStringArray(R.array.ACTIONS);
    setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row,
    R.id.testo, azioni));
    selection = (TextView) findViewById(R.id.selection);
    }

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
    selection.setText(" " + position);
    }
    }


    This begin to work when I added on row.xml


    android:focusable="false"
    android:focusableInTouchMode="false"


    I use Eclipse 3.5.2
    Android SDK 10.0.1
    min SDK version: 3

    I hope this is helpful
    ... and sorry for my english :(

    ReplyDelete
  4. I've had the same problem with ToggleButton. After half a day of banging my head against a wall I finally solved it.
    It's as simple as making the focusable view un-focusable, using 'android:focusable'. You should also avoid playing with the focusability and clickability (I just made up words) of the list row, just leave them with the default value.

    Of course, now that your focusable views in the list row are un-focusable, users using the keyboard might have problems, well, focusing them. It's not likely to be a problem, but just in case you want to write 100% flawless apps, you could use the onItemSelected event to make the elements of the selected row focusable and the elements of the previously selected row un-focusable.

    ReplyDelete
  5. ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    lv.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
    // When clicked, show a toast with the TextView text
    Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
    Toast.LENGTH_SHORT).show();
    }
    });

    ReplyDelete
  6. You wrote those lines:

    convertView = mInflater.inflate(R.layout.custom_row, null);
    }
    //take the Button and set listener. It will be invoked when you click the button.
    Button btn = (Button) convertView.findViewById(R.id.button);
    btn.setOnClickListener(this);
    //set the text... not important
    ...


    Who is "this" in that line?

    btn.setOnClickListener(this);


    this must be replaces with some listener.

    ReplyDelete
  7. you can refer to the following tutorial:

    http://www.codegod.de/WebAppCodeGod/Android-ImageButtons-in-ListView-with-RelativeLayout-AID589.aspx

    Bye!

    ReplyDelete
  8. i used the getListAdapter().getItem(position) instantiating an Object that holds my values within the item

    MyPojo myPojo = getListAdapter().getItem(position);

    then used the getter method from the myPojo it will call its proper values within the item .

    ReplyDelete
  9. 'this' is in the implementation modifier and the onClick() override

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex