argetlam5
argetlam5

Reputation: 112

How to add an onClickListener to different items in a ListView row

So I'm making an app where one of the features is you are able to set alerts. Below are 2 example alerts that I used an adapter to put into a ListView. Each item has an ImageView, a TextView, and another ImageView.

enter image description here

My question is how would I turn on a onClickListener for the different images and maybe even the text depending how I do things.

For example, when you click the 'x' it will delete that alert from the list (showing me how to do and letting the adapter know a alert was deleted would be cool) or clicking the alert picture would activate/deactivate the alert (which would switch between the two images seen).

This screen comes to be by a MainActivity inflating an AlertFragment. In the past I've had problems with Fragments implementing inner classes but the way I have it set up now is (I think) with Fragments implementing inner classes. This is what I currently have which I know is wrong:

public class AlertsFragment extends Fragment {

    private ListView mListView;
    private List<Alert> alerts = new ArrayList<>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_alerts, container, false);

        mListView = (ListView) rootView.findViewById(R.id.alerts_list_view);

        alerts.add(new Alert(1, 5400, true));
        alerts.add(new Alert(2, 120, false));

        AlertsAdapter adapter = new AlertsAdapter(getActivity(), R.layout.alert_item_row, alerts);
        mListView.setAdapter(adapter);

        getActivity().setTitle(new AlertsItem().getLabel());

        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
                Log.d("matt", "list_item");
                ImageView img = (ImageView) getActivity().findViewById(R.id.active_image);
                img.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        Log.d("matt", "image");
                        alerts.get(position).setActive(!alerts.get(position).isActive());
                    }
                });
            }
        });
        return rootView;
    }
}

Any help you guys can give would be appreciated, thanks.

--------------------------------------------------------- EDIT ---------------------------------------------------------

As some have requested, here is my ArrayAdapter code:

/**
 * Adapter for adding Alerts to ListView
 */
public class AlertsAdapter extends ArrayAdapter {

    private int resource;
    List<Alert> objects;

    public AlertsAdapter(Context context, int resource, List<Alert> objects) {
        super(context, resource, objects);
        this.resource = resource;
        this.objects = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        AlertHolder holder = null;

        if (row == null) {
            LayoutInflater inflater = ((Activity)getContext()).getLayoutInflater();
            row = inflater.inflate(resource, parent, false);

            holder = new AlertHolder();
                holder.imgActive = (ImageView)row.findViewById(R.id.active_image);
            holder.txtTitle = (TextView)row.findViewById(R.id.txt_title);
            holder.txtTime = (TextView)row.findViewById(R.id.txt_time);

            row.setTag(holder);
        }
        else {
            holder = (AlertHolder)row.getTag();
        }

        Alert alert = (Alert) getItem(position);
        int image;
        if (alert.isActive()) {
            image = R.drawable.ic_alert_active_medium;
        }
        else {
            image = R.drawable.ic_alert_inactive_medium;
        }

        holder.imgActive.setImageResource(image);
        holder.txtTitle.setText("Route " + Integer.toString(alert.getRoute()));

        int min = alert.getTime() / 60;
        int hr = min / 60;
        min = min % 60;

        holder.txtTime.setText(((hr == 0) ? "" : (Integer.toString(hr) + " hr ")) + Integer.toString(min) + " min ");

        return row;
    }

    private static class AlertHolder {
        ImageView imgActive;
        TextView txtTitle;
        TextView txtTime;
    }
}

Upvotes: 3

Views: 3219

Answers (4)

jcroot
jcroot

Reputation: 5

I'm using in this snippet the same situation, when I clicked on the row, I save the position into my holder. I think you can use the same code, changing a little part of this code.

public class DeliveryAdapter extends ArrayAdapter<Delivery> {

    public DeliveryAdapter(Context context, List<Delivery> objects) {
        super(context, 0, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        ViewHolder holder;

        if (null == convertView) {
            holder = new ViewHolder();
            convertView = inflater.inflate(
                    R.layout.list_item_delivery,
                    parent,
                    false);

            holder.tvName = convertView.findViewById(R.id.tvName);
            holder.ivCheck = convertView.findViewById(R.id.ivCheck);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }

        Delivery item = getItem(position);

        holder.tvName.setText(item.getName());
        holder.ivCheck.setVisibility((item.isCheckVisible()) ? View.VISIBLE : View.GONE);
        holder.position = position;

        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ViewHolder viewHolder = (ViewHolder) view.getTag();
                for (int i = 0; i< getCount(); i++){
                    Delivery currentItem = getItem(i);
                    currentItem.setCheckVisible(viewHolder.position == i);
                }
                notifyDataSetChanged();
            }
        });

        return convertView;
    }

    public static class ViewHolder{
        public ImageView ivCheck;
        public TextView tvName;

        int position;

    }
}

Upvotes: 0

Jack
Jack

Reputation: 1855

You can handle this in onClick method.Example;

 public MyViewHolder(final View itemView) {
        super(itemView);

        iconImageView = (ImageView) itemView.findViewById(R.id.myRecyclerImageView);
        iconTextView = (TextView) itemView.findViewById(R.id.myRecyclerTextView);

        itemView.setOnClickListener(this);
        iconTextView.setOnClickListener(this);
        iconImageView.setOnLongClickListener(this);
    } 

    // onClick Listener for view 
    @Override 
    public void onClick(View v) {

        if (v.getId() == iconTextView.getId()){
            Toast.makeText(v.getContext(), "ITEM PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
        } else { 
            Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
        } 
    } 

Upvotes: 0

Keyur Android
Keyur Android

Reputation: 395

You have to manage click listener in AlertsAdapter class for separate views like x button, image.

Upvotes: 0

Jeffalee
Jeffalee

Reputation: 1085

Create your own Adapter which extends the ArrayAdapter (see this link), override the getView() method and in there you can add OnClickListeners to every View in the ListView's child. To notify the ListView a child is removed, call notifyDataSetChanged() on the ListView's Adapter.

You could solve this using the ListView, but I would suggest using the RecyclerView (Android RecyclerView). RecyclerView has better support for updating its children (like removing, inserting, updating children) and has default animations set.

Upvotes: 2

Related Questions