16

Używam PreferenceFragment w ActionBarActivity z biblioteki support-v7.
W działaniu Mam Toolbar. Wszystko idzie dobrze, dopóki nie otworzę zagnieżdżonego PreferenceScreen.
Na otwartym ekranie ukryty jest Toolbar.Pasek narzędzi jest ukryty w zagnieżdżonym PreferenceScreen

Może ktoś zna obejście tego problemu?

Preferencje xml-file:

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

układ aktywny:

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

http://stackoverflow.com/a/27455363/2247612 Ta odpowiedź ma idealne rozwiązanie do wsparcia Biblioteki – harishannam

Odpowiedz

26

znalazłem rozwiązania na własną rękę. Użyłem małego obejścia tego zagnieżdżonego PreferenceScreen's. Po prostu dokonałem separacji do różnych plików xml-preference, utworzyłem dodatkową Fragment, która rozciąga się na PreferenceFragment i tam pokazuję odpowiedni zagnieżdżony ekran preferencji.
Może ktoś uzna to za przydatne.

Github sources link.

Niektóre przykłady kodu poniżej:

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

} 
+0

I było w tej kwestii w ostatnim czasie. Twoje rozwiązanie jest dobre, ale możesz użyć tylko 1 poziomu zagnieżdżania, prawda?Jakieś pomysły rozszerzenia tego na dowolną liczbę zagnieżdżonych ekranów preferencji? Widziałem obejście tego, że Toolbar jest niestandardową preferencją, która działa dobrze, ale wydaje mi się bardzo zła. –

+0

Tak, przy obecnym rozwiązaniu możesz mieć tylko 1 poziom zagnieżdżenia. W każdym razie moje rozwiązanie opiera się na manipulacji stosem wstecznym fragmentu. Myślę, że bardzo możliwe jest dodawanie dodatkowych fragmentów do bieżącego back-stacka i operowanie logiką, aby utworzyć tyle zagnieżdżonych prefów, ile chcesz. – yurezcv

+0

Dzięki bracie! Doskonała odpowiedź. –

6

Nadchodzi mój roztwór, który jest inspirowany oryginalnym odpowiedź, ale nie tak skomplikowany. Może to pomoże komuś ...

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> 

Ćwiczenia:

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 { 
    ... 
} 

Testowałem go na 4.3 i 5.0.2 a nie ograniczenie poziomu zagnieżdżenia dotyczy

0

W moim rozwiązanie trzeba tylko jedną AppCompatActivity i jeden PreferenceFragement, ale kilka plików XML, z których każdy ma tylko jeden poziom PreferenceScreens.

lista plików XML

  • najwyższym poziomie PreferenceScreen
  • drugi poziom PreferenceScreen 0
  • drugi poziom PreferenceScreen 1
  • drugi poziom PreferenceScreen 2
  • ...

Ten kod jest dla jednego poziomu podrzędnego (dla uproszczenia i uzyskania idei), ale można go łatwo rozszerzyć, aby uzyskać dowolne podpoziomy: 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; 
    } 

    // ... 
} 

Technicznie to powinno działać dla wszystkich wersji Androida dla których PreferenceFragment są dostępne.

0

Ponieważ emisja pochodzi z części, które są nadal w tym samym działaniu/fragmentu i zagnieżdżonego pref ekranie jest tylko dialogowe można wykonać następujące czynności:

  • Można ustawić preferencje kliknij słuchacza
  • Get widok z okna głównego: (PreferenceScreen)preference).getDialog().getWindow() .getDecorView().getRootView());

  • Rekursywnie szukać aż do znalezienia widoku skrótową (jest tylko jedna, niestety nie znam android.R.id.xxxxx) i ustawić co trzeba jak layout tytuł, który będzie wyglądał na pasku narzędzi (pasek narzędzi można nadmuchać):

    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(); 
    
  • W układzie można umieścić tylko pasek. I ustaw tylną ikonę. Zarejestruj się, aby go kliknąć i odwołać się do fragmentu, po kliknięciu możesz zamknąć okno dialogowe. Ustawiono tytuł itp

Powiązane problemy