web-dev-qa-db-ja.com

PreferenceFragmentは、互換性パッケージから意図的に除外されていましたか?

3.0および3.0以前のデバイスの両方に適用できる設定を作成したいと考えています。 PreferenceActivityに非推奨のメソッドが含まれていることを発見しました(これらは付属のサンプルコードで使用されていますが)が、PreferenceFragementと互換性パッケージを見て問題を解決しました。

ただし、PreferenceFragmentは互換パッケージに含まれていないようです。これが意図的なものであるかどうか、誰にも教えてもらえますか?その場合、デバイスの範囲(<3.0および> = 3.0)を簡単にターゲットにできますか、それともフープをジャンプする必要がありますか?意図的に除外されなかった場合、互換性パッケージの新しいリリースを期待できますか?または、安全に使用できる別の回避策はありますか?

乾杯

ジェームス

153
James

PreferenceActivityに非推奨のメソッドが含まれていることを発見する(ただし、これらは付属のサンプルコードで使用されています)

廃止されたメソッドは、Android 3.0から廃止されます。 Androidのすべてのバージョンで完全に問題ありませんが、Android 3.0以降でPreferenceFragmentを使用することをお勧めします。

これが意図的なものかどうか、誰にも教えてもらえますか?

私の推測では、それはエンジニアリング時間の問題ですが、それは単なる推測です。

その場合、さまざまなデバイス(つまり、<3.0および> = 3.0)を簡単にターゲットにできますか、それともフープをジャンプする必要がありますか?

私はそれが「簡単に」行われると考えています。 2つの別個のPreferenceActivity実装があります。1つは設定ヘッダーを使用し、もう1つは元のアプローチを使用するPreferenceFragmentsを使用します。必要な時点で適切なものを選択します(たとえば、ユーザーがオプションメニュー項目をクリックしたとき)。 これはサンプルプロジェクトです これを示しています。または、 このサンプルプロジェクト のように、両方のケースを処理する単一のPreferenceActivityを用意します。

意図的に除外されなかった場合、互換パッケージの新しいリリースを期待できますか?

あなたは私たちの残りの人が見つけたとき、つまりそれがいつ出荷されるかを知るでしょう。

または、安全に使用できる別の回避策はありますか?

上記を参照。

90
CommonsWare

@CommonsWareからの答えの微妙な意味は、アプリが互換性APIまたは組み込みのフラグメントAPI(SDK 11以降)を選択する必要があるということです。実際、それが「簡単に」推奨されたことです。つまり、PreferenceFragmentを使用する場合は、アプリで組み込みのフラグメントAPIを使用し、PreferenceActivityの非推奨のメソッドを処理する必要があります。逆に、アプリがコンパットを使用することが重要な場合。 PreferenceFragmentクラスがまったくないAPIに直面します。したがって、デバイスのターゲット設定は問題ではありませんが、いずれかのAPIを選択しなければならないときにフープジャンプが発生し、予期せぬ回避策にデザインを送信することになります。コンパが必要です。 APIなので、独自のPreferenceFragmentクラスを作成して、その仕組みを確認します。最悪のシナリオでは、通常の(フラグメント)レイアウトを作成し、手動でビューコンポーネントをsharedprefsにバインドします...

編集: http://grepcode.com/file/repository.grepcode.com/Java/ext/com.google.Android/android/4.0.1_r1/Android/preference/のコードを試してみた後PreferenceFragment.java?av=h -独自のPreferenceFragmentの作成は行われません。 「保護された」の代わりにPreferenceManagerでpackage-privateを自由に使用することが主なブロッカーのようです。セキュリティやモチベーションがあるようには見えませんし、単体テストには向いていませんが、タイピングが少ないと思います...

EDIT v2:実際にそれが起こり、動作しました。互換性API JARでコードを機能させることは間違いなく頭痛の種でした。 com.Android.preferenceパッケージの約70%をSDKからアプリにコピーしてから、Androidの通常の品質Javaコードを使用します。SDKのv14を使用しました。 Googのエンジニアにとって、私がやったことをはるかに簡単にしたはずです。私が聞いたのとは反対に、鉛Android.

ところで-私は「デバイスをターゲットにすることは問題ではない」と言いましたか?それは完全に... com.Android.preferenceを使用する場合、大きなリファクタリングなしで互換性APIと交換することはできません。楽しいログ!

21
Tenacious

CommonsWareの答えとTenaciousの観察に基づいて、現在のすべてのAndroid APIバージョンを最小限の手間とコードまたはリソースの重複なしでターゲットにできる単一の子孫クラスソリューションを作成しました。参照してください。ここで関連する質問に対する私の答え: PreferenceActivity Android 4.0 and以前

または私のブログ: http://www.blackmoonit.com/2012/07/all_api_prefsactivity/

4.0.3および4.0.4を実行する2つのタブレット、4.0.4および2.3.3を実行する電話、および1.6を実行するエミュレーターでテスト済み。

16

Machinariusの PreferenceFragment-Compat を参照してください。 gradleで簡単に立ち寄ることができ、そこにあることも忘れてしまいました。

compile 'com.github.machinarius:preferencefragment:0.1.1'

重要な更新:v7 support library最新リビジョン にはネイティブ PreferenceFragmentCompat

10
theblang

2015年8月、Googleは新しい Preference Support Library v7 をリリースしました。

これで、任意のActivityまたはAppCompatActivityPreferenceFragmentCompat を使用できます

public static class PrefsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }
}

テーマにpreferenceThemeを設定する必要があります。

<style name="AppTheme" parent="@style/Theme.AppCompat.Light">
  ...
  <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>

このようにして、アクティビティの他の部分に影響を与えることなく、preferenceThemeをカスタマイズして、各設定タイプに使用されるレイアウトのスタイルを設定できます。

10

Tenaciousの答えは正しいですが、ここにいくつかの詳細があります。

「通常のレイアウトを作成し、ビューコンポーネントを共有設定に手動でバインド」できないのは、Android.preferences APIにいくつかの驚くべき省略があるからです。 PreferenceActivityとPreferenceFragmentは、どちらも重要な非パブリックPreferenceManagerメソッドにアクセスできます。これがないと、独自の設定UIを実装できません。

特に、XMLファイルからPreference階層を構築するには、PreferenceManagerを使用する必要がありますが、PreferenceManagerのコンストラクターはすべてパッケージプライベートまたは非表示になっています。 Preference onClickリスナーをアクティビティにアタッチする方法もパッケージプライベートです。

また、Android APIの非公開メソッドは実際にはSDKから省略されているため、実装をこっそりAndroid.preferencesパッケージに配置してもこの問題を回避できません。 Tenaciousが言うように、唯一の選択肢は、少なくとも15のクラス、5つのレイアウト、同様の数のstyle.xmlとattrsを含むAndroid.preferenceパッケージ全体をフォークすることです。 xml要素。

したがって、元の質問に答えるために、GoogleがPreferenceFragmentを互換性パッケージに含めなかった理由は、彼らがTenaciousと私とまったく同じ難しさを抱えていたからです。 Googleでさえ、過去のプラットフォームに戻ってこれらのメソッドを公開することはできません(ただし、将来のリリースではそうすることを望みます)。

7
mhsmith

Preferencesをアプリケーションの設計に統合し、2.3 Androidのサポートを維持する必要がありました。だから、まだPreferencesFragmentが必要だった。

いくつかの検索の後、 Android-support-v4-preferencefragment libを見つけました。 Tenaciousが言ったように、このライブラリは元のPreferencesFragmentをコピーしてリファクタリングするための時間を大幅に節約します。正常に機能し、ユーザーは好みを楽しむことができます。

2
neworld

私のアプリのターゲットはAPI +14ですが、いくつかの派手なナビゲーションにサポートライブラリを使用しているため、Android.app.Fragmentを使用できず、Android.support.v4.app.Fragmentを使用する必要がありましたが、PreferenceFragmentコードビハインドに大きな変更を加えることなく、所定の場所に配置します。

サポートライブラリとPreferenceFragmentの両方の世界を持つための私の簡単な修正:

private Android.support.v4.app.Fragment fragment;
private Android.app.Fragment nativeFragment = null;

private void selectItem(int position) {
    fragment = null;
    boolean useNativeFragment = false;
    switch (position) {
    case 0:
        fragment = new SampleSupprtFragment1();
        break;
    case 1:
        fragment = new SampleSupprtFragment2();
        break;
    case 2:
        nativeFragment = new SettingsFragment();
        useNativeFragment = true;
        break;
    }
    if (useNativeFragment) {
        Android.app.FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
            .replace(R.id.content_frame, nativeFragment).commit();
    } else {
        if (nativeFragment != null) {
            getFragmentManager().beginTransaction().remove(nativeFragment)
                .commit();
            nativeFragment = null;
        }
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment).commit();
    }
}
2
Mohsen Afshin