我想自定义ListPreference
让用户从他的应用程序中进行选择。这目前效果很好。除了:
- 过滤掉系统应用程序(我已经过滤了,
(info.activityInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1
但它仍然显示系统应用程序) - 图标(“检查所有”项目除外;我想我需要以某种方式操作布局?;找到解决方案: http: //www.devmil.de/ ?p=63 )
首选项.xml
<com.example.gui.preference.ApplicationListPreference
android:key="pref_key_choose_apps"
android:dependency="pref_key_enable_server"
android:title="@string/choose_apps"
android:dialogTitle="@string/choose_apps"
android:entries="@array/pref_entries_choose_apps"
android:entryValues="@array/pref_values_choose_apps"
example:checkAll="#ALL#" />
数组.xml
<string-array name="pref_values_choose_apps">
<item>#ALL#</item>
</string-array>
<string-array name="pref_entries_choose_apps">
<item>All</item>
</string-array>
属性.xml
<declare-styleable name="ApplicationListPreference">
<attr format="string" name="checkAll" />
</declare-styleable>
应用程序列表首选项:
public class ApplicationListPreference extends ListPreference {
private final static String SEPARATOR = ";";
private String checkAllKey = null;
private boolean[] mClickedDialogEntryIndices;
public ApplicationListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
checkAllKey = context.obtainStyledAttributes(attrs, R.styleable.ApplicationListPreference).getString(R.styleable.ApplicationListPreference_checkAll);
List<CharSequence> entries = new ArrayList<CharSequence>();
for (CharSequence entry : getEntries()) {
entries.add(entry);
}
List<CharSequence> entryValues = new ArrayList<CharSequence>();
for (CharSequence entryValue : getEntryValues()) {
entryValues.add(entryValue);
}
Intent intentFilter = new Intent(Intent.ACTION_MAIN, null);
intentFilter.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = context.getPackageManager();
List<ResolveInfo> appList = pm.queryIntentActivities(intentFilter, PackageManager.PERMISSION_GRANTED);
Collections.sort(appList, new ResolveInfo.DisplayNameComparator(pm));
for (ResolveInfo info : appList) {
if ((info.activityInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1) {
entryValues.add(info.activityInfo.packageName);
entries.add(info.loadLabel(pm).toString());
}
}
setEntries(entries.toArray(new CharSequence[entries.size()]));
setEntryValues(entryValues.toArray(new CharSequence[entryValues.size()]));
}
public ApplicationListPreference(Context context) {
this(context, null);
}
@Override
public void setEntries(CharSequence[] entries) {
super.setEntries(entries);
mClickedDialogEntryIndices = new boolean[entries.length];
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
CharSequence[] entries = getEntries();
CharSequence[] entryValues = getEntryValues();
if (entries == null || entryValues == null || entries.length != entryValues.length) {
throw new IllegalStateException("Irregular array length");
}
restoreCheckedEntries();
builder.setMultiChoiceItems(entries, mClickedDialogEntryIndices, new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which, boolean val) {
if (isCheckAllValue(which) == true) {
checkAll(dialog, val);
}
mClickedDialogEntryIndices[which] = val;
}
});
}
private boolean isCheckAllValue(int which) {
final CharSequence[] entryValues = getEntryValues();
if (checkAllKey != null) {
return entryValues[which].equals(checkAllKey);
}
return false;
}
private void checkAll(DialogInterface dialog, boolean val) {
ListView lv = ((AlertDialog) dialog).getListView();
int size = lv.getCount();
for (int i = 0; i < size; i++) {
lv.setItemChecked(i, val);
mClickedDialogEntryIndices[i] = val;
}
}
public String[] parseStoredValue(CharSequence val) {
if (val == null || "".equals(val)) {
return null;
}
return ((String) val).split(SEPARATOR);
}
private void restoreCheckedEntries() {
CharSequence[] entryValues = getEntryValues();
String[] vals = parseStoredValue(getValue());
if (vals != null) {
List<String> valuesList = Arrays.asList(vals);
for (int i = 0; i < entryValues.length; i++) {
CharSequence entry = entryValues[i];
if (valuesList.contains(entry)) {
mClickedDialogEntryIndices[i] = true;
}
}
}
}
@Override
protected void onDialogClosed(boolean positiveResult) {
ArrayList<String> values = new ArrayList<String>();
CharSequence[] entryValues = getEntryValues();
if (positiveResult && entryValues != null) {
for (int i = 0; i < entryValues.length; i++) {
if (mClickedDialogEntryIndices[i] == true) {
String val = (String) entryValues[i];
if (checkAllKey == null || (val.equals(checkAllKey) == false)) {
values.add(val);
}
}
}
String value = join(values);
if (callChangeListener(value)) {
setValue(value);
}
}
}
protected static String join(Iterable<? extends Object> pColl) {
Iterator< ? extends Object > oIter;
if (pColl == null || (!(oIter = pColl.iterator()).hasNext())) {
return "";
}
StringBuilder oBuilder = new StringBuilder(String.valueOf(oIter.next()));
while (oIter.hasNext()) {
oBuilder.append(SEPARATOR).append(oIter.next());
}
return oBuilder.toString();
}
public static boolean contains(String straw, String haystack) {
for (String val : haystack.split(SEPARATOR)) {
if (val.equals(straw)) {
return true;
}
}
return false;
}
}