【问题标题】:Programmatically added checkbox doesnt save state以编程方式添加的复选框不保存状态
【发布时间】:2014-12-09 23:54:34
【问题描述】:

在我的代码中,我的线性布局中有几个视图。视图以编程方式添加

mUserProfile = mNavigationCallback.getUserProfile();
    List<Contact> contacts = mUserProfile.getContacts();
    for (Contact c : contacts) {
        View view = View.inflate(getActivity(), R.layout.item_contact, null);
        TextView tv = (TextView) view.findViewById(R.id.tvPhone);
        tv.setText(c.getValue());
        CheckBox cb = (CheckBox) view.findViewById(R.id.cbContactChecked);
        cb.setId(generateViewId());
        if (c.getType().equals("email")) {
            llEmailContacts.addView(view);
        }
        if (c.getType().equals("phone")) {
            llPhoneContacts.addView(view);
        }
    }

每个视图都包含带有 Textview 和 Checkbox 的线性布局。 但是checkbox在屏幕旋转时没有保存自己的状态,请问是什么问题以及如何解决?

UPD:我不能使用 onSaveInstanceState,因为这个片段使用了 setRetainInstance(true)

【问题讨论】:

  • 您是否知道旋转 Android 时的默认行为会导致所有数据被重置?您需要在 onSaveInstanceState() 中处理状态保存并在 onCreate() 或 onRestoreInstanceState() 中检索它
  • 还请彻底检查一个活动生命周期。每当您的设备方向发生变化时,都会再次调用 onCreate() !这意味着您的 UI 将失去其状态。请考虑使用片段
  • 您希望保存什么状态?您如何在新活动/片段中使用与旧活动/片段中相同的小部件 ID 创建小部件?
  • @CommonsWare 我只想保存检查状态。它适用于 xml 定义的复选框,但不适用于动态添加。而且我不能使用 saveInstanceState,因为片段使用 setRetain(true)。 Id 是使用 View 类中的 generateViewId() 方法生成的。

标签: android checkbox


【解决方案1】:

Id 使用 View 类的 generateViewId() 方法生成

这对于您初次设置小部件时可能没问题。如果您希望内置保存的实例状态逻辑能够正常工作,则第二次及以后的时间需要使用与之前使用的相同 ID

【讨论】:

  • 谢谢,我的问题已经解决了。看我的回答,如果有错请纠正。
【解决方案2】:

当您旋转屏幕时,您的活动会被破坏并再次恢复。重新创建所有成员变量并重新绘制所有视图。您可以在清单中添加一些标志,但您应该考虑在方法 onSaveInstancestate() 中保存状态

在您的示例中,Contact 可能有一个变量 isSelected,它会随着复选框的选择而改变

mUserProfile = mNavigationCallback.getUserProfile();
    List<Contact> contacts = mUserProfile.getContacts();
    for (Contact c : contacts) {
        View view = View.inflate(getActivity(), R.layout.item_contact, null);
        TextView tv = (TextView) view.findViewById(R.id.tvPhone);
        tv.setText(c.getValue());
        CheckBox cb = (CheckBox) view.findViewById(R.id.cbContactChecked);
        cb.setChecked(c.isSelected)
        cb.setId(generateViewId());
        if (c.getType().equals("email")) {
            llEmailContacts.addView(view);
        }
        if (c.getType().equals("phone")) {
            llPhoneContacts.addView(view);
        }
    }

然后你覆盖 onSaveInstanceState 保存所有联系人的位置

public void onSaveInstanceState(Bundla outState) {
//Save your userprofile somehow, for example by serializing it using json
//and add to bundle
}

然后在 onCreate()

public void onCreate(Bundle state) {
//Get your userProfile from state. If it is null, there was no state saved then get it like you //already do = mUserProfile = mNavigationCallback.getUserProfile();
List<Contact> contacts = mUserProfile.getContacts();
for (Contact c : contacts) {
            View view = View.inflate(getActivity(), R.layout.item_contact, null);
            TextView tv = (TextView) view.findViewById(R.id.tvPhone);
            tv.setText(c.getValue());
            CheckBox cb = (CheckBox) view.findViewById(R.id.cbContactChecked);
            cb.setChecked(c.isSelected)
            cb.setId(generateViewId());
            if (c.getType().equals("email")) {
                llEmailContacts.addView(view);
            }
            if (c.getType().equals("phone")) {
                llPhoneContacts.addView(view);
            }
        }
}

【讨论】:

  • 我真的很想使用 onSaveInstanceState 回调,但由于 setRetainInstance(true) 方法,bundle 将始终为空。我只是想了解为什么保存状态对于在 xml 中添加的所有带有 ID 的视图都有效,但不适用于动态添加的视图和 ID
【解决方案3】:

通过保存生成的 ID 并重新使用它来修复:

 mUserProfile = mNavigationCallback.getUserProfile();
    List<Contact> contacts = mUserProfile.getContacts();
    for (Contact c : contacts) {
        View view = View.inflate(getActivity(), R.layout.item_contact, null);
        TextView tv = (TextView) view.findViewById(R.id.tvPhone);
        tv.setText(c.getValue());
        CheckBox cb = (CheckBox) view.findViewById(R.id.cbContactChecked);
        if (c.getViewId() == 0) {
            c.setViewId(generateViewId());
        }
        cb.setId(c.getViewId());

        cb.setTag(c);
        Timber.d("setting CB: " + "ID :" + cb.getId() + " tag " + cb.getTag());

        cb.setOnCheckedChangeListener(mOnCheckedChangeListener);
        if (c.getType().equals("email")) {
            llEmailContacts.addView(view);
        }
        if (c.getType().equals("phone")) {
            llPhoneContacts.addView(view);
        }
    }

【讨论】:

    猜你喜欢
    • 2020-01-08
    • 2020-01-09
    • 1970-01-01
    • 2014-09-25
    • 2011-02-14
    • 2020-04-20
    • 1970-01-01
    • 2012-03-31
    • 2012-04-18
    相关资源
    最近更新 更多