Java 在Android MultiSelectListPreference中至少选择一项
我在互联网上搜索了几个小时,到目前为止没有发现任何实质性的东西。我想做的是一个多选偏好视图,它禁用最后一项并重新启用它,如果它不再是单独的 到目前为止,我已经完成了关于使用超级类强制读取其中的私有变量来编写我自己的Java 在Android MultiSelectListPreference中至少选择一项,java,android,options,multichoiceitems,multiselectlistpreference,Java,Android,Options,Multichoiceitems,Multiselectlistpreference,我在互联网上搜索了几个小时,到目前为止没有发现任何实质性的东西。我想做的是一个多选偏好视图,它禁用最后一项并重新启用它,如果它不再是单独的 到目前为止,我已经完成了关于使用超级类强制读取其中的私有变量来编写我自己的onPrepareDialogBuilder(AlertDialog.Builder)。它正在配置自己的OnMultiChoiceClickListener,在只剩下一个项目的情况下跳入。这里的问题是,我使用了一个错误的方法强制读取私有变量,到目前为止,我不知道如何获取复选框项以及如何
onPrepareDialogBuilder(AlertDialog.Builder)
。它正在配置自己的OnMultiChoiceClickListener
,在只剩下一个项目的情况下跳入。这里的问题是,我使用了一个错误的方法强制读取私有变量,到目前为止,我不知道如何获取复选框项以及如何禁用它。但我认为,深入研究Android SDK将解决这个问题
最后,如果什么都不起作用,解决了在用户选择的项目少于一个时覆盖OnPreferenceChangeListener
以显示toast的问题。但是,用户友好性是一个很高的价值,这需要努力,而且往往并不容易
Thx
导入android.content.Context;
导入android.preference.MultiSelectListPreference;
导入android.util.AttributeSet;
导入java.util.ArrayList;
导入java.util.HashSet;
导入java.util.List;
导入java.util.Set;
导入georg.com.flironetest_01.Variables.Units;
/**
*由Georg于2016年3月16日创建。
*/
公共类UnitMultipleSelectorReference扩展了MultiSelectListPreference{
公共UnitMultipleSelectorReference(上下文上下文、属性集属性){
超级(上下文,attrs);
List humanU=new ArrayList();
List machineU=new ArrayList();
Units[]all=Units.values();//Units是一个带有rewriten to string语句的枚举。
单位(要素:全部){
humanU.add(elem.toString());
machineU.add(elem.name());
}
setEntries(humanU.toArray(新的字符序列[humanU.size()]));
setEntryValues(machineU.toArray(新的字符序列[machineU.size()]);
Set mU=新的HashSet();
mU.add(Units.C.name());
mU.add(Units.K.name());
设置默认值(μ);
}
}
好的。在“自我就是男人”这句格言之后,我在这里回答自己的问题:我最终编写了自己的偏好面板。下面是代码。如果有人喜欢查看它,并给出一些时间如何使它更稳定:请随意
但总结一下我所做的:我创建了自己的ArrayAdapter。但是,DialogPreference
不允许我创建自己的多选择器。您需要更改最后一个对话框片段以创建一个工作的多选择器列表(请参见此处:)。如果使用DialogPreferences,这不是一项容易的任务。原因是代码数量很少:
/**
* Shows the dialog associated with this Preference. This is normally initiated
* automatically on clicking on the preference. Call this method if you need to
* show the dialog on some other event.
*
* @param state Optional instance state to restore on the dialog
*/
protected void showDialog(Bundle state) {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
mBuilder = new AlertDialog.Builder(context)
.setTitle(mDialogTitle)
.setIcon(mDialogIcon)
.setPositiveButton(mPositiveButtonText, this)
.setNegativeButton(mNegativeButtonText, this);
View contentView = onCreateDialogView();
if (contentView != null) {
onBindDialogView(contentView);
mBuilder.setView(contentView);
} else {
mBuilder.setMessage(mDialogMessage);
}
onPrepareDialogBuilder(mBuilder);
getPreferenceManager().registerOnActivityDestroyListener(this);
// Create the dialog
final Dialog dialog = mDialog = mBuilder.create();
if (state != null) {
dialog.onRestoreInstanceState(state);
}
if (needInputMethod()) {
requestInputMethod(dialog);
}
dialog.setOnDismissListener(this);
dialog.show();
}
如您所见,这里有一个方法被触发,用于使用onPrepareDialogBuilder
更改我的对话框生成器,但之后似乎没有任何其他函数被触发,允许我在创建对话框后直接更改对话框。第二个想法是更改prepareDialogBuilder上的,这样我就可以在那里初始化所有内容,但这并没有真正的帮助,因为我最终会显示对话框窗口。这让我决定创建完全属于自己的偏好类。有了这个决定,我失去了所有准备好的函数,比如onRestoreInstanceState
和Co,但我现在有了一个更持久的流的应用程序,当我为热视图选择零单位时,它不会做任何愚蠢的事情
下面是未注释的代码。很抱歉,但我认为这对登陆这里的每个人来说都很简单
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import georg.com.flironetest_01.Variables.Units;
/**
* Created by Georg on 16/03/16.
*/
public class UnitMultipleSelectorPreference extends Preference implements DialogInterface.OnClickListener, Preference.OnPreferenceClickListener {
String[] human_entries = null;
String[] machine_entries = null;
public SharedPreferences prev;
public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
prev = getSharedPreferences();
List<String> humanU = new ArrayList<>();
List<String> machineU = new ArrayList<>();
Units[] all = Units.values();
for (Units elem : all) {
humanU.add(elem.toString());
machineU.add(elem.name());
}
human_entries = humanU.toArray(new String[humanU.size()]);
machine_entries = machineU.toArray(new String[machineU.size()]);
Set<String> mU = new HashSet<>();
mU.add(Units.C.name());
mU.add(Units.K.name());
setDefaultValue(mU);
setOnPreferenceClickListener(this);
}
boolean[] selected = new boolean[0];
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
if (prev == null)
return;
if (human_entries == null || machine_entries == null || human_entries.length != machine_entries.length ) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array which are both the same length");
}
selected = new boolean[human_entries.length];
for (int i = 0; i < human_entries.length; i++)
selected[i] = prefSet.contains(machine_entries[i]);
String[] stringObj = new String[human_entries.length];
int i = 0;
for(CharSequence ch : human_entries)
stringObj[i++] = ch.toString();
builder.setAdapter(new MyAdapter(getContext(), android.R.layout.simple_list_item_multiple_choice, stringObj), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog mDialog = builder.create();
mDialog.getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
mDialog.getListView().setItemsCanFocus(false);
mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Manage selected items here
ListView mParent = (ListView)parent;
if (mParent.getCheckedItemCount() >= 1)
selected[position] = mParent.isItemChecked(position);
if (mParent.getCheckedItemCount() == 0)
mParent.setItemChecked(position, true);
}
});
mDialog.show();
i = 0;
for (boolean select : selected)
mDialog.getListView().setItemChecked(i++, select);
}
@Override
public boolean onPreferenceClick(Preference preference) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext());
mBuilder.setTitle(getTitle())
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this);
onPrepareDialogBuilder(mBuilder);
return true;
}
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), "W:"+which + " | " + Arrays.toString(selected), Toast.LENGTH_SHORT).show();
switch (which) {
case -1:
if (isPersistent()) {
prefSet = new HashSet<>();
for (int i = 0; i < selected.length; i++) {
if (selected[i])
prefSet.add(machine_entries[i]);
}
getEditor().putStringSet(getKey(), prefSet).apply();
Toast.makeText(getContext(), "W:"+which + " | " + getSharedPreferences().getStringSet(getKey(),null).toString(), Toast.LENGTH_SHORT).show();
}
return;
}
}
public class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, String[] objects) {
super(context, textViewResourceId, objects);
}
@Override
public boolean isEnabled(int n) {
return true;
}
}
Set<String> prefSet;
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
super.onSetInitialValue(restorePersistedValue, defaultValue);
prev = getSharedPreferences();
if(restorePersistedValue) {
prefSet = prev.getStringSet(getKey(), new HashSet<String>());
} else {
try {
prefSet = (Set<String>)defaultValue;
if(isPersistent())
getEditor().putStringSet(getKey(), prefSet);
} catch (ClassCastException e) {
Log.e("ERROR_CAST", "Error casting the default value to Set<String>.");
}
}
}
}
导入android.app.AlertDialog;
导入android.content.Context;
导入android.content.DialogInterface;
导入android.content.SharedReferences;
导入android.preference.preference;
导入android.util.AttributeSet;
导入android.util.Log;
导入android.view.view;
导入android.widget.AbsListView;
导入android.widget.AdapterView;
导入android.widget.ArrayAdapter;
导入android.widget.ListView;
导入android.widget.Toast;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.HashSet;
导入java.util.List;
导入java.util.Set;
导入georg.com.flironetest_01.Variables.Units;
/**
*由Georg于2016年3月16日创建。
*/
公共类UnitMultipleSelectorReference扩展首选项实现DialogInterface.OnClickListener,Preference.OnPreferenceClickListener{
String[]human_entries=null;
字符串[]机器\u项=空;
公众共享参考文献;
公共UnitMultipleSelectorReference(上下文上下文、属性集属性){
超级(上下文,attrs);
prev=getSharedReferences();
List humanU=new ArrayList();
List machineU=new ArrayList();
Units[]所有=Units.values();
单位(要素:全部){
humanU.add(elem.toString());
machineU.add(elem.name());
}
human_entries=humanU.toArray(新字符串[humanU.size()]);
machine_entries=machineU.toArray(新字符串[machineU.size()]);
Set mU=新的HashSet();
mU.add(Units.C.name());
mU.add(Units.K.name());
设置默认值(μ);
设置首选项单击侦听器(此);
}
布尔值[]选定=新布尔值[0];
受保护的无效onPrepareDialogBuilder(AlertDialog.Builder){
if(prev==null)
返回;
if(人|u项==null | |机器|u项==null | |人|u项.length!=machine|u项.length){
抛出新的非法状态异常(
“ListPreference需要长度相同的entries数组和entryValues数组”);
}
选定=新布尔值[human_entries.length];
for(int i=0;iimport android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import georg.com.flironetest_01.Variables.Units;
/**
* Created by Georg on 16/03/16.
*/
public class UnitMultipleSelectorPreference extends Preference implements DialogInterface.OnClickListener, Preference.OnPreferenceClickListener {
String[] human_entries = null;
String[] machine_entries = null;
public SharedPreferences prev;
public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
prev = getSharedPreferences();
List<String> humanU = new ArrayList<>();
List<String> machineU = new ArrayList<>();
Units[] all = Units.values();
for (Units elem : all) {
humanU.add(elem.toString());
machineU.add(elem.name());
}
human_entries = humanU.toArray(new String[humanU.size()]);
machine_entries = machineU.toArray(new String[machineU.size()]);
Set<String> mU = new HashSet<>();
mU.add(Units.C.name());
mU.add(Units.K.name());
setDefaultValue(mU);
setOnPreferenceClickListener(this);
}
boolean[] selected = new boolean[0];
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
if (prev == null)
return;
if (human_entries == null || machine_entries == null || human_entries.length != machine_entries.length ) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array which are both the same length");
}
selected = new boolean[human_entries.length];
for (int i = 0; i < human_entries.length; i++)
selected[i] = prefSet.contains(machine_entries[i]);
String[] stringObj = new String[human_entries.length];
int i = 0;
for(CharSequence ch : human_entries)
stringObj[i++] = ch.toString();
builder.setAdapter(new MyAdapter(getContext(), android.R.layout.simple_list_item_multiple_choice, stringObj), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog mDialog = builder.create();
mDialog.getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
mDialog.getListView().setItemsCanFocus(false);
mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Manage selected items here
ListView mParent = (ListView)parent;
if (mParent.getCheckedItemCount() >= 1)
selected[position] = mParent.isItemChecked(position);
if (mParent.getCheckedItemCount() == 0)
mParent.setItemChecked(position, true);
}
});
mDialog.show();
i = 0;
for (boolean select : selected)
mDialog.getListView().setItemChecked(i++, select);
}
@Override
public boolean onPreferenceClick(Preference preference) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext());
mBuilder.setTitle(getTitle())
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this);
onPrepareDialogBuilder(mBuilder);
return true;
}
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), "W:"+which + " | " + Arrays.toString(selected), Toast.LENGTH_SHORT).show();
switch (which) {
case -1:
if (isPersistent()) {
prefSet = new HashSet<>();
for (int i = 0; i < selected.length; i++) {
if (selected[i])
prefSet.add(machine_entries[i]);
}
getEditor().putStringSet(getKey(), prefSet).apply();
Toast.makeText(getContext(), "W:"+which + " | " + getSharedPreferences().getStringSet(getKey(),null).toString(), Toast.LENGTH_SHORT).show();
}
return;
}
}
public class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, String[] objects) {
super(context, textViewResourceId, objects);
}
@Override
public boolean isEnabled(int n) {
return true;
}
}
Set<String> prefSet;
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
super.onSetInitialValue(restorePersistedValue, defaultValue);
prev = getSharedPreferences();
if(restorePersistedValue) {
prefSet = prev.getStringSet(getKey(), new HashSet<String>());
} else {
try {
prefSet = (Set<String>)defaultValue;
if(isPersistent())
getEditor().putStringSet(getKey(), prefSet);
} catch (ClassCastException e) {
Log.e("ERROR_CAST", "Error casting the default value to Set<String>.");
}
}
}
}
MultiSelectListPreference infoPreference = findPreference("information");
infoPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (size(newValue) == 0){
return false;
}
return true;
}
});