aletede91
aletede91

Reputation: 1166

ListView modify other view from specific view

I have a ListView that contains 5 rows with 5 button:

enter image description here

When I click on first button, I replace it text with "B".

enter image description here

Then, I click on second button, I replace it text with "B", but how can I replace the previous clicked button (the first) with "A"?

enter image description here

This is what really happen:

enter image description here

This is my code for the button click:

private int resource;
private LayoutInflater inflater;
ViewHolder holder;
private Context ctx;
public RingtoneAdapter(Context context, int resourceId, List<Ringtone> objects) {
    super(context, resourceId, objects);
    this.ctx = context;
    resource = resourceId;
    inflater = LayoutInflater.from(context);
}
public View getView(final int position, View v, ViewGroup parent) {

    // Recuperiamo l'oggetti che dobbiamo inserire a questa posizione
    final Ringtone ringtone = getItem(position);

    if (v == null) {
        v = inflater.inflate(resource, parent, false);
        holder = new ViewHolder();
        holder.btnPlay = (Button) v.findViewById(R.id.btnPlay);
        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }

    holder.btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            Button btnadd = (Button) view;
            btnadd.setText("B");
            notifyDataSetChanged();

        }
    });

    return v;
}
private static class ViewHolder {
    Button btnPlay;
    TextView txtTitolo;
    TextView txtCategoria;
}

Upvotes: 2

Views: 130

Answers (2)

Pankaj Nimgade
Pankaj Nimgade

Reputation: 4549

you need to reset the items which were not clicked,

 btn.setText("B"); // if the item was clicked

 btn.setText("A"); // for all other items 

what you can do is, cycle through all elements setting the text for button like this btn.setText("A"), once this is done call btn.setText("B")

you should be using OnItemClickListener on the listview, it is easy that way, as you are setting the value in view holder, it does not give you access to the other items in the listview, but by using OnItemClickListener you can cover all the elements in the listview once you update things as you like call notifyDataSetChanged(), As this can be done there is another way to look at the problem

    ListView listView = (ListView) findViewById(R.id.ListViewTestSevenActivity_listView);
    ArrayList<Item> items = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        Item item = new Item("A");
        items.add(item);
    }
    MyAdapter adapter = new MyAdapter(getApplicationContext(), R.layout.simple_list_item_1, items);
    listView.setAdapter(adapter);

This will take care of initialization and rest of the code as you want it to work. code is also available on github

private class MyAdapter extends ArrayAdapter {

    private Context a_context;
    private ArrayList<Item> items;
    private LayoutInflater a_layoutInflater;

    public MyAdapter(Context context, int resource, ArrayList<Item> items) {
        super(context, resource, items);
        this.a_context = context;
        this.items = items;
        a_layoutInflater = LayoutInflater.from(this.a_context);
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View row = convertView;
        ViewHolder holder = null;
        if (row == null) {
            row = a_layoutInflater.inflate(R.layout.single_item_listview_seven, parent, false);
            holder = new ViewHolder();
            holder.button = (Button) row.findViewById(R.id.ListViewTestSevenActivity_text_button);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }

        final Item item = items.get(position);
        System.out.println("" + item.getText());

        holder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for (Item current_item : items) {
                    current_item.setText("A");
                }
                item.setText("B");
                notifyDataSetChanged();
            }
        });
        holder.button.setText("" + item.getText());
        return row;
    }

    private class ViewHolder {
        Button button;
    }
}

private class Item {
    String text;

    public Item(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

Upvotes: 0

Cruceo
Cruceo

Reputation: 6834

If I'm reading this correctly, you only want a single position to be 'selected' at a time. If that's the case, you could keep a reference to the selected position, and use the Adapter's functionality instead of having multiple buttons know about each other. e.g.

private int selectedPosition = -1;

@Override
public View getView(final int position, View convertView, ViewGroup parent){
    // ... Your ViewHolder / Ringtone initialization

    if(position == selectedPosition)
        holder.btnPlay.setText("B");
    else holder.btnPlay.setText("A");

    holder.btnPlay.setOnClickListener(new View.OnClickListener(){
        if(holder.btnPlay.getText().toString().equals("A")) 
            selectedPosition = position;
        else selectedPosition = -1;

        notifyDataSetChanged();
    });

    return convertView;
}

The key here is allowing notifyDataSetChanged() to internally call your getView method, which then really only needs to know how to render the data in its current state, instead of dealing with the complex logic required to map between multiple Views.

Upvotes: 1

Related Questions