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


153

3.0と3.0以前のデバイスの両方に適用できる設定を書きたいと思っています。PreferenceActivity非推奨のメソッドが含まれていることがわかったため(これらは添付のサンプルコードで使用されています)、PreferenceFragement問題を解決するために互換性パッケージを調べました。

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

乾杯

ジェームズ


1
これは、問題を解決するための私のアプローチです:stackoverflow.com/questions/14076073/...
ECV

PreferenceFragmentあなたが忘れる第三者がそこにさえいる誰かを作った。私の答えをください。
theblang 2014

Chris Banesは彼のブログのコメントでこれ対処しています。その理由は"Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
次のとおりである

私の更新された答えを見てください。PreferenceFragmentCompat最近サポートライブラリに追加されました。
theblang 2015

回答:


90

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

廃止されたメソッドは、Android 3.0以降廃止されました。Androidのすべてのバージョンで問題なく動作しますが、方向はPreferenceFragmentAndroid 3.0以降で使用することです。

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

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

もしそうなら、私は簡単にデバイスの範囲をターゲティングできますか(例:3.0未満および3.0以上)、またはフープをジャンプする必要がありますか?

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

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

それが出荷されるかどうか、いつ出荷されるか、つまり、残りの部分がいつになるかがわかります。

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

上記を参照。


乾杯マーク。いくつかの場所(android google groupとあなたのブログ)でこれについてコメントしているのを見ましたが、(状況を考えれば)確実な回答を求めていました。
ジェームズ

@ジェームズ:ええ、設定XMLの定義に問題があり<include>ます。設定XMLで動作するかどうかわからないので、フラグメントとして適切に機能し、一緒に連結されるものを取得します。ところで、あなたが購読者であれば、このプロジェクトを参照する本の更新は数分前に発表されました。
CommonsWare 2011年

7
申し訳ありませんが、あなたがここで何を言おうとしているのか本当にわかりません。あなたは何も答えず、単にコメント/推測/問題に関係のない無関係な外部リンクを参照します。質問は省略が、意図的だったかどうかであるなしに PreferenceFragmentが存在しないならば、どちらも(getSupportFragmentManagerしませんので、あなたが説明してきた方法で、PreferenceActivityを拡張する手立てがないPreferenceFragmentの互換バージョン)、または他のいずれかの方法そもそもフラグメントを使用する必要があります。
Justin Buser、

8
@JustinBuser:「問題は、省略が意図的なものであったかどうかです」-Googleでその作業に答えることができる唯一の人々。Googleに就職して、ぜひ見つけてみてください。「説明したようにPreferenceActivityを拡張する手段はありません」-私がリンクしたコードをダウンロードしてください。
CommonsWare 2012

9
@JustinBuser記録として、マークは私の質問に答えました。それは私が彼の答えを受け入れることから明らかです。
ジェームズ

21

@CommonsWareからの回答の微妙な意味は、アプリは互換性APIまたは組み込みのフラグメントAPI(SDK 11以来)のどちらかを選択する必要があるということです。実際、それが「簡単に」推奨されていることです。つまり、PreferenceFragmentを使用する場合、アプリは組み込みフラグメントAPIを使用し、PreferenceActivityで非推奨のメソッドを処理する必要があります。逆に、アプリで互換性を使用することが重要な場合。PreferenceFragmentクラスがないことに直面するAPI。したがって、デバイスをターゲットにすることは問題ではありませんが、いずれかのAPIを選択し、予期しない回避策に設計を提出する必要がある場合に、フープジャンプが発生します。互換が必要です。APIなので、独自のPreferenceFragmentクラスを作成して、それがどのように機能するかを確認します。最悪のシナリオでは私は

編集: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を使用しました。Androidの一部のリードエンジニアがこのトピックについて言っているのを聞いたのとは対照的に、私が行った作業はGoogエンジニアにとってはるかに簡単でした。

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


もっと率直にさせてください。あなたが気にしているのがHoneycomb以上(市場シェアはどれくらいか)をターゲットにしている場合は、@ Commonswareからの回答に投票してください!今日市場に出回っているAndroidデバイスの大部分を気にする場合は、私の返答を読む必要があります。
粘り強い

4
あなたはこれをどのようにしたかを喜んで共有しますか?まったく同じ問題が発生しています。PreferenceActivityのみがローダーを使用する必要があるため、互換性ライブラリを使用する必要があります。
からくり

3
@Tenacious私はあなたの調査が好きです-よくやった。ただし、誰かがあなたの最初のコメントにレコードを直接設定する必要があると思います-Commonswareのコードは、プレ&ポストHCデバイスで動作します-そのようなコメントをする前に、最初に試してください。実現する必要があるのは、以前のデバイスをサポートするために実行時に使用される遅延バインディングです。実行時のバージョンチェックは、OSの両方のファミリーをサポートします-これは一般的なAndroidパターンです(私が好きなパターンではありませんが、Android開発者が学び、慣れるために重要です)...したがって、将来の読者には-ドンどちらのアプローチも却下しないでください。
Richard Le Mesurier 2012年

@RichardLeMesurierですが、DrawerLayout内で設定を行う必要がある場合、Commonswareのメソッドは適切ではありません
neworld

16

CommonsWareの回答とTenaciousの観察に基づいて、最小限の手間でコードやリソースの重複なしに、現在のすべてのAndroid APIバージョンをターゲットにできる単一の子孫クラスソリューションを思いつきました。こちらの関連​​質問への私の回答をご覧ください: PreferenceActivity Android 4.0およびそれ以前

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

4.0.3と4.0.4を実行している2つのタブレット、および4.0.4と2.3.3を実行している電話、および1.6を実行しているエミュレータでテストされています。



10

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

これで、PreferenceFragmentCompatをany ActivityまたはAppCompatActivity

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


1
関数が見当たらないと思います:onCreatePreferences
android developer

これは私の日を救った!なぜこれがAndroid Studioのプロジェクト構造に表示されないのでしょうか... ?? ところであなたのコードにタイプミスがあります。「PreferenceFragmentCompatを拡張する」である必要があります
Grzegorz D.

7

テナシャスの答えは正しいですが、詳細は次のとおりです。

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

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

また、Android APIの非公開メソッドは実際にはSDKから省略されているため、実装をandroid.preferencesパッケージにこっそり入れることによってこれを回避することはできません。リフレクションとダイナミックプロキシを含む少しの創造性があれば、それらを手に入れることができます。Tenaciousが言うように、唯一の代替手段は、少なくとも15のクラス、5つのレイアウト、および同数のstyle.xmlとattrs.xml要素を含むandroid.preferenceパッケージ全体をフォークすることです。

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


2

マイアプリのターゲットは、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

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

いくつか検索した後、android-support-v4-preferencefragment lib を見つけました。Tenaciousが言ったように、このlibはオリジナルのPreferencesFragmentをコピーしてリファクタリングするための多くの時間を節約します。正常に動作し、ユーザーは設定を楽しむことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.