Android 4.0 の ApiDemos でさまざまな設定アクティビティを試してみると、たとえば、PreferencesFromCode.java で一部のメソッドが非推奨になっていることがコードでわかります。
私の質問は次のとおりです。PreferenceFragment を使用すると、すべてのバージョンで機能しますか、それとも 3.0 または 4.0 以降でのみ機能しますか?
もしそうなら、2.2 と 2.3 でも機能するものを使用する必要がありますか?
Android 4.0 の ApiDemos でさまざまな設定アクティビティを試してみると、たとえば、PreferencesFromCode.java で一部のメソッドが非推奨になっていることがコードでわかります。
私の質問は次のとおりです。PreferenceFragment を使用すると、すべてのバージョンで機能しますか、それとも 3.0 または 4.0 以降でのみ機能しますか?
もしそうなら、2.2 と 2.3 でも機能するものを使用する必要がありますか?
PreferenceFragment
2.2 および 2.3 では機能しません (API レベル 11 以上のみ)。最高のユーザー エクスペリエンスを提供し、古いバージョンの Android をサポートしたい場合、ここでのベスト プラクティスは、2 つのPreferenceActivity
クラスを実装し、どちらを呼び出すかを実行時に決定することです。ただし、このメソッドには非推奨の API の呼び出しが含まれていますが、それを避けることはできません。
たとえば、次のようなものがありますpreference_headers.xml
。
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<header android:fragment="your.package.PrefsFragment"
android:title="...">
<extra android:name="resource" android:value="preferences" />
</header>
</preference-headers>
および標準preferences.xml
(より低い API レベルからあまり変更されていません):
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="...">
...
</PreferenceScreen>
次に、次の実装が必要ですPreferenceFragment
。
public static class PrefsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
PreferenceActivity
最後に、 API レベルが をサポートするかどうかに応じて、の 2 つの実装が必要ですPreferenceFragments
。
public class PreferencesActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
addPreferencesFromResource(R.xml.other);
}
}
と:
public class OtherPreferencesActivity extends PreferenceActivity {
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
}
設定画面をユーザーに表示したい時点で、どちらを開始するかを決定します。
if (Build.VERSION.SDK_INT < 11) {
startActivity(new Intent(this, PreferencesActivity.class));
} else {
startActivity(new Intent(this, OtherPreferencesActivity.class));
}
基本的に、フラグメントごとに xml ファイルがあり、API レベルが 11 未満の場合はこれらの xml ファイルを手動でロードし、両方のアクティビティで同じ設定を使用します。
@Mef PreferencesActivity と OtherPreferencesActivity の両方を必要としないように、回答をさらに単純化できます (2 つの PrefsActivities を持つことは PITA です)。
onBuildHeaders() メソッドを PreferencesActivity に配置すると、v11 より前の Android バージョンでエラーがスローされないことがわかりました。onBuildHeaders 内に loadHeadersFromResource() を配置しても、2.3.6 ではスローおよび例外は発生しませんでしたが、Android 1.6 では発生しました。しかし、いじくり回した後、次のコードがすべてのバージョンで機能するため、必要なアクティビティは 1 つだけであることがわかりました (問題が大幅に簡素化されます)。
public class PreferencesActivity extends PreferenceActivity {
protected Method mLoadHeaders = null;
protected Method mHasHeaders = null;
/**
* Checks to see if using new v11+ way of handling PrefFragments.
* @return Returns false pre-v11, else checks to see if using headers.
*/
public boolean isNewV11Prefs() {
if (mHasHeaders!=null && mLoadHeaders!=null) {
try {
return (Boolean)mHasHeaders.invoke(this);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
return false;
}
@Override
public void onCreate(Bundle aSavedState) {
//onBuildHeaders() will be called during super.onCreate()
try {
mLoadHeaders = getClass().getMethod("loadHeadersFromResource", int.class, List.class );
mHasHeaders = getClass().getMethod("hasHeaders");
} catch (NoSuchMethodException e) {
}
super.onCreate(aSavedState);
if (!isNewV11Prefs()) {
addPreferencesFromResource(R.xml.preferences);
addPreferencesFromResource(R.xml.other);
}
}
@Override
public void onBuildHeaders(List<Header> aTarget) {
try {
mLoadHeaders.invoke(this,new Object[]{R.xml.pref_headers,aTarget});
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
}
この方法では、1 つのアクティビティ、AndroidManifest.xml 内の 1 つのエントリ、および設定を呼び出すときに 1 つの行のみが必要です。
startActivity(new Intent(this, PreferencesActivity.class);
2013 年 10 月の更新: Eclipse/Lint は非推奨のメソッドの使用について警告しますが、警告は無視してください。この方法は、v11 以降のスタイル設定がなく、使用する必要がある場合にのみ使用しています。これは問題ありません。非推奨のコードを考慮したとしても、心配する必要はありません。Android は非推奨のメソッドをすぐに削除することはありません。これが発生した場合、新しいデバイスのみをターゲットにする必要があるため、このクラスはもう必要ありません。Deprecated メカニズムは、最新の API バージョンで何かを処理するためのより良い方法があることを警告するためにありますが、それを説明したら、それ以降は安全に警告を無視できます。廃止されたメソッドへのすべての呼び出しを削除すると、コードを新しいデバイスでのみ実行するように強制されるだけであり、下位互換性を維持する必要がまったくなくなります。
役立つかもしれない新しいライブラリがあります。
UnifiedPreference は、API v4 以降のすべてのバージョンの Android Preference パッケージを操作するためのライブラリです。
以前の回答の問題は、すべての設定が Honecomb より前のデバイスの 1 つの画面にスタックされることです ( の複数の呼び出しによるaddPreferenceFromResource()
)。
最初の画面をリストとして表示し、次に設定を含む画面 (設定ヘッダーの使用など) が必要な場合は、互換性のある設定の公式ガイドを使用する必要があります。
http://developer.android.com/guide/topics/ui/settings.html#PreferenceHeadersから始めて、「設定ヘッダーを使用した古いバージョンのサポート」のセクションまで進むと、もっと理にかなっています。そこのガイドは非常に役に立ち、うまく機能します。ガイドに従った明示的な例を次に示します。
したがって、HoneyComb の前に、Android システムのファイルpreference_header_legacy.xmlから始めます。
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="OLD Test Title"
android:summary="OLD Test Summary" >
<intent
android:targetPackage="example.package"
android:targetClass="example.package.SettingsActivity"
android:action="example.package.PREFS_ONE" />
</Preference>
次に、HoneyComb+ を使用する Android システム用のファイルpreference_header.xmlを作成します。
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="example.package.SettingsFragmentOne"
android:title="NEW Test Title"
android:summary="NEW Test Summary" />
</preference-headers>
次に、設定を保持するpreferences.xmlファイルを作成します...
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:key="pref_key_auto_delete"
android:summary="@string/pref_summary_auto_delete"
android:title="@string/pref_title_auto_delete"
android:defaultValue="false" />
</PreferenceScreen>
次に、SettingsActivity.javaファイルを作成します。
package example.project;
import java.util.List;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class SettingsActivity extends PreferenceActivity{
final static String ACTION_PREFS_ONE = "example.package.PREFS_ONE";
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String action = getIntent().getAction();
if (action != null && action.equals(ACTION_PREFS_ONE)) {
addPreferencesFromResource(R.xml.preferences);
}
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
addPreferencesFromResource(R.xml.preference_header_legacy);
}
}
@SuppressLint("NewApi")
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_header, target);
}
}
次に、SettingsFragmentOne.javaクラスを作成します。
package example.project;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.preference.PreferenceFragment;
@SuppressLint("NewApi")
public class SettingsFragmentOne extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
AndroidManifest.xml、<application>
タグの間にこのブロックを追加しました
<activity
android:label="@string/app_name"
android:name="example.package.SettingsActivity"
android:exported="true">
</activity>
そして最後に、<wallpaper>
タグについて...
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/description"
android:thumbnail="@drawable/ic_thumbnail"
android:settingsActivity="example.package.SettingsActivity"
/>
私はこのライブラリAAR
を使用していmavenCentral
ますGradle
。
compile 'com.github.machinarius:preferencefragment:0.1.1'