0

我想自定义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;
    }

}
4

1 回答 1

1

对于系统应用过滤,您应该检查flagsApplicationInfo 而不是 ActivityInfo。尝试修改这个:

(info.activityInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1

(info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1
于 2012-10-15T03:40:55.330 回答