【问题标题】:Saving State Of Dynamatically Created Checkbox保存动态创建的复选框的状态
【发布时间】:2017-08-01 01:08:29
【问题描述】:

我目前正在尝试为学习目的制作一个简单的任务杀手,我创建了一个列表视图,显示所有用户安装的带有复选框的应用程序,因此用户可以选择应用程序应该在屏幕关闭时被杀死。

但我不知道如何保存复选框状态并获取已检查应用程序的包名称

我的搜索堆栈溢出了很长时间,但仍然不知道该怎么做,请帮助我,谢谢

这是我的代码

AppAdapter.java

public class AppAdapter extends BaseAdapter {

private LayoutInflater layoutInflater;
private List<AppList> listStorage;

public AppAdapter(Context context, List<AppList> customizedListView) {
    layoutInflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    listStorage = customizedListView;
}

@Override
public int getCount() {
    return listStorage.size();
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return position;
}

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

    final ViewHolder listViewHolder;
    if(convertView == null){
        listViewHolder = new ViewHolder();
        convertView = layoutInflater.inflate(R.layout.installed_app_list, parent, false);

        listViewHolder.textInListView = (TextView)convertView.findViewById(R.id.list_app_name);
        listViewHolder.imageInListView = (ImageView)convertView.findViewById(R.id.app_icon);
        listViewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.checkBox);
        convertView.setTag(listViewHolder);

        listViewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    listViewHolder.checkBox.setSelected(listStorage.get(position).isSelected());
                }
            }
        });
    }else{
        listViewHolder = (ViewHolder)convertView.getTag();
    }
    listViewHolder.textInListView.setText(listStorage.get(position).getName());
    listViewHolder.imageInListView.setImageDrawable(listStorage.get(position).getIcon());
    listViewHolder.checkBox.setChecked(listStorage.get(position).isSelected());

    return convertView;
}

static class ViewHolder{

    TextView textInListView;
    ImageView imageInListView;
    CheckBox checkBox;
}

}

Applist.java

public class AppList {

private String name;
Drawable icon;
private static final String PREFERENCES_NAMESPACE = "checkboxes_states";
boolean selected = false;
private SharedPreferences mSettings;
private SharedPreferences.Editor mEditor;

public AppList(Context context, String name, Drawable icon) {
    this.name = name;
    this.icon = icon;
    mSettings = context.getSharedPreferences(PREFERENCES_NAMESPACE, 0);
    mEditor = mSettings.edit();
    setSelected(mSettings.getBoolean(name, selected));
}

public String getName() {
    return name;
}

public Drawable getIcon() {
    return icon;
}
public boolean isSelected() {
    return selected;
}
public void setSelected(boolean selected) {
    if(this.selected != selected) { // update if changed
        mEditor.putBoolean(getName(), selected);
        mEditor.apply();
        this.selected = selected;
    }
}
}

MainActivity.java

public class MainActivity extends Activity {

Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    context = getApplicationContext();

    ListView userInstalledApps = (ListView)findViewById(R.id.installed_app_list);

    List<AppList> installedApps = getInstalledApps();
    AppAdapter installedAppAdapter = new AppAdapter(MainActivity.this, installedApps);
    userInstalledApps.setAdapter(installedAppAdapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private List<AppList> getInstalledApps() {
    List<AppList> res = new ArrayList<AppList>();
    List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
    for (int i = 0; i < packs.size(); i++) {
        PackageInfo p = packs.get(i);
        if ((isSystemPackage(p) == false)) {
            String appName = p.applicationInfo.loadLabel(getPackageManager()).toString();
            Drawable icon = p.applicationInfo.loadIcon(getPackageManager());
            res.add(new AppList(context, appName, icon));
        }
    }
    return res;
}

private boolean isSystemPackage(PackageInfo pkgInfo) {
    return ((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true : false;
}
}

提前致谢

【问题讨论】:

    标签: java android xml android-layout checkbox


    【解决方案1】:

    创建接口:

        public interface AppSelector {
            void selectApp(String appName);
            void removeApp(String appName);
            boolean isSelected(String appName);
        }
    

    将其添加到您的 AppAdapter:

        public class AppAdapter extends BaseAdapter {
    
        private AppSelector appSelector;
        private List<AppList> listStorage;
    
        public AppAdapter(AppSelector appSelector, List<AppList> customizedListView) {
            this.appSelector = appSelector;
            listStorage = customizedListView;
        }
    
        ....
    
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            final ViewHolder listViewHolder;
            if(convertView == null){
                listViewHolder = new ViewHolder();
                convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.installed_app_list, parent, false);
    
                listViewHolder.textInListView = (TextView)convertView.findViewById(R.id.list_app_name);
                listViewHolder.imageInListView = (ImageView)convertView.findViewById(R.id.app_icon);
                listViewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.checkBox);
                convertView.setTag(listViewHolder);
                listViewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        if (isChecked) {
                            appSelector.selectApp(listStorage.get(position).getName());
                        } else {
                            appSelector.removeApp(listStorage.get(position).getName());
                        }
                    }
                });
            } else {
                listViewHolder = (ViewHolder)convertView.getTag();
            }
            listViewHolder.textInListView.setText(listStorage.get(position).getName());
            listViewHolder.imageInListView.setImageDrawable(listStorage.get(position).getIcon());
            listViewHolder.checkBox.setChecked(appSelector.isSelected(listStorage.get(position).getName()));
    
            return convertView;
        }
    
        ....
    }
    

    由您的 MainActivity 实现:

        class MainActivity extends AppCompatActivity implements AppSelector {
    
        private static final String PREFERENCES_NAMESPACE = "checkboxes_states";
        private SharedPreferences checkedAppsPreferences;
    
        ....
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            ....
            checkedAppsPreferences = getSharedPreferences(PREFERENCES_NAMESPACE, 0);
            ....
            AppAdapter installedAppAdapter = new AppAdapter(this, installedApps);
            ....
        }
    
        @Override
        public void selectApp(String appName) {
            checkedAppsPreferences.edit()
                .putBoolean(appName, true)
                .apply();
        }
    
        @Override
        public void removeApp(String appName) {
            checkedAppsPreferences.edit()
                .remove(appName)
                .apply();
        }
    
        @Override
        public boolean isSelected(String appName) {
            return checkedAppsPreferences.contains(appName) && checkedAppsPreferences.getBoolean(appName, false);
        }
    
        ....
    }
    

    您的 AppList 类不应包含对 Context 或 SharedPreferences 的任何引用以及“检查”/“取消检查”的逻辑。应该是简单的 POJO。

    使用界面,您可以轻松地将共享首选项替换为另一种存储库,例如 SQLite

    已编辑:我更改 AppAdapter getView mwthod:

                listViewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (isChecked) {
                        appSelector.selectApp(listStorage.get(position).getName());
                    } else {
                        appSelector.removeApp(listStorage.get(position).getName());
                    }
                }
            });
    

    您可以在https://github.com/valeragit/AppListExample查看完整项目

    【讨论】:

    • 我试过你的代码,但没有工作,复选框仍然没有保存状态
    • 已编辑,虽然添加了测试项目
    • 我尝试导入您的项目并测试应用程序,但它仍然无法正常工作,滚动列表视图后复选框再次未选中
    • 经过一些研究和更改我的一些代码后,我发现它又可以工作了,谢谢
    【解决方案2】:

    您从未调用过 AppList.setSelected()。 比在 listViewHolder onClickListener 上调用,然后很可能通知适配器有更改。 您可能还想调用 setChecked 而不是 setSelected

     listViewHolder.checkBox.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    boolean isSelected = listStorage.get(position).isSelected();
                    listViewHolder.checkBox.setChecked(!isSelected);
                    listStorage.get(position).setSelected(!isSelected)
                    notifyDataSetChanged();
                }
            });
    

    您可以通过设置 checkChangedListener 而不是 onClickListener 来进一步改进这一点,但首先要解决最初的问题。

    编辑:OP 解决了最初的问题,现在评论改进。 将 onClick 替换为:

    listViewHolder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                listStorage.get(position).setSelected(isChecked)
                notifyDataSetChanged();
            }
    
        });
    

    【讨论】:

    • 有效!!!非常感谢,我已经在网上搜索了两个多星期,但没有找到答案,请您说明如何在 onCheckedChangedListener 中进行此操作?
    • 但是当我尝试向下滚动列表视图并单击下面的复选框时出现问题
    • 你遇到了什么问题?
    • 当我打开应用程序并单击复选框时,它工作正常,但是当我向下滚动列表视图并单击复选框时,它会自动取消勾选
    • @Dragon957 试试 setOnCheckedChangeListener
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2012-04-18
    • 2013-02-21
    • 1970-01-01
    相关资源
    最近更新 更多