17

我从 support-v7 库PreferenceFragment中使用。 在我的活动中。一切顺利,直到我打开一个嵌套的. 在打开的屏幕中是隐藏的。ActionBarActivity
ToolbarPreferenceScreen
Toolbar

也许有人知道这个问题的解决方法?

首选项 xml 文件:

<?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Main category" >

        <EditTextPreference
            android:defaultValue="defaultValue"
            android:key="key_global_setting"
            android:title="Global title" />        

    </PreferenceCategory>

    <PreferenceCategory android:title="Nested screens" >        

        <PreferenceScreen
            android:persistent="false"
            android:title="@string/settings_facility_title" >

        <CheckBoxPreference
            android:defaultValue="false"
            android:key="nested_screen_1_1"
            android:title="Nested screen 1.1 check box" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="nested_screen_1_2"
            android:title="Nested screen 1.2 check box" />
        </PreferenceScreen>

        <PreferenceScreen
            android:persistent="false"
            android:title="@string/settings_menu_screen_title" >

         <CheckBoxPreference
            android:defaultValue="true"
            android:key="nested_screen2"
            android:title="Nested screen 2 check box" />
        </PreferenceScreen>        

    </PreferenceCategory>    

</PreferenceScreen> 

活动布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"    
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SettingsScreen" >

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/Toolbar" />

    <FrameLayout
        android:id="@+id/contentSettings"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
4

4 回答 4

27

我自己找到了解决方案。我对所有这些嵌套的PreferenceScreen's. 我只是对不同的xml-preference文件进行了分离,创建了一个Fragment扩展的附加文件,PreferenceFragment并在那里显示了一个适当的嵌套首选项屏幕。
也许有人会发现这很有用。

Github 来源链接。

下面的一些代码示例:

main_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Main category" >

        <EditTextPreference
            android:defaultValue="defaultValue"
            android:key="key_global_setting"
            android:title="Global title" />

    </PreferenceCategory>

    <PreferenceCategory android:title="Nested screens" >

        <Preference
            android:key="NESTED_KEY1"
            android:persistent="false"
            android:title="Nested screen #1" />

        <Preference
            android:key="NESTED_KEY2"
            android:persistent="false"
            android:title="Nested screen #2" />

    </PreferenceCategory>

</PreferenceScreen> 

nested_screen1_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="Nested screen #1" >

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="nested_screen_1_1"
        android:title="Nested screen 1.1 check box" />

    <CheckBoxPreference
        android:defaultValue="true"
        android:key="nested_screen_1_2"
        android:title="Nested screen 1.2 check box" />
</PreferenceScreen>

nested_screen2_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="Nested screen #2">

    <CheckBoxPreference
        android:defaultValue="true"
        android:key="nested_screen2"
        android:title="Nested screen 2 check box" />
</PreferenceScreen>

SettingsActivity.java

public class SettingsActivity extends ActionBarActivity implements MyPreferenceFragment.Callback {

    private static final String TAG_NESTED = "TAG_NESTED";

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

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

        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.contentSettings, new MyPreferenceFragment())
                    .commit();
        }
    }

    @Override
    public void onBackPressed() {
        // this if statement is necessary to navigate through nested and main fragments
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }

    @Override
    public void onNestedPreferenceSelected(int key) {
        getFragmentManager().beginTransaction().replace(R.id.contentSettings, NestedPreferenceFragment.newInstance(key), TAG_NESTED).addToBackStack(TAG_NESTED).commit();
    }    
}

MyPreferenceFragment.java

// The main preference fragment class
public class MyPreferenceFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener {

    private Callback mCallback;

    private static final String KEY_1 = "NESTED_KEY1";
    private static final String KEY_2 = "NESTED_KEY2";

    @Override
    public void onAttach(Activity activity) {

        super.onAttach(activity);

        if (activity instanceof Callback) {
            mCallback = (Callback) activity;
        } else {
            throw new IllegalStateException("Owner must implement Callback interface");
        }
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.main_preferences);

        // add listeners for non-default actions
        Preference preference = findPreference(KEY_1);
        preference.setOnPreferenceClickListener(this);

        preference = findPreference(KEY_2);
        preference.setOnPreferenceClickListener(this);
    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        // here you should use the same keys as you used in the xml-file
        if (preference.getKey().equals(KEY_1)) {
            mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_1_KEY);
        }

        if (preference.getKey().equals(KEY_2)) {
            mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_2_KEY);
        }

        return false;
    }

    public interface Callback {
        public void onNestedPreferenceSelected(int key);
    }
}

NestedPreferencesFragment.java

public class NestedPreferenceFragment extends PreferenceFragment {

    public static final int NESTED_SCREEN_1_KEY = 1;
    public static final int NESTED_SCREEN_2_KEY = 2;

    private static final String TAG_KEY = "NESTED_KEY";

    public static NestedPreferenceFragment newInstance(int key) {
        NestedPreferenceFragment fragment = new NestedPreferenceFragment();
        // supply arguments to bundle.
        Bundle args = new Bundle();
        args.putInt(TAG_KEY, key);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        checkPreferenceResource();
    }

    private void checkPreferenceResource() {
        int key = getArguments().getInt(TAG_KEY);
        // Load the preferences from an XML resource
        switch (key) {
            case NESTED_SCREEN_1_KEY:
                addPreferencesFromResource(R.xml.nested_screen1_preferences);
                break;

            case NESTED_SCREEN_2_KEY:
                addPreferencesFromResource(R.xml.nested_screen2_preferences);
                break;

            default:
                break;
        }
    }

}
于 2015-01-14T11:21:30.683 回答
7

这是我的解决方案,它的灵感来自原始答案,但并不复杂。也许它会帮助某人......

layout/settings.xml

    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <include
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            layout="@layout/toolbar" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/content"
            android:layout_below="@+id/toolbar"/>

    </RelativeLayout>

课程:

public class SettingsActivity extends ActionBarActivity {
  @Override
  protected void onCreate( Bundle savedInstanceState ) {
    setContentView( R.layout.settings );
    super.onCreate( savedInstanceState ); 
    initializeSupportActionBar();
    getFragmentManager().beginTransaction().replace( R.id.content, new MainFragment() ).commit();
  }

  @Override
  public void onBackPressed() {
    if( !getFragmentManager().popBackStackImmediate() ) super.onBackPressed();
  }
}

public class MainFragment extends PreferenceFragment {

  public MainFragment() {}

  @Override
  public void onCreate( Bundle savedInstanceState ) {
    super.onCreate( savedInstanceState );
    addPreferencesFromResource( R.xml.pref_main );
    // "nested" is the <Preference android:key="nested" android:persistent="false"/>`
    findPreference( "nested" ).setOnPreferenceClickListener( new OnPreferenceClickListener() {
      @Override public boolean onPreferenceClick( Preference preference ) {
        getFragmentManager().beginTransaction().replace( R.id.content, new NestedFragment() ).addToBackStack( NestedFragment.class.getSimpleName() ).commit();
        return true;
      }
    } );
  }

public class NestedFragment extends PreferenceFragment {
  ...
}

我对其进行了测试,4.3并且5.0.2对嵌套级别没有限制

于 2015-08-11T14:24:46.630 回答
0

在我的解决方案中,您只需要一个AppCompatActivity和一个PreferenceFragement,但需要几个 XML 文件,每个文件只有一个级别的PreferenceScreens.

XML 文件列表

  • 顶级 PreferenceScreen
  • 第二级 PreferenceScreen 0
  • 第二级 PreferenceScreen 1
  • 第二级 PreferenceScreen 2
  • ...

此代码用于一个子级别(为了简单起见),但您可以轻松地将其扩展为具有PreferenceScreens.

SettingsFragment.java

public class SettingsFragment extends PreferenceFragment
{
    private int xmlId;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        xmlId = R.xml.preferences;
        addPreferencesFromResource(xmlId);
    }

    public void changePrefScreen(int xmlId, int titleId)
    {
        this.xmlId = xmlId;
        ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(getActivity().getResources().getString(titleId));
        getPreferenceScreen().removeAll();
        addPreferencesFromResource(xmlId);
    }

    // will be called by SettingsActivity (Host Activity)
    public void onUpButton()
    {
        if(xmlId == R.xml.preferences) // in top-level
        {
            // Switch to MainActivity
            Intent intent = new Intent(getActivity(), MainActivity.class);
            startActivity(intent);
        }
        else // in sub-level
        {
            changePrefScreen(R.xml.preferences, R.string.settings);
        }
    }

    @Override
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)
    {
        String key = preference.getKey();

        //
        // Top level PreferenceScreen
        //
        if(key.equals("top_key_0"))
        {
            changePrefScreen(R.xml.download_preference_screen, R.string.download_database); // descend into second level
        }

        // ...

        //
        // Second level PreferenceScreens
        //
        if (key.equals("second_level_key_0"))
        {
           // do something...
        }

        // ...
     }

SettingsActivity.java

public class SettingsActivity extends AppCompatActivity
{
    SettingsFragment settingsFragment;

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

        settingsFragment = new SettingsFragment();

        // Display the fragment as the main content.
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, settingsFragment)
                .commit();
    }

    //
    // Handle what happens on up button
    //
    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch (item.getItemId()) 
        {
            case android.R.id.home:
                settingsFragment.onUpButton();
                return true;
        }
        return true;
    }

    // ...
}

从技术上讲,它应该适用于所有可用的 Android 版本PreferenceFragment

于 2016-09-05T11:39:28.757 回答
0

由于问题来自您仍在同一活动/片段中的部分,并且嵌套的首选项屏幕只是一个对话框,您可以执行以下操作:

  • 您可以设置首选项点击监听器
  • 从对话框中获取根视图: (PreferenceScreen)preference).getDialog().getWindow() .getDecorView().getRootView());

  • 递归搜索直到找到一个存根视图(有一个,不幸的是我不知道android.R.id.xxxxx)并设置您需要的布局作为标题,它看起来像工具栏(您可以膨胀工具栏):

    private Toolbar toolbar;
    
        public void findViewStub(ViewGroup viewGroup) {
        int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = viewGroup.getChildAt(i);
            if( childView instanceof ViewStub){
                ((ViewStub)childView).setLayoutResource(R.layout.your_title_layout);
               toolbar =  ((ViewStub)childView).inflate();
            }
            if (childView instanceof ViewGroup) {
                findViewStub((ViewGroup) childView);
            }
        }
    
      }
    
    toolbar.setNavigationIcon();
    toolbar.setNavigationOnClickListener();
    toolbar.setTitle();
    
  • 在布局中,您只能放置一个工具栏。并设置后退图标。注册单击它并参考片段,单击时您可以关闭对话框。您已设置标题等。

于 2017-03-24T15:54:08.450 回答