web-dev-qa-db-ja.com

プログラムでXMLで作成されたAndroid Preferenceのクリックを開くまたはシミュレートする方法は?

私はAndroid設定がXMLで宣言され、addPreferencesFromResourceがロードされたアプリケーションを持っています。ユーザーは設定を開き、各項目をクリックして編集できます。すべて機能します。

私の好みは次のとおりです。

        <ListPreference Android:key="abc"
            Android:title="@string/abc"
            Android:summary="@string/cde"
            Android:persistent="true"/>

どうすればユーザーに設定ダイアログを自動的に表示できますか(ユーザーが設定画面に移動してクリックする必要はありませんか?)。

私は試した ( (Android.preference.DialogPreference) prefMgr.findPreference( "abc" )).showDialog(null)、しかしそれは保護されたメソッドであると言います...?私のメインアクティビティ(PreferenceActivity)から呼び出したため、明らかに機能しません。しかし、他にどのように?

編集

私はfindViewByIdを使用して設定にアクセスするという考えで2つのスレッド( 1 および 2 )を見つけましたが、成功しませんでした。それは常にnullを返します(私にも同じです)。

コードからこれを行う可能性は本当にないようです。

44
Markus

ListPreferenceを拡張してダイアログを作成し、ListPreferenceの保護されたshowDialogメソッドを呼び出す独自のパブリックメソッドを含めることができます。何かのようなもの:

public void show()
{
    showDialog(null);
}

この方法では、PreferenceGroupsがあるときにgetOrder()が機能しないという問題が発生することはありません。何人かの人々がコメントでコメントに指摘しているからです。

これは、showDialogメソッドが保護されているすべての設定タイプで実行できます。

23
Jabari

より明確なアプローチについては、新しい承認済みの回答を参照してください。これは機能していましたが、実際にクリーンな方法ではありませんでした。


くそー、それは私に数時間かかりましたが、最終的にはうまくいきます。

解決策は、文書化されていない呼び出し public void onItemClick (...) です。これはいくつかの引数を取り、 この質問 で指摘されているように、呼び出す要素のインデックスに従ってクリックをシミュレートするために使用できます。

私の問題は、呼び出したい項目がXML構造に深くネストされていることでした。しかし、解決策は非常に簡単です:開きたいアイテムがあるkeyPreferenceScreenを追加します。

<PreferenceScreen
    Android:key="pref_key"
    ....
    />
    <ListPreference Android:key="abc"
        Android:title="@string/abc"
        Android:summary="@string/cde"
        Android:persistent="true"/>

</PreferenceScreen>

そして、あなたはちょうど次のことができます:

// the preference screen your item is in must be known
PreferenceScreen screen = (PreferenceScreen) findPreference("pref_key");

// the position of your item inside the preference screen above
int pos = findPreference("abc").getOrder();

// simulate a click / call it!!
screen.onItemClick( null, null, pos, 0 ); 

そしてダイアログがポップアップします!

PreferenceScreen a Preferenceが入っているのはいいことです(つまり、Preferenceがどこにあるかを知る必要はありません)。自動ダイアログを静かに壊し、気付かれない場合があります(テストされていない場合)。

このために、すべての設定を検索してPreferenceScreenを返す関数を作成しました。これは、設定がオンになっているため、PreferenceScreenにキーを設定する必要はありません。

private PreferenceScreen findPreferenceScreenForPreference( String key, PreferenceScreen screen ) {
    if( screen == null ) {
        screen = getPreferenceScreen();
    }

    PreferenceScreen result = null;

    Android.widget.Adapter ada = screen.getRootAdapter();
    for( int i = 0; i < ada.getCount(); i++ ) {
        String prefKey = ((Preference)ada.getItem(i)).getKey();
        if( prefKey != null && prefKey.equals( key ) ) {
            return screen;
        }
        if( ada.getItem(i).getClass().equals(Android.preference.PreferenceScreen.class) ) {
            result = findPreferenceScreenForPreference( key, (PreferenceScreen) ada.getItem(i) );
            if( result != null ) {
                return result;
            }
        }
    }

    return null;
}

private void openPreference( String key ) {
    PreferenceScreen screen = findPreferenceScreenForPreference( key, null );
    if( screen != null ) {
        screen.onItemClick(null, null, findPreference(key).getOrder(), 0);
    }
}

// With this, you can call your `Preference` like this from code, you do
// not even have to give your PreferenceScreen a key!
openPreference( "abc" );
37
Markus
 PreferenceScreen preferenceScreen  = (PreferenceScreen) findPreference("pref_key");
    final ListAdapter listAdapter = preferenceScreen.getRootAdapter();
         EditTextPreference editPreference = (EditTextPreference)   findPreference("set_password_preference");

    final int itemsCount = listAdapter.getCount();
    int itemNumber;
    for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) {
        if (listAdapter.getItem(itemNumber).equals(editPreference)) {
            preferenceScreen.onItemClick(null, null, itemNumber, 0);
            break;
        }
    }
     }
 }  
8
Deepak Goel

サポートライブラリを使用すると、 PreferenceManager.showDialog(Preference) でダイアログを簡単に開くことができます。

PreferenceFragmentCompatで:

getPreferenceManager().showDialog(findPreference("pref_name"));

サポート設定パッケージには多くの問題があることに注意してください: 非マテリアルスタイル および 開いているダイアログで回転するとクラッシュします

6
headsvk

deepak goelの答え:

private void openPreference(String key) {
    PreferenceScreen preferenceScreen = getPreferenceScreen();
    final ListAdapter listAdapter = preferenceScreen.getRootAdapter();

    final int itemsCount = listAdapter.getCount();
    int itemNumber;
    for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) {
        if (listAdapter.getItem(itemNumber).equals(findPreference(key))) {
            preferenceScreen.onItemClick(null, null, itemNumber, 0);
            break;
        }
    }
}
3
azendh