2015-09-09 31 views
15

PreferenceFragmentCompat的內部PreferenceScreen未顯示,或似乎忽略輕敲事件。內部PreferenceScreen不打開PreferenceFragmentCompat

我創建MyPreferenceFragmentextends PreferenceFragmentCompat

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

然後我改變了我的主題,在styles.xml

<style name="AppTheme" parent="@style/Theme.AppCompat.Light"> 
    <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> 
</style> 

最後創建我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> 

build.gradle我有添加既:活動

public class MainActivity extends AppCompatActivity { 

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

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" /> 

測試上面的代碼,我不能開/進入偏好屏幕的

compile 'com.android.support:appcompat-v7:23.0.1' 
compile 'com.android.support:preference-v7:23.0.1' 

代碼。我錯過了什麼嗎?爲什麼這不起作用?

+0

發佈您的活動。 – Aryan

+0

添加了活動,但請注意,如果我在xml中添加活動或使用FragmentManager並進行替換,則它沒有區別。如果首選項片段是ViewPager的一部分,則會發生相同的行爲。 – madlymad

+2

如果我理解正確,你應該自己處理嵌套的PreferenceScreen。例如,如果將它添加到PreferenceFragmentCompat中,它將起作用:@Override public void onNavigateToScreen(PreferenceScreen preferenceScreen){setPreferenceScreen(preferenceScreen);}'雖然這顯然不會將新屏幕添加到後退按鈕。我假設他們希望我們使用此方法或OnPreferenceStartFragmentCallback創建Intents或交換片段。 – squirrel

回答

28

經過許多小時的嘗試,搜索並感謝支持庫的創建者的一些幫助。我設法使它工作。

第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; 
    } 
} 

提示。

  • 不要添加片段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); 
    } 

} 

提示。

  • 使用方法setPreferencesFromResource並利用每個屏幕的rootKey。這樣你的代碼將被正確地重用。請注意,如果你的代碼片段中有findPreference這樣的代碼,它應該有null檢查,因爲當你在內部屏幕時,這將不會給你任何東西。

的事情,現在缺少的是在動作條(家庭行動)的後退箭頭的執行,而且這本身不;-)

我也」創造了一個演示應用程序包所有這些代碼工作你可以在github找到它。

+0

感謝您的最小可行代碼。我通過添加後退箭頭擴展了您的工作。進入內部首選項屏幕時,我傾向於更改操作欄外觀。但是,我不知道正確的方法,當從內部首選項屏幕退出時,恢復回操作欄的外觀。我目前的方法工作,但它看起來有點hackish。 https://github.com/yccheok/PreferenceApp/commits/master請隨時提供一些輸入。謝謝:) –

+0

@CheokYanCheng我檢查了代碼。唯一認爲避免hackish(如果是的話)onBackPressed是在片段的onResume中實現標題。我不確定這是否直截了當,或者您需要將它與onUserVisible方法一起使用。 – madlymad

+0

謝謝,通過重寫onViewCreated()並將視圖的背景塗成白色幫助我擺脫黑色背景。 – AndaluZ

4

我做得稍微不同,我爲每個屏幕啓動一項新的活動。這似乎需要更少的竅門:不需要交換碎片和背景顏色。您還可以獲得活動更改動畫作爲獎勵!

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); 
     } 
    } 
} 

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> 
0

基於@squirrel意向的解決方案,我把它以這種方式工作。它需要更少的黑客攻擊。
活動:

import android.support.v7.app.AppCompatActivity; 

public class SettingsActivity extends AppCompatActivity { 

    public static final String TARGET_SETTING_PAGE = "target"; 

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

     SettingsFragment settingsFragment = new SettingsFragment(); 
     Intent intent = getIntent(); 
     if (intent != null) { 
      String rootKey = intent.getStringExtra(TARGET_SETTING_PAGE); 
      if (rootKey != null) { 
       settingsFragment.setArguments(Bundler.single(TARGET_SETTING_PAGE, rootKey)); 
      } 
     } 

     getFragmentManager().beginTransaction() 
       .replace(android.R.id.content, settingsFragment) 
       .commit(); 
    } 
} 

片段:

import android.support.v14.preference.PreferenceFragment; 

public class SettingsFragment extends PreferenceFragment { 

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

     Bundle arguments = getArguments(); 
     if (arguments != null && arguments.getString(TARGET_SETTING_PAGE) != null) { 
      setPreferencesFromResource(R.xml.preferences, arguments.getString(TARGET_SETTING_PAGE)); 
     } else { 
      addPreferencesFromResource(R.xml.preferences); 
     } 
    } 

    @Override 
    public void onNavigateToScreen(PreferenceScreen preferenceScreen) { 
     Intent intent = new Intent(getActivity(), SettingsActivity.class) 
       .putExtra(TARGET_SETTING_PAGE, preferenceScreen.getKey()); 
     startActivity(intent); 

     super.onNavigateToScreen(preferenceScreen); 
    } 
} 

可悲的是你在程序兼容性庫支持的東西,完美的作品出的現成的標準Android需要這麼多的黑客。

0

解決方法是啓動同一個類的另一個片段,但使用不同的根密鑰。不涉及活動行爲。

@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(R.id.container, applicationPreferencesFragment) 
      .addToBackStack(null) 
      .commit(); 
} 
相關問題