简体   繁体   中英

listview toggle switch works only last row

i'm facing a problem which is, when i toggle switch it's works for only last item of listview. It doesn't matter which switch i toggle. I research other asked questions but i couldn't figure it out.

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View customView = inflater.inflate(R.layout.row, parent, false);
    String allData = getItem(position);


    final Switch status = (Switch) customView.findViewById(R.id.switchStatus);


    status.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            Toast.makeText(getContext(),"selectid",Toast.LENGTH_LONG).show();

        }
    });

    return customView;

}

You can see my adapter activiy in here.

public class adapter_test extends ArrayAdapter<String> {



    public adapter_allservicerecords(Context context, String[] data){
        super(context, R.layout.row, data);
    }

    @Override
public View getView(int position, View convertView, ViewGroup parent)
{
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View customView = inflater.inflate(R.layout.row, parent, false);
    String allData = getItem(position);



        try {
            if(!all_data.isEmpty()) {
                JSONObject jsonRowData = new JSONObject(all_data);
                try {
                    text.setText(jsonRowData.getString("TITLE"));


                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            Log.e("FAILED", "Json parsing error: " + e.getMessage());
        }

    return customView;

    }
}

The solution to the problem is you have to instead of making your data as a String, you should instead change it into something that would represent each row.

For example you can set this class to represent your row:

class Item {
    String data;
    boolean toggled;

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

    public void setToggled(boolean toggle) {
        toggled = toggle;
    }
}

Your data source now must not be Strings, so you should instead have your List as List and you can easily add your strings to the list by passing on new Item("THE STRING DATA HERE"); when adding data to the list. So instead of

String allData = getItem(position); 

you would use

Item item = getItem(position);

then on the getView would look something like this:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View customView = inflater.inflate(R.layout.row, parent, false);
    Item item = getItem(position);


    final Switch status = (Switch) customView.findViewById(R.id.switchStatus);

    status.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            // here we change the value of the item which is referring to the specific index in the array returned by getItems()
            item.setToggled(isChecked);
            Toast.makeText(getContext(),"selectid",Toast.LENGTH_LONG).show();

        }
    });

    // here we get what the latest value of the switch is
    status.setChecked(item.toggled);
    return customView;

}

Make sure you also change your data source into a data structure/list that represents somewhat like List or anything similar on which you decide to use.

BONUS TIP: It is recommended to use a ViewHolder to hold your View and for efficient recycling of instances.

class ViewHolder {
    Switch statusSwitch;
    View customView;
}

Then to use that in the getView() part you can easily. You actually don't have to create a new instance of the view since convertView or the second parameter of the method represents the view that could be reused or instantiated if null.

Heterogeneous lists can specify their number of view types, so that this View is always of the right type, so you are recommended to use that.

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

    LayoutInflater inflater = LayoutInflater.from(getContext());
    ViewHolder holder = null;
    Item item = getItem(position);
    if (convertView == null) { // instantiate if not yet instantiated
        convertView = inflater.inflate(R.layout.supplies_list_item, null);
        holder.statusSwitch = (Switch) convertView.findViewById(R.id.switchStatus);
    }
    else {
        holder = (ViewHolder) convertView.getTag();
    }
    // you could set the values/ listeners  here
    holder.statusSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            item.setToggled(isChecked);
            Toast.makeText(getContext(),"selectid",Toast.LENGTH_LONG).show();

        }
    });
    holder.statusSwitch.setChecked(item.toggled);

    return convertView;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM