【问题标题】:How can i have one switch on in a ListView of many switches?如何在多个开关的 ListView 中打开一个开关?
【发布时间】:2016-02-10 23:07:08
【问题描述】:

我正在构建一个 Android 应用程序,我希望在任何时候在 ListView 中只激活一个处于开启模式的开关。我正在使用 onCheckedChanged 方法。我该怎么做?

public ListAdapter2(Context context, ArrayList<String> resource, Boolean[] checkedStatus) {
    super(context,R.layout.toggle_button_row,resource);
    // TODO Auto-generated constructor stub
    this.context = context;
    goalList=new ArrayList<String>();
    this.goalList =resource;
    this.checkedStatus=checkedStatus;

}

 @Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    LayoutInflater inflater = ((Activity)context).getLayoutInflater();
    convertView = inflater.inflate(R.layout.toggle_button_row, parent, false);
    v1=convertView;
    TextView name = (TextView) v1.findViewById(R.id.textview1);
    name.setText(goalList.get(position).toString());
    sw= (Switch) v1.findViewById(R.id.switch1);
    sw.setTag(position);
    sw.setOnCheckedChangeListener(ListAdapter2.this);
    sw.setChecked(checkedStatus[position]);

    return convertView;
}

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    Integer index = (Integer) buttonView.getTag();
    checkedStatus[index] = isChecked;
    String key = index.toString();

    //save the data for the status
    SharedPreferences sharedPreferences = getContext().getSharedPreferences("status", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putBoolean(key, isChecked);
    editor.putBoolean("MyGoal", isChecked);
    editor.putString("MyGoal1", goalList.get(index).toString().trim());
    editor.apply();
}

我添加了更多代码。我想要做的是,在这个特定的 ListView 中,当我打开时,例如第一个我想保存它的状态,我已经通过使用 sharedPreferences 完成了这个,但我不想打开多个开关。因此,当我激活第二个时,我希望第一个关闭。这同样适用于所有这些,当一个处于活动状态时,其他的处于关闭状态。

public void display(View v) {
    //The database is open!
    ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(this, DB_NAME);
    database = dbOpenHelper.openDataBase();
    //initialize
    goalList = new ArrayList<String>();
    //put cursor
    Cursor cursor = database.rawQuery("select * from tbl_WG", null);
    cursor.moveToFirst();
    if(!cursor.isAfterLast()) {
        do {
            String name=cursor.getString(cursor.getColumnIndex("name"));
            Integer steps=Integer.parseInt(cursor.getString(1));

            goalList.add("Name: "+name+" || Steps: "+steps);


        } while (cursor.moveToNext());
    }
    cursor.close();
    //size of the status list;
    status= new boolean[goalList.size()];

    //check state
    SharedPreferences sharedPreferences = getSharedPreferences("status", MODE_PRIVATE);
    checkedStatus = new Boolean[goalList.size()];
    for ( int index = 0; index < checkedStatus.length; index++)
        checkedStatus[index] = sharedPreferences.getBoolean(Integer.toString(index), false);


    //create an ArrayAdaptar from the String Array
    ListAdapter2 adapter = new ListAdapter2(this, goalList, checkedStatus);
    // Assign adapter to ListView
    mainListView.setAdapter(adapter);

}

【问题讨论】:

  • 您是否在任何地方维护所有这些开关的阵列?
  • 你能描述一下你现在的策略是什么,特别是你不想做的事情是什么?也许发布此代码所在的整个文件。
  • 更新了我的帖子,感谢您的宝贵时间

标签: android oncheckedchanged


【解决方案1】:

我想你快到了。

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

        // First turn off the switch of any other item that may be on
        Arrays.fill(checkedStatus, false);

        Integer index = (Integer) buttonView.getTag();
        checkedStatus[index] = isChecked;
        notifyDataSetChanged();  // don't forget to tell ListView that data is updated

        //save the data for the status
        String key = index.toString();
        SharedPreferences sharedPreferences = getContext().getSharedPreferences("status", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        /*
         *  I don't think this code:
         *
         *      editor.putBoolean(key, isChecked);
         *
         *  is a really good idea, because you have to make sure
         *  you "uncheck" any keys that were previously checked.
         *
         *  This might be better:
         */
        if (isChecked) {
            editor.putInt("last_index", index);
        } else {
            editor.remove("last_index"); // nothing's checked, so erase pref
        }

        editor.putBoolean("MyGoal", isChecked);

        // not sure this makes sense if isChecked == false, you may want to rethink the preferences
        editor.putString("MyGoal1", goalList.get(index).toString().trim());
        editor.apply();
    }

此外,在您的 getView 方法中,您应该执行以下操作:

        sw.setOnCheckedChangeListener(null);
        sw.setChecked(checkedStatus[position]);
        sw.setOnCheckedChangeListener(ListAdapter2.this);

这将防止在您设置开关的选中状态时触发任何回收的侦听器。


使用上面的首选项保存代码,您可以通过以下方式恢复选中状态:

    //check state
    SharedPreferences sharedPreferences = getSharedPreferences("status", MODE_PRIVATE);
    checkedStatus = new Boolean[goalList.size()];
    int index = sharedPreferences.getInt("last_index", -1);
    if (index != -1) {
        checkedStatus[index] = true;
    }

【讨论】:

  • 非常感谢您的代码,您确实帮助我理解了一些事情。现在有了这段代码,我已经成功地检查了一个并取消了其他完美但现在我失去了状态。任何快速修复?还有为什么 null 那里? sw.setOnCheckedChangeListener(null)
  • 不确定我理解您所说的“失去状态”是什么意思。如果您使用首选项来存储整个列表的状态,那么可能有更好的方法。至于null,只需调用setChecked 就会触发OnCheckedChangeListener,因此通过将其设置为null,您可以确保它仅在用户选中/取消选中它时才会触发。请记住,这些视图可以被回收,因此视图可能会在已设置的侦听器的情况下进入;这就是为什么您需要先取消设置。
  • 我的意思是当我再次返回活动时,开关不是打开而是关闭,因此它失去了状态。这是 Arrays.fill(checkedStatus, false);导致问题?有更好的方法是什么意思?
  • 如果您只需要在方向更改和其他活动返回之间保持状态,您可以使用onSaveInstanceState() 保存当前的开关设置。如果除此之外还需要保持持久性,则首选项是可以的,但数据库表可能会更好。您可以使用首选项来恢复您的状态;发布创建布尔数组和适配器的活动代码;然后我会更新我的答案。
  • 我已经用您询问的活动更新了我的帖子。我现在能做什么?
猜你喜欢
  • 2017-11-21
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多