2

我的应用程序中有一个 listView。对于 listView 中的每个元素,它都有一个 Switch。以前,我在 listView 适配器的 getView 方法中为 Switch 实现了 onClickListener。但是,我发现虽然当用户点击开关时它确实起作用,但当用户在开关上滑动时它不起作用。然后我尝试将 onClickListener 更改为 onCheckedChangeListener。它在用户单击或滑动 Switch 时起作用,但是,当我滚动 listView 以使元素消失时,我发现最初选中的 Switch 变为未选中状态。

你能帮忙吗?下面是我在 listView 适配器中的 getView 方法的代码:

@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
    class viewHolder {
        public TextView tvSceneName;
        public Switch swSelectSwitch;
    }
    final viewHolder holder;

    final View v = convertView;

    // Use ViewHolder to avoid findViewById each time the user scroll
    if (convertView == null) {
        holder = new viewHolder();
        convertView = mInflater.inflate(R.layout.scene_list_element, parent, false);
        holder.tvSceneName = (TextView) convertView.findViewById(R.id.tvSceneName);
        holder.swSelectSwitch = (Switch) convertView.findViewById(R.id.swScene);
        convertView.setTag(holder);
    } else {
        holder = (viewHolder) convertView.getTag();
    }


    if(holder.swSelectSwitch != null) {

        // Set the switch to correct on/off status
        holder.swSelectSwitch.setChecked(mDataSource.get(position).get_isOn());

        // Set up On checked change listener for the switch
        holder.swSelectSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton toggleButton, boolean isChecked) {

                // Set the new status to arraylist
                Switch sw = (Switch) v.findViewById(R.id.swScene);
                MainActivity.sceneArrayList.get(position).set_isOn(sw.isChecked());

        });
    }
}

编辑: 在进一步测试中,我发现我新添加的 onCheckChangedListener 中存在错误(因为我从 onClickListener 复制了一些代码)。我也找到了一个解决方案,它是在我通过代码设置 Switch 之前将 onCheckChangedListener 设置为 null。

if(holder.swSelectSwitch != null) {

    // Set the switch to correct on/off status
    holder.swSelectSwitch.setOnCheckedChangeListener(null);
    holder.swSelectSwitch.setChecked(mDataSource.get(position).get_isOn());

    // Set up On checked change listener for the switch
    holder.swSelectSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton toggleButton, boolean isChecked) {

            // Set the new status to arraylist
            mDataSource.get(position).set_isOn(isChecked);

    });
}
4

2 回答 2

1

ViewHolder模式的重点是Views 正在被回收。

您正在从中获取已检查状态mDataSource,但未对其进行更新,因此当View被回收时,将Switch返回其原始(未检查)状态。

您应该在mDataSource发生更改时更新状态:

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

    // Set the new status to arraylist
    MainActivity.sceneArrayList.get(position).set_isOn(isChecked);

    // updating mDataSource
    mDataSource.get(position).set_isOn(isChecked);
}
于 2016-11-08T07:59:53.447 回答
0

您应该删除以下行if(holder.swSelectSwitch != null) {:当您滚动时,视图不会被破坏而是被回收,因此getView在滚动后调用时,convertView它不为空。当convertView不为空时,您将重用您已经创建并放入视图标签的持有者。

于 2016-11-08T07:49:54.390 回答