AppCompatActivityとsupport.v7.preferenceを使用して、サブ画面で設定を実装しようとしています
ドキュメントによると、別のPreferenceScreen内のすべてのPreferenceScreenはサブ画面として機能し、フレームワークはクリックされたときにそれを表示します。 http://developer.Android.com/guide/topics/ui/settings.html#Subscreens
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android">
<!-- opens a subscreen of settings -->
<PreferenceScreen
Android:key="button_voicemail_category_key"
Android:title="@string/voicemail"
Android:persistent="false">
<ListPreference
Android:key="button_voicemail_provider_key"
Android:title="@string/voicemail_provider" ... />
<!-- opens another nested subscreen -->
<PreferenceScreen
Android:key="button_voicemail_setting_key"
Android:title="@string/voicemail_settings"
Android:persistent="false">
...
</PreferenceScreen>
<RingtonePreference
Android:key="button_voicemail_ringtone_key"
Android:title="@string/voicemail_ringtone_title"
Android:ringtoneType="notification" ... />
...
</PreferenceScreen>
...
</PreferenceScreen>
これは、ネイティブのActivity、PreferenceFragment ...を使用して正常に機能しますが、AppCompatActivityおよびPreferenceFragmentCompatを使用して、Preference要素をクリックすると強調表示されるだけで、サブ画面は開きません。
私はこれをドキュメントとコードを読んで何も見つけることができませんでした...追加のコールバックを実装する必要がありますか?
編集:完全を期すために...
これが機能し、サブ画面が開きます。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(Android.R.id.content, new DemoPreferenceFragment())
.commit();
}
}
static public class DemoPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
これは機能しません/サブ画面を開きます:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(Android.R.id.content, new DemoPreferenceFragment())
.commit();
}
}
static public class DemoPreferenceFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.preferences);
}
}
}
編集:25/01/2016
support.v7.preferenceを数日間いじった後、私はここで私の発見を要約しました、それが他の人に役立つことを願っています: HowToのsupport.v7 AppCompatの設定と潜在的な欠点
PreferenceFragmentCompatのバグまたはドキュメントの不足のようです。 PreferenceScreen項目をクリックすると呼び出されるonNavigateToScreenメソッドがあります。
ただし、メソッドgetCallbackFragment()はデフォルトでnullを返すため、これを返すにはフラグメントでオーバーライドする必要があります。また、PreferenceFragmentCompat.OnPreferenceStartScreenCallbackを実装する必要があります。
public class SettingsFragment extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
public static SettingsFragment newInstance() {
return new SettingsFragment();
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.news_settings);
}
@Override
public Fragment getCallbackFragment() {
return this;
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) {
preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
return true;
}
}
ただし、最初のPreferenceScreenに戻れない場合は、別の問題が発生します。
別の方法は、ここで説明されているフラグメントを置き換えることです PreferenceFragmentCompatのPreferencesサブ画面からメイン画面に戻る方法
これは完全に機能する例ですが、これが誰かに役立つことを願っています。設定サブ画面を開いて、メイン設定画面に戻る方法について説明します。
私はAndroidオープンソースの問題トラッカー- ここでこの問題を追跡しました
公式ドキュメントには、設定サブ画面の読み込みに関するドキュメントがありません— 公式ドキュメントについては、こちらを参照してください- -
メインの詳細設定画面には2つのチェックボックスがあり、サブ画面のタイトルが無効になっています(カスタムパターン設定):-
カスタムチェックボックスをチェックすると、従属画面のタイトルが有効になります。
カスタムパターン設定をクリックすると、サブ画面が新しい画面で開きます
これがドキュメントのサンプルコードです:-
Res/xml/preferences.xmlファイル:-
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:summary="Trying intro text">
<PreferenceCategory Android:title="Settings">
<CheckBoxPreference
Android:defaultValue="true"
Android:key="defaultPress"
Android:title="Default settings" />
<CheckBoxPreference
Android:defaultValue="false"
Android:key="customKey"
Android:title="Custom" />
<PreferenceScreen
Android:key="customPrefKey"
Android:title="Custom Pattern Settings">
<PreferenceCategory
Android:key="customSettingsKey"
Android:title="Custom Settings">
<ListPreference
Android:defaultValue="4"
Android:entries="@array/initialClickArray"
Android:entryValues="@array/initialClickValues"
Android:key="initialClicks"
Android:summary="initialClicksSummary"
Android:title="No. Of Clicks" />
<ListPreference
Android:defaultValue="5"
Android:entries="@array/initialTimeArray"
Android:entryValues="@array/initialTimeValues"
Android:key="initialTimeKey"
Android:summary="Time to complete clicks"
Android:title="Time to complete" />
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
</PreferenceScreen>
MainActivity.Javaは、インターフェイスPreferenceFragmentCompat.OnPreferenceStartScreenCallback
を実装してから、メソッドをオーバーライドする必要があります-onPreferenceStartScreen
public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
private static final String TAG = MainActivity.class.getName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = null;
if (savedInstanceState == null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragment = new AdvancedSettingsFragment().newInstance("Advanced Setting");
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
PreferenceScreen preferenceScreen) {
Log.d(TAG, "callback called to attach the preference sub screen");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
AdvancedSettingsSubScreenFragment fragment = AdvancedSettingsSubScreenFragment.newInstance("Advanced Settings Subscreen");
Bundle args = new Bundle();
//Defining the sub screen as new root for the subscreen
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
fragment.setArguments(args);
ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey());
ft.addToBackStack(null);
ft.commit();
return true;
}
メイン設定画面(フラグメント)の場合:-
public class AdvancedSettingsFragment extends PreferenceFragmentCompat {
private static final String TAG = AdvancedSettingsFragment.class.getName();
public static final String PAGE_ID = "page_id";
public static AdvancedSettingsFragment newInstance(String pageId) {
AdvancedSettingsFragment f = new AdvancedSettingsFragment();
Bundle args = new Bundle();
args.putString(PAGE_ID, pageId);
f.setArguments(args);
return (f);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
final CheckBoxPreference customPreference = (CheckBoxPreference) findPreference("customKey");
final Preference customSettings = (Preference) findPreference("customPrefKey");
// First time loading the preference screen, we check the saved settings and enable/disable the custom settings, based on the custom check box
//get the customSettings value from shared preferences
if (getCustomSettings(getActivity())) {
customPreference.setChecked(true);
customSettings.setEnabled(true);
} else {
customPreference.setChecked(false);
customSettings.setEnabled(false);
}
customPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object selectedValue) {
Log.d(TAG, "Inside on preference change of custom checkbox selection " + selectedValue.getClass());
if ((Boolean) selectedValue) {
customSettings.setEnabled(true);
}else{
customSettings.setEnabled(false);
}
return true;
}
});
}
private boolean getCustomSettings(Context context) {
return PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("customKey", false);
}
}
そして最後に、従属画面のロード:
public class AdvancedSettingsSubScreenFragment extends PreferenceFragmentCompat {
private static final String TAG = AdvancedSettingsSubScreenFragment.class.getName();
public static final String PAGE_ID = "page_id";
public static AdvancedSettingsSubScreenFragment newInstance(String pageId) {
AdvancedSettingsSubScreenFragment f = new AdvancedSettingsSubScreenFragment();
Bundle args = new Bundle();
args.putString(PAGE_ID, pageId);
f.setArguments(args);
return (f);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// rootKey is the name of preference sub screen key name , here--customPrefKey
setPreferencesFromResource(R.xml.preferences, rootKey);
Log.d(TAG, "onCreatePreferences of the sub screen " + rootKey);
}
}
覚えておく必要のある非常に重要なことの1つ:
PreferenceScreenには以下が含まれている必要があります。
Android:key="name_a_unique_key"
それ以外の場合は機能しません。私は何時間も過ごしました
オーバーライドPreferenceFragmentCompat.OnPreferenceStartScreenCallback
そして、私の好みのフラグメントに以下を追加すると、私の日が救われました
@Override
public Fragment getCallbackFragment() {
return this;
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
caller.setPreferenceScreen(pref);
return true;
}
私の好みのバージョンは
compile 'com.Android.support:preference-v7:25.0.0'
Googleはついに、新しくリリースされたAndroidX設定1.1.0-alphaでこれをサポートすることを最終的に決定したようです。