Search code examples
androidlistviewonclicklistener

How to avoid setting inline onClickListner in getView()


I have got ListView with a custom Adapter. Every row contains clickable buttons and texts.

At the moment onClickListeners are set in the body of getView(), this is quite insane idea because this method is called very frequently. Inside every onClick function, I need access to the private data to call new activity with the bundle.

How can I move the onClick definition outside getView() routine?

When onClick will be called I need info about the position of the list element (to access private data) and which View was clicked (to start the correct Activity).

public View getView(int position, View convertView, ViewGroup parent) {
    if(convertview == null) {
        convertView = ((Activity) getContext()).getLayoutInflater().inflate(R.layout.photo_tweet_row, null);
    }

    TextView userTweet = (TextView) v.findViewById(R.id.feed_user_tweet_body);
    RepliesButton repliesBtn = (RepliesButton) v.findViewById(R.id.feed_replies_button);

    Status twitterDataItem = getItem(position);

    if (twitterDataItem != null) {

        if (userTweet != null) {
            userTweet.setText(twitterDataItem.getText());
        }
        if (repliesBtn != null) {
            repliesBtn.setText(" replies");
        }
        
        userTweet.setOnClickListener(new View.OnClickListener() {           
            @Override
            public void onClick(View v) {                    
              Intent intent = new Intent(getContext(), ProfileActivity.class); 
              intent.putExtra(getContext().getString(R.string.serializable_user), twitterDataItem.getUser());
              getContext().startActivity(intent);
            }
        });
        
        repliesBtn.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                if (!twitterDataItem.getComments().contentEquals("0")) {
                    Intent myIntent = new Intent(getContext(), RepliesToFeedActivity.class);
                    myIntent.putExtra("photoTweet", twitterDataItem);
                    getContext().startActivity(myIntent);
                }
            }
        });
    }
    return convertView;
}

Solution

  • Your activitiy has to implement the OnClickListener, and move the implemented method up to the activity level.

    Based on the view parameter of the method you are able to detect from which UI object the event came from (button, textview).

    As for how to detect for which record/row in a listview. You have to set a custom tag on the buttons and textviews in the getView method, that you will read in the event via getTag this tag can be a custom object too if string is not enough. Probably/recommended way is to be the position in the adapter.