web-dev-qa-db-ja.com

onPreferenceClickがトリガーされたときにListPreferenceを動的に入力する方法は?

使用可能な言語のリストを表示するlanguageとしてListPreferenceを持つ設定アクティビティがあります。 onCreateが呼び出されたときにリストを埋めることができますが、ユーザーがクリックしたときにリストを埋めたいです。

this is the Java code

public class SettingsActivity extends PreferenceActivity implements OnPreferenceClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

    }

    @Override
    public boolean onPreferenceClick(Preference preference) {

        if((preference instanceof ListPreference) && (preference.getKey().equals("language"))){
            ListPreference lp = (ListPreference)preference;
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
            return true;
        }
        return false;

    }
}

これはsettings.xml(設定):

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <PreferenceCategory Android:title="General Settings">
        <CheckBoxPreference Android:key="enabled"  Android:title="Application Status" Android:summary="Enable or disable the application" />
         <ListPreference 
         Android:key="language" 
         Android:title="Language"
         Android:dialogTitle="Application language" 
         Android:summary="Select the Application language"
         />
    </PreferenceCategory>
</PreferenceScreen>

検索しましたが結果が見つかりませんでした!そのリストをクリックするたびに例外が発生します。

30
Abdullah

ListPreferenceオブジェクトが初期化されていないため、例外が発生しています。XMLでentriesおよびentryValues属性を設定するか、onCreate()でプログラム的に設定する必要があります。

最初のListPreferenceオブジェクトが初期化された後でリスト内の項目を動的に変更できるようにする場合は、OnPreferenceClickListenerを直接ListPreferenceオブジェクトにアタッチする必要があります。 XMLで指定したキーを使用して、設定へのハンドルを取得します。

entries配列とentryValues配列にデータを入力するコードは、onCreate()onPreferenceClickの両方で実行する必要があるため、次の場所に抽出するのが合理的です別のメソッド-setListPreferenceData()重複を避けるため。

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

        final ListPreference listPreference = (ListPreference) findPreference("language");

        // THIS IS REQUIRED IF YOU DON'T HAVE 'entries' and 'entryValues' in your XML
        setListPreferenceData(listPreference);

        listPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {

                setListPreferenceData(listPreference);
                return false;
            }
        });
    }

    protected static void setListPreferenceData(ListPreference lp) {
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
    }
}

ここ は、Googleの別の例です DeskClock アプリ:

49
ccpizza

PreferenceFragment&Java キーを設定するではなくキーを設定するPreferenceActivity&XMLhttps://stackoverflow.com/a/13828912/1815624 に示されているように、この回答は以下に基づいています:

最初のListPreferenceオブジェクトが初期化された後でリスト内の項目を動的に変更できるようにする場合は、OnPreferenceClickListenerを直接ListPreferenceオブジェクトにアタッチする必要があります。お持ちのキーJava source(_CUSTOM_LIST_として)で指定)を使用して、設定へのハンドルを取得します。

entries配列とentryValues配列を生成するコードは、onCreate()onPreferenceClickの両方で実行する必要があるため、それを別のメソッド-setListPreferenceData()重複を避けるため。

_/**
 * This fragment shows data and sync preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class myCustomPreferenceFragment extends PreferenceFragment {

    final private String CUSTOM_LIST= "custom_list";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_custom_frag);

        PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");

        final ListPreference lp = setListPreferenceData((ListPreference) findPreference(CUSTOM_LIST), getActivity());

        lp.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {

                setListPreferenceData(lp, getActivity());
                return false;
            }
        });
        setHasOptionsMenu(true);
        targetCategory.addPreference(lp);

        bindPreferenceSummaryToValue(targetCategory);
        bindPreferenceSummaryToValue(lp);
    }

    protected ListPreference setListPreferenceData(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Number Of blahs");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Number of Blah objects");
        lp.setKey(CUSTOM_LIST);
        return lp;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == Android.R.id.home) {
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
_

XMLレイアウト:

_<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <PreferenceCategory
        Android:key="CUSTOM_FRAG"
        Android:title="Some Options">

    </PreferenceCategory>
</PreferenceScreen>
_
6
CrandellWS

ListPreferenceを拡張することで問題を解決しました。とてもシンプルでした。

public class DListPref extends ListPreference
{
    public interface LoadingListener
    {
        void setData(ListPreference lp);
    }

    LoadingListener TheLL;

    public void setLoadingListener(LoadingListener l)
    {
        TheLL = l;
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder)
    {
        if(TheLL!=null)
        {
            TheLL.setData(this);
        }
        super.onPrepareDialogBuilder(builder);
    }

    //Do not mind the rest of this class, as they are auto-generated boilerplate code.
    public DListPref(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public DListPref(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    public DListPref(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public DListPref(Context context)
    {
        super(context);
    }
}

その後、XMLで名前をクラスに変更しました。

<my.company.DListPref
    Android:defaultValue="-1"
    Android:key="damn"
    Android:title="vegetables"/>

そして、私は単にonCreateでこれを行いました。

        DListPref lp = (DListPref) findPreference("damn");

        lp.setLoadingListener(new DListPref.LoadingListener()
        {
            @Override
            public void setData(ListPreference lp)
            {
                lp.setEntries(new String[]{"doge", "wow"});
                lp.setEntryValues(new String[] {"1", "2"});
                lp.setDefaultValue("1");
            }
        });

すぐに働きました。実際、こんなに簡単にできるとは思いもしませんでした。

1
Damn Vegetables