内部PreferenceScreen无法使用PreferenceFragmentCompat打开

mad*_*mad 23 android android-appcompat android-support-library preference-v7

我的PreferenceFragmentCompat的内部PreferenceScreen没有显示,或者似乎忽略了点击事件.

我创造了MyPreferenceFragment那个extends PreferenceFragmentCompat

public class MyPreferenceFragment extends PreferenceFragmentCompat {
 @Override
  public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    addPreferencesFromResource(R.xml.preferences);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,我改变了我的主题,在styles.xml

<style name="AppTheme" parent="@style/Theme.AppCompat.Light">
  <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>
Run Code Online (Sandbox Code Playgroud)

最后创建我的preferences.xml文件

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference android:title="Check Me"/>
    <PreferenceScreen android:title="My Screen"> <!-- This is not opening -->
        <EditTextPreference android:title="Edit text" />
    </PreferenceScreen>
</PreferenceScreen>
Run Code Online (Sandbox Code Playgroud)

build.gradle我添加了两个:

compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:preference-v7:23.0.1'
Run Code Online (Sandbox Code Playgroud)

活动的代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
Run Code Online (Sandbox Code Playgroud)

activity_main.xml中

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment"
    android:name="com.mando.preferenceapp.MyPreferenceFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
Run Code Online (Sandbox Code Playgroud)

测试上面的代码我无法打开/进入首选项屏幕.我错过了什么吗?为什么这不起作用?

mad*_*mad 37

花了很多时间尝试,搜索并谢天谢地,在支持库的创建者的帮助下.我成功地使它成功了.

步骤1. Activity

public class MyActivity extends AppCompatActivity implements
        PreferenceFragmentCompat.OnPreferenceStartScreenCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            // Create the fragment only when the activity is created for the first time.
            // ie. not after orientation changes
            Fragment fragment = getSupportFragmentManager().findFragmentByTag(MyPreferenceFragment.FRAGMENT_TAG);
            if (fragment == null) {
                fragment = new MyPreferenceFragment();
            }

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.fragment_container, fragment, MyPreferenceFragment.FRAGMENT_TAG);
            ft.commit();
        }
    }

    @Override
    public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
                                           PreferenceScreen preferenceScreen) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        MyPreferenceFragment fragment = new MyPreferenceFragment();
        Bundle args = new Bundle();
        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
        fragment.setArguments(args);
        ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey());
        ft.addToBackStack(preferenceScreen.getKey());
        ft.commit();
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

提示.

  • 不要添加片段,xml因为方向更改会导致崩溃.
  • 处理活动/片段添加的重新创建,onCreate以避免在首选项屏幕内丢失您的片段.
  • 片段的主机活动应该实现 PreferenceFragmentCompat.OnPreferenceStartScreenCallback并重新创建同一实例的片段.

第2步. PreferenceFragment

public class MyPreferenceFragment extends PreferenceFragmentCompat {

    public static final String FRAGMENT_TAG = "my_preference_fragment";

    public MyPreferenceFragment() {
    }

    @Override
    public void onCreatePreferences(Bundle bundle, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);
    }

}
Run Code Online (Sandbox Code Playgroud)

提示.

  • 使用该方法setPreferencesFromResource并利用rootKey每个屏幕的优势.这样您的代码将被正确重用.
  • 请记住,如果你findPreference的片段中有代码,它应该有null你在内部屏幕时的检查,这将不会给你任何东西.

现在缺少的是在动作栏中执行后退箭头(主动作),但这本身并不起作用;-)

我还创建了一个包含所有这些代码的演示应用程序,您可以在github上找到它.


小智 7

解决方案是启动同一类但具有不同根密钥的另一个片段.不涉及任何活动.

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey){
    if(getArguments() != null){
        String key = getArguments().getString("rootKey");
        setPreferencesFromResource(R.xml.preferences, key);
    }else{
        setPreferencesFromResource(R.xml.preferences, rootKey);
    }
}

@Override
public void onNavigateToScreen(PreferenceScreen preferenceScreen){
    ApplicationPreferencesFragment applicationPreferencesFragment = new ApplicationPreferencesFragment();
    Bundle args = new Bundle();
    args.putString("rootKey", preferenceScreen.getKey());
    applicationPreferencesFragment.setArguments(args);
    getFragmentManager()
            .beginTransaction()
            .replace(getId(), applicationPreferencesFragment)
            .addToBackStack(null)
            .commit();
}
Run Code Online (Sandbox Code Playgroud)


squ*_*rel 5

我做的略有不同,我正在为每个屏幕启动一个新活动.这似乎需要更少的黑客攻击:无需混淆交换片段和背景颜色.您还可以获得活动更改动画作为奖励!

public class PreferencesActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
    final static private String KEY = "key";

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

        setContentView(R.layout.preferences);

        setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) actionBar.setDisplayHomeAsUpEnabled(true);

        if (savedInstanceState != null)
            return;

        Fragment p = new PreferencesFragment();

        String key = getIntent().getStringExtra(KEY);
        if (key != null) {
            Bundle args = new Bundle();
            args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, key);
            p.setArguments(args);
        }

        getSupportFragmentManager().beginTransaction()
                .add(R.id.preferences, p, null)
                .commit();
    }

    @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) {
        Intent intent = new Intent(PreferencesActivity.this, PreferencesActivity.class);
        intent.putExtra(KEY, preferenceScreen.getKey());
        startActivity(intent);
        return true;
    }

    @Override public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public static class PreferencesFragment extends PreferenceFragmentCompat implements ... {

        private static final String FRAGMENT_DIALOG_TAG = "android.support.v7.preference.PreferenceFragment.DIALOG";
        private String key;


        @Override public void onCreatePreferences(Bundle bundle, String key) {
            setPreferencesFromResource(R.xml.preferences, this.key = key);
        }

        // this only sets the title of the action bar
        @Override public void onActivityCreated(Bundle savedInstanceState) {
            ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
            if (actionBar != null) actionBar.setTitle((key == null) ? "Settings" : findPreference(key).getTitle());
            super.onActivityCreated(savedInstanceState);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="0dp"
    android:orientation="vertical"
    android:padding="0dp"
    android:id="@+id/preferences">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary" />

    <!-- preference fragment will be inserted here programmatically -->

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

8354 次

最近记录:

7 年,2 月 前