简体   繁体   中英

Getting Switch state in ListView

in my Application I want the user to make multiple choices and for this i present some Switch in a ListView and a button to confirm.

The problem is, when I inserted the values in db in the Button onClickListener() function, i can retrieve from the switches the text, but not the state of them (in the example, always output true)

btn.setOnClickListener( new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            ListAdapter adapter = list.getAdapter();
            MyDatabase db = new MyDatabase(cntx);
            db.open();
            for(int n=0;n<adapter.getCount();n++)
            {
                View rowview = adapter.getView(n, null, null);
                Switch swtc = (Switch) rowview.findViewById(R.id.switch1);
                String[] args = {(String)swtc.getText()};
                if(swtc.isChecked())
                {
                    Log.i("update", args[0]+" going to be true");
                }
                else
                {
                    Log.i("update", args[0]+" going to be false");

                }
                int a = db.updateAlert(swtc.isChecked(), MyDatabase.Tab_Cal_Set.Cal+"=?", args);
                Toast.makeText(cntx, "affected: "+Integer.toString(a), Toast.LENGTH_LONG).show();
            }
            db.close();

        }
    });

PS: adapter is the arrayadapter I've created for the ListView, cntx is the context of the application, and MyDatabase is my custom class that provide to manage an Sqlite Database. Hope you can help me

code of arrayadapter:

 public class NotificationElementList extends ArrayAdapter<String>{

private final Activity context;

private final List<String> titles;
private final List<String> imgs;
private final List<Boolean> alert;


public NotificationElementList(Activity context, List<String> titles, List<String> imgs, List<Boolean> alert) {

    super(context, R.layout.list_single, titles);
    this.context = context;
    this.titles = titles;
    this.imgs = imgs;
    this.alert = alert;

    }

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

    LayoutInflater inflater = context.getLayoutInflater();

    View rowView= inflater.inflate(R.layout.notification_list_element, null, true);

    Switch switch_text = (Switch) rowView.findViewById(R.id.switch1);
    switch_text.setChecked(alert.get(position));
    switch_text.setText(titles.get(position));

    return rowView;
    }

}

As you are not providing the convertView argument to ArrayAdapter.getView method, it will always create a new view hierarchy for you. As a result you will always see your switch widgets' state initialized to alert.get(position) .

One of the potential solutions could be to set a OnCheckedChangeListener to Switch widgets and update model whenever switch state changes. For example like this

@Override
public View getView(final int position, View view, ViewGroup parent) {
    LayoutInflater inflater = context.getLayoutInflater();
    View rowView = inflater.inflate(R.layout.notification_list_element, null, true);

    Switch s = (Switch) rowView.findViewById(R.id.switch1);
    s.setChecked(alert.get(position));
    s.setText(titles.get(position));
    s.setOnCheckedChangeListener(new OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            alert.set(position, isChecked);
        }
    });

    return rowView;
}

Doing so will allow you to obtain the state directly from model as opposed to trying to obtain it from switch widget in your button click event handler. Instead of doing this

View rowview = adapter.getView(n, null, null);
Switch swtc = (Switch) rowview.findViewById(R.id.switch1);     
db.updateAlert(swtc.isChecked(), MyDatabase.Tab_Cal_Set.Cal+"=?", args);

You would do

 db.updateAlert(alert.get(n), MyDatabase.Tab_Cal_Set.Cal+"=?", args);

In addition, I suggest you update the adapter to utilize the view holder pattern for better performance.

You should not call adapter getView method. It is used internally by ListView.
Its purpose is say to ListView how to populate its contents.

If the alert list is used to save the Switch checked state you can use it.

btn.setOnClickListener( new View.OnClickListener() {

    @Override
    public void onClick(View v) {

        MyDatabase db = new MyDatabase(cntx);
        db.open();
        for(int n=0;n<alert.size();n++)
        {
            String[] args = {titles.get(n)};
            if(alert.get(n))
            {
                Log.i("update", args[0]+" going to be true");
            }
            else
            {
                Log.i("update", args[0]+" going to be false");

            }
            int a = db.updateAlert(alert.get(n), MyDatabase.Tab_Cal_Set.Cal+"=?", args);
            Toast.makeText(cntx, "affected: "+Integer.toString(a), Toast.LENGTH_LONG).show();
        }
        db.close();

    }
});

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