【问题标题】:ToggleButton in ListView being inconsistent with isChecked settingListView 中的 ToggleButton 与 isChecked 设置不一致
【发布时间】:2017-04-04 23:02:24
【问题描述】:

所以我在列表视图中设置了一个按钮,以便在选中/取消选中时将其选中状态保存在 sharedpreferences 中,然后当它加载视图时,它会根据它是保存为选中还是未选中自动设置检查状态,但有些似乎不检查自己或根本不切换。这是相当不一致的。

这是我的 ListViewAdapter

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View ListItem = convertView;
        Holder holder;

        if (ListItem == null) {

            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            ListItem = inflater.inflate(layoutResourceId, parent, false);

            holder = new Holder();
    //            holder.description = (TextView) ListItem.findViewById(R.id.deityDesc);
                holder.banner = (ImageView) ListItem.findViewById(R.id.deityBanner);
                holder.website = (Button) ListItem.findViewById(R.id.deityWebsite);
                holder.active = (ToggleButton) ListItem.findViewById(R.id.isActiveButtonToggle);
    //            holder.background = (RelativeLayout) ListItem.findViewById(R.id.listItemBG);
                holder.highlight =  (ImageView) ListItem.findViewById(R.id.highlight);
    //            holder.highlight2 = (ImageView) ListItem.findViewById(R.id.highlight2);
                holder.title = (TextView) ListItem.findViewById(R.id.titleText);

            ListItem.setTag(holder);

        } else {
            holder = (Holder) ListItem.getTag();
        }
        final deities deity = data[position];
        SharedPreferences sharedPref = ((Activity) context).getPreferences(Context.MODE_PRIVATE);
        deity.active = sharedPref.getBoolean(Integer.toString(deity.id), false);
        notifyDataSetChanged();

        View.OnClickListener holderListener = new View.OnClickListener() {
            public void onClick(View v) {
                WebView webView = (WebView) ((Activity) context).findViewById(R.id.webView);
                webView.setVisibility(View.VISIBLE);
                webView.loadUrl(deity.url);
            }
        };

        CompoundButton.OnCheckedChangeListener ToggleButtonListener = new CompoundButton.OnCheckedChangeListener() {
            @NonNull
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//                int position = (int) buttonView.getParent().getT();
//                deities deity = data[position];
                deity.active = isChecked;
                SharedPreferences sharedPref = ((Activity) context).getPreferences(Context.MODE_PRIVATE);
                SharedPreferences.Editor prefeditor = sharedPref.edit();
                TextView deityActiveCount = (TextView) ((Activity) context).findViewById(R.id.deitySelectedCounter);
                final CompoundButton Button = buttonView;
                final RelativeLayout r = (RelativeLayout) ((ViewGroup) Button.getParent()).getParent();
                prefeditor.putBoolean(Integer.toString(deity.id), isChecked);
                prefeditor.apply();
                setCounter(isChecked ? getCounter() + 1 : getCounter() - 1);
                ViewGroup ListItem = (ViewGroup) buttonView.getParent();
                int startColor = isChecked ? Color.parseColor("#ce5a5a") : Color.parseColor("#2e7d32");
                int endColor = isChecked ? Color.parseColor("#2e7d32") : Color.parseColor("#ce5a5a");
                ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
                    colorAnimation.setDuration(100);
                    colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator animation) {

                            ImageView sideThing1 = (ImageView) r.findViewById(R.id.highlight);
//                            ImageView sideThing2 = (ImageView) r.findViewById(R.id.highlight2);
                            sideThing1.setBackgroundColor((int) animation.getAnimatedValue());
//                            sideThing2.setBackgroundColor((int) animation.getAnimatedValue());
                            Button.setBackgroundColor((int) animation.getAnimatedValue());

                        }
                    });
                colorAnimation.start();
                notifyDataSetChanged();

            }
        };


        if (deity.active) {
            holder.active.setChecked(true);
            holder.active.setBackgroundColor(Color.parseColor("#2e7d32"));
            holder.highlight.setBackgroundColor(Color.parseColor("#2e7d32"));
//            holder.highlight2.setBackgroundColor(Color.parseColor("#2e7d32"));


        } else {
            holder.active.setChecked(false);
            holder.active.setBackgroundColor(Color.parseColor("#ce5a5a"));
            holder.highlight.setBackgroundColor(Color.parseColor("#ce5a5a"));
//            holder.highlight2.setBackgroundColor(Color.parseColor("#ce5a5a"));
        }


        holder.active.setOnCheckedChangeListener(ToggleButtonListener);
        holder.website.setOnClickListener(holderListener);
        holder.banner.setImageResource(deity.banner);
//        holder.description.setText(deity.description);
        holder.banner.setBackgroundColor(Color.parseColor("#616161"));
//        holder.description.setText(deity.url);
        holder.title.setText(deity.title + " " + deity.active);
        return ListItem;

    }

This is what I mean by inconsistent (click me, it's a video)

注意一些如何恢复/不保存?

一天过去了,我还是想不通。

【问题讨论】:

  • 数据本身没有得到更新。你在哪里调用 notifyDataSetChanged()
  • 我建议删除 OnCheckedChangeListener,使 CompoundButton 可点击为 false 并通过在列表上单击项目来处理它
  • 天哪,这就是我所缺少的!谢谢。如果您将其发布为解决方案,我很乐意为您提供正确答案。

标签: android listview


【解决方案1】:

试试这个:

@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
    View ListItem = convertView;
    Holder holder;

    if (ListItem == null) {

        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        ListItem = inflater.inflate(layoutResourceId, parent, false);

        holder = new Holder();
        //            holder.description = (TextView) ListItem.findViewById(R.id.deityDesc);
        holder.banner = (ImageView) ListItem.findViewById(R.id.deityBanner);
        holder.website = (Button) ListItem.findViewById(R.id.deityWebsite);
        holder.active = (ToggleButton) ListItem.findViewById(R.id.isActiveButtonToggle);
        //            holder.background = (RelativeLayout) ListItem.findViewById(R.id.listItemBG);
        holder.highlight = (ImageView) ListItem.findViewById(R.id.highlight);
        //            holder.highlight2 = (ImageView) ListItem.findViewById(R.id.highlight2);
        holder.title = (TextView) ListItem.findViewById(R.id.titleText);

        ListItem.setTag(holder);

    } else {
        holder = (Holder) ListItem.getTag();
    }
    final deities deity = data[position];

    View.OnClickListener holderListener = new View.OnClickListener() {
        public void onClick(View v) {
            WebView webView = (WebView)((Activity) context).findViewById(R.id.webView);
            webView.setVisibility(View.VISIBLE);
            webView.loadUrl(deity.url);
        }
    };

    CompoundButton.OnCheckedChangeListener ToggleButtonListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            int position = (int) buttonView.getTag();

            final deities deity = data[position];

            SharedPreferences sharedPref = ((Activity) context).getPreferences(Context.MODE_PRIVATE);
            SharedPreferences.Editor prefeditor = sharedPref.edit();
            final CompoundButton Button = buttonView;
            final RelativeLayout r = (RelativeLayout) Button.getParent().getParent();

            deity.active = isChecked;
            prefeditor.putBoolean(Integer.toString(deity.id), isChecked);
            prefeditor.apply();

            int startColor = isChecked ? Color.parseColor("#ce5a5a") : Color.parseColor("#ce5a5a");
            int endColor = isChecked ? Color.parseColor("#2e7d32") : Color.parseColor("#2e7d32");

            ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
            colorAnimation.setDuration(100);
            colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {

                    ImageView sideThing1 = (ImageView) r.findViewById(R.id.highlight);
                    //                            ImageView sideThing2 = (ImageView) r.findViewById(R.id.highlight2);
                    sideThing1.setBackgroundColor((int) animation.getAnimatedValue());
                    //                            sideThing2.setBackgroundColor((int) animation.getAnimatedValue());
                    Button.setBackgroundColor((int) animation.getAnimatedValue());

                }
            });
            colorAnimation.start();

            notifyDataSetChanged();
        }
    };

    SharedPreferences sharedPref = ((Activity) context).getPreferences(Context.MODE_PRIVATE);
    deity.active = sharedPref.getBoolean(Integer.toString(deity.id), false);

    holder.active.setChecked(deity.active);

    if (deity.active) {
        holder.active.setBackgroundColor(Color.parseColor("#2e7d32"));
        holder.highlight.setBackgroundColor(Color.parseColor("#2e7d32"));
    } else {
        holder.active.setBackgroundColor(Color.parseColor("#ce5a5a"));
        holder.highlight.setBackgroundColor(Color.parseColor("#ce5a5a"));
    }

    holder.active.setTag(position);

    holder.active.setOnCheckedChangeListener(ToggleButtonListener);
    holder.website.setOnClickListener(holderListener);
    holder.banner.setImageResource(deity.banner);
    //        holder.description.setText(deity.description);
    holder.banner.setBackgroundColor(Color.parseColor("#616161"));
    //        holder.description.setText(deity.url);
    holder.title.setText(deity.title + " " + deity.active);
    return ListItem;
}

PS:我尝试在没有进行大量更改的情况下解决问题,因此这可能不是最佳答案

【讨论】:

  • 谢谢。特别感谢您展示了我为真/假 isChecked 事物制作 if 语句的明显错误,我真的不知道我为什么这样做
  • 因此,通过在 getView 方法中使用 position/diety 的声明,我在尝试在空对象引用上调用 Integer.intValue() 时遇到了崩溃。也由于一些奇怪的原因,我的 notifyDataSetChanged 停止修复问题,它又坏了。我已经更新了 OP
【解决方案2】:

tl;dr: 确保您的 ToggleButton 的 setOnCheckedChangedListener 在调用 setChecked 之前 已设置。 This issue is talked about more here (click me).

为了解决这个特定问题(虽然感谢zombie指出notifyDataSetChanged的重要性),我移动了

holder.active.setOnCheckedChangedListener(ToggleButtonListener);

到之前

holder.active.setChecked(diety.active);

因为显然这是 ListViews 的常见问题,如果侦听器位于 setChecked 的前面,onChecked 将无法正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 2011-04-15
    相关资源
    最近更新 更多