0

I have an Android ListView with a bunch of rows. Each row contains an image and some text. If I click on the image of a row, I want to perform action A, if I click on any other place in the row, I want to perform action B. Both of these actions need the id of the ListView item to work.

So far, for action B, I simply used listview's onItemClick, where I got the id from the parameter. However, as far as I know, the only way to find out on which view in the row itself the user clicked, is to add an onClick event handler to the ImageView that triggers action A. In that case, I only get the View that was clicked, though - not the id of the row that the ImageView is in.

My question is - how do I go from a View object to getting the id of the parent row within the ListView?

Max
  • 431
  • 1
  • 5
  • 13

5 Answers5

3

The onItemClickListener method has an onClick interface already with the view and position passed into it: You can get check which view has been clicked by doing a switch statement and performing a dedicated action when the specific view has been clicked.

E.g.

listView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
        String item = listView.getItemAtPosition(position);
        Toast.makeText(this,"You selected : " + item,Toast.LENGTH_SHORT).show();                
    }
});

as shown in How to create listview onItemclicklistener

You'll see that in the onItemClick interface it has the View view as a parameter and int position as a parameter, perform the action inside the listener using both of those parameters. Like i mentioned before you can use a switch statement.

listView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
            String item = listView.getItemAtPosition(position);
            switch(view.getId()) {
               case R.id.imageView:
                      //perform action for imageView using the data from Item (if you have used an MVC pattern)
               break;
               // you can do this for any widgets you wish to listen for click actions
            }           
        }
    });

Update: All credit for this goes to wwfloyd in How to know which view inside a specific ListView item that was clicked

@Override
public View getView(final int position, View convertView, final ViewGroup parent) {

    // Check if an existing view is being reused, otherwise inflate the view
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.one_line, parent, false);
    }

    // This chunk added to get textview click to register in Fragment's onItemClick()
    // Had to make position and parent 'final' in method definition
    convertView.findViewById(R.id.someName).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((ListView) parent).performItemClick(v, position, 0);
        }
    });
    // do stuff...
}

in your adapter apply a click listener to the element and then trigger the interface method, so that you can identify the registered widget that has been clicked and then in your onItemClick do:

public void onItemClick(AdapterView adapterView, View view, int position, long id) {
    long viewId = view.getId();
    switch (viewId) {
       case R.id.someName:
            //widget has been clicked
       break;

       default:
           //row has been clicked
       break;
    }
}
Community
  • 1
  • 1
Bradley Wilson
  • 1,197
  • 1
  • 13
  • 26
  • This was the first idea that came to my mind too, but unfortunately, the View that is passed as a parameter is not the actual UI element I clicked, but its parent - the RelativeLayout of the item row. – Max Mar 22 '17 at 11:51
  • That's very strange, you have no click logic on your parent elsewhere? – Bradley Wilson Mar 22 '17 at 11:54
  • No, I simply have a RelativeLayout that has an image view and a few text views. There is no onClick handler on any of the elements – Max Mar 22 '17 at 11:56
  • Oh thanks, that should work! How weird that you have to explicitly register the views to be clickable. – Max Mar 22 '17 at 12:15
  • Happy to help. It is strange, I would suggest using a RecyclerView with your own custom interface in the future, it gets the view that has been registered a listener rather than relying on the whole row. – Bradley Wilson Mar 22 '17 at 12:16
1
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1,
            int position, long id)

in this method View arg1 gives you Item view and you can find the item content by this arg1.findViewById(R.id.content);. Here position gives you the item position of list view

Aashutosh Kumar
  • 183
  • 4
  • 12
1

if you aren't using tag, then you can

int itemId=...;
OnClickListener customOnClick=...;
imageView.setTag(itemId);
imageView.setOnClickListener(customOnClick);

and inside your custom OnClickListener

int itemId = (Integer) view.getTag();

note that you can set "any" Object as tag, so you may even set your whole custom object, not only id

snachmsm
  • 17,866
  • 3
  • 32
  • 74
0

You can set click listeners for each view in a row from the getView() method in the adapter.

Alvin Varghese
  • 679
  • 2
  • 9
  • 17
0

You can impliment it in getView() method of adapter of listview.

R.R.M
  • 780
  • 4
  • 10