2

我通過PreferenceFragment這是一個DialogFragment顯示我的應用程序的首選項。工作非常好99%。Preferencefragment作爲DialogFragment需要一個工具欄(符合設計庫)

如何添加一個工具欄到該特定的DialogFragment?

佈局經由addPreferencesFromResource(R.xml.preferences)加載。

所以,我沒有可以添加工具欄的佈局。

編輯:下面我找到了一個很好的解決方案!

+0

爲什麼這不是一個好問題?你能詳細說明嗎? – tjm1706

+0

你問關於添加對話框到對話框片段? –

+0

感謝您的回覆。 DialogFragment包含PreferenceFragment。 我想添加工具欄...有兩個原因:(1)符合具有工具欄的其他屏幕,特別是(2)空的工具欄將顯示「後退」箭頭。 – tjm1706

回答

0

有一個更好的解決方案。

首先我使用適合支持庫的PreferenceFragment。作者Christophe Beyls(謝謝!)。

步驟1:基本類:PreferenceFragment的支持庫

import android.annotation.SuppressLint; 
import android.app.Activity; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.preference.Preference; 
import android.preference.PreferenceManager; 
import android.preference.PreferenceScreen; 
import android.support.v4.app.DialogFragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ListView; 

import java.lang.reflect.Constructor; 
import java.lang.reflect.Method; 

/* A PreferenceFragment f/t support library. @author Christophe Beyls */ 
public abstract class PreferenceFragment2 extends DialogFragment { 

    private static final int FIRST_REQUEST_CODE = 100; 
    private static final int MSG_BIND_PREFERENCES = 1; 
    private static final int MSG_REQUEST_FOCUS = 2; 
    private static final String PREFERENCES_TAG = "android:preferences"; 
    private static final float HC_HORIZONTAL_PADDING = 16; 

    @SuppressLint("HandlerLeak") 
    private final Handler mHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      switch (msg.what) { 
      case MSG_BIND_PREFERENCES: 
       bindPreferences(); 
       break; 
      case MSG_REQUEST_FOCUS: 
       mList.focusableViewAvailable(mList); 
       break; 
      } 
     } 
    }; 

    private boolean mHavePrefs; 
    private boolean mInitDone; 
    private ListView mList; 
    private PreferenceManager mPreferenceManager; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setStyle(android.support.v4.app.DialogFragment.STYLE_NORMAL, R.style.FullScreenDialogTheme); 
     try { 
      Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class); 
      c.setAccessible(true); 
      mPreferenceManager = c.newInstance(this.getActivity(), FIRST_REQUEST_CODE); 
     } catch (Exception e) { 
     } 
    } 

    @Override 
    public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstanceState) { 
     ListView listView = new ListView(getActivity()); 
     listView.setId(android.R.id.list); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      final int horizontalPadding = (int) (HC_HORIZONTAL_PADDING * getResources().getDisplayMetrics().density); 
      listView.setPadding(horizontalPadding, 0, horizontalPadding, 0); 
     } 
     return listView; 
    } 

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

     if (mHavePrefs) { 
      bindPreferences(); 
     } 

     mInitDone = true; 

     if (savedInstanceState != null) { 
      Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG); 
      if (container != null) { 
       final PreferenceScreen preferenceScreen = getPreferenceScreen(); 
       if (preferenceScreen != null) { 
        preferenceScreen.restoreHierarchyState(container); 
       } 
      } 
     } 
    } 

    public void onStop() { 
     super.onStop(); 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop"); 
      m.setAccessible(true); 
      m.invoke(mPreferenceManager); 
     } catch (Exception e) { 
     } 
    } 

    public void onDestroyView() { 
     mList = null; 
     mHandler.removeCallbacksAndMessages(null); 
     super.onDestroyView(); 
    } 

    public void onDestroy() { 
     super.onDestroy(); 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy"); 
      m.setAccessible(true); 
      m.invoke(mPreferenceManager); 
     } catch (Exception e) { 
     } 
    } 

    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     PreferenceScreen preferenceScreen = getPreferenceScreen(); 
     if (preferenceScreen != null) { 
      Bundle container = new Bundle(); 
      preferenceScreen.saveHierarchyState(container); 
      outState.putBundle(PREFERENCES_TAG, container); 
     } 
    } 

    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class); 
      m.setAccessible(true); 
      m.invoke(mPreferenceManager, requestCode, resultCode, data); 
     } catch (Exception e) { 
     } 
    } 

    public PreferenceManager getPreferenceManager() { 
     return mPreferenceManager; 
    } 

    public void setPreferenceScreen(PreferenceScreen screen) { 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class); 
      m.setAccessible(true); 
      boolean result = (Boolean) m.invoke(mPreferenceManager, screen); 
      if (result && (screen != null)) { 
       mHavePrefs = true; 
       if (mInitDone) { 
        postBindPreferences(); 
       } 
      } 
     } catch (Exception e) { 
     } 
    } 

    public PreferenceScreen getPreferenceScreen() { 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen"); 
      m.setAccessible(true); 
      return (PreferenceScreen) m.invoke(mPreferenceManager); 
     } catch (Exception e) { 
      return null; 
     } 
    } 

    public void addPreferencesFromIntent(Intent intent) { 
     requirePreferenceManager(); 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class); 
      m.setAccessible(true); 
      PreferenceScreen screen = (PreferenceScreen) m.invoke(mPreferenceManager, intent, getPreferenceScreen()); 
      setPreferenceScreen(screen); 
     } catch (Exception e) { 
     } 
    } 

    public void addPreferencesFromResource(int resId) { 
     requirePreferenceManager(); 
     try { 
      Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class); 
      m.setAccessible(true); 
      PreferenceScreen screen = (PreferenceScreen) m.invoke(mPreferenceManager, getActivity(), resId, getPreferenceScreen()); 
      setPreferenceScreen(screen); 
     } catch (Exception e) { 
     } 
    } 

    public Preference findPreference(CharSequence key) { 
     if (mPreferenceManager == null) { 
      return null; 
     } 
     return mPreferenceManager.findPreference(key); 
    } 

    private void requirePreferenceManager() { 
     if (this.mPreferenceManager == null) { 
      throw new RuntimeException("This should be called after super.onCreate."); 
     } 
    } 

    private void postBindPreferences() { 
     if (!mHandler.hasMessages(MSG_BIND_PREFERENCES)) { 
      mHandler.sendEmptyMessage(MSG_BIND_PREFERENCES); 
     } 
    } 

    private void bindPreferences() { 
     final PreferenceScreen preferenceScreen = getPreferenceScreen(); 
     if (preferenceScreen != null) { 
      preferenceScreen.bind(getListView()); 
     } 
    } 

    public ListView getListView() { 
     ensureList(); 
     return mList; 
    } 

    private void ensureList() { 
     if (mList != null) { 
      return; 
     } 
     View root = getView(); 
     if (root == null) { 
      throw new IllegalStateException("Content view not yet created"); 
     } 
     View rawListView = root.findViewById(android.R.id.list); 
     if (!(rawListView instanceof ListView)) { 
      throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class"); 
     } 
     mList = (ListView) rawListView; 
     if (mList == null) { 
      throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'"); 
     } 
     mHandler.sendEmptyMessage(MSG_REQUEST_FOCUS); 
    } 
} 

步驟2:創建自己的基於上述文件FragmentPreferences:

步驟2.1 - 創建佈局文件:res/layout/preferences_with_toolbar.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    android:id="@+id/preferences_dialog" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:background="@color/white" 
    android:orientation="vertical"> 

    <android.support.v7.widget.Toolbar 
     android:id="@+id/preferences_toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="?attr/actionBarSize" 
     android:background="?attr/colorPrimary" 
     app:itemTextColor="#333" 
     app:itemIconTint="#333" 
     app:layout_scrollFlags="scroll|enterAlways" 
     app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
     app:popupTheme="@style/ThemeOverlay.AppCompat.Light"> 
    </android.support.v7.widget.Toolbar> 
</LinearLayout> 

步驟2.2 - 在工具欄中創建菜單選項。沒有在我的情況。

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto"> 
</menu> 

步驟2.3 - 創建FragmentPreferences

public class FragmentUserPreferences extends PreferenceFragment2 implements SharedPreferences.OnSharedPreferenceChangeListener { 
    View rootView = null; 
    Preference letterSizePref; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // Access the main layout file 
    rootView = inflater.inflate(R.layout.preferences_with_toolbar, container, false); 
    Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.preferences_toolbar); 
    toolbar.setNavigationIcon(R.drawable.ic_action_back); 
    toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      dismiss(); 
     } 
    }); 
    toolbar.inflateMenu(R.menu.dialog_toolbar_empty); 
    toolbar.setTitle("Preferences"); 
    View view = super.onCreateView(inflater, container, savedInstanceState); 
    view.setBackgroundColor(Color.WHITE); 
    PreferenceManager.getDefaultSharedPreferences(getActivity()).registerOnSharedPreferenceChangeListener(this); 
    LinearLayout prefLayout = (LinearLayout) rootView.findViewById(R.id.preferences_dialog); 
    prefLayout.addView(view); 

    // Load the preferences from an XML resource 
    addPreferencesFromResource(R.xml.preferences); 

    letterSizePref= (Preference) findPreference("letterSize"); 

    // From here this is your default user settings stuff 
    // ... 
    return rootView; 
} 
// etc. 
0
  1. 首先,你需要像下面的對話片段創建自定義佈局。

<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    card_view:cardBackgroundColor="@color/orange" 
    android:orientation="horizontal"> 

    <ImageView 
     android:id="@+id/back_button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:padding="10dp" 
     android:src="@drawable/ic_arrow_back_black_36dp" /> 

</android.support.v7.widget.CardView> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <android.support.design.widget.TextInputLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:padding="20dp"> 

     <EditText 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:singleLine="true" 
      android:hint="@string/first_name"/> 

    </android.support.design.widget.TextInputLayout> 
</LinearLayout> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal"> 

    <Button 
     android:id="@+id/ok" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:text="OK" 
     android:padding="10dp" 
     android:gravity="center" 
     android:background="@color/holo_green_light" 
     android:textColor="@android:color/white" 
     android:layout_weight="1"/> 

    <Button 
     android:id="@+id/cancel" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:text="CANCEL" 
     android:padding="10dp" 
     android:gravity="center" 
     android:background="@color/holo_red_light" 
     android:textColor="@android:color/white" 
     android:layout_weight="1"/> 
</LinearLayout> 

要使用cardview,這將給你一個影子功能看起來像一個工具欄使用在你的應用程序中的build.gradle以下依賴。

編譯 'com.android.support:cardview-v7:23.0.+'

  • 創建一個使用上述佈局象下面自定義對話框片段。
  •  
    public class CustomDialogFragment extends DialogFragment { 
        public CustomDialogFragment(){ 
    
        } 
    
        @Override 
        public Dialog onCreateDialog(Bundle onSavedInstanceState){ 
         Dialog dialog = super.onCreateDialog(onSavedInstanceState); 
    
         // Hide default title. 
         dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); 
    
         return dialog; 
        } 
    
        @Override 
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle onSavedInstanceState){ 
         View v = inflater.inflate(R.layout.custom_dialog_layout, container, false); 
    
         ImageView backButton = (ImageView) v.findViewById(R.id.back_button); 
    
         backButton.setOnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View v) { 
           /** TODO handle the Back button (OR) 
            Communicate to the MainActivity to dismiss the dialog 
            To know more about communicating from fragment to main activity check this thread 
            http://stackoverflow.com/a/34498055/3049065 
           **/ 
          } 
         }); 
    
         Button okButton = (Button) v.findViewById(R.id.ok); 
    
         okButton.setOnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View v) { 
           // TODO handle the ok Button 
          } 
         }); 
    
         Button cancelButton = (Button) v.findViewById(R.id.cancel); 
    
         cancelButton.setOnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View v) { 
           // TODO handle the cancel Button 
          } 
         }); 
    
         return v; 
        } 
    } 
    

    檢查這個我下面的資料庫分支的示範項目。

    https://github.com/Mahendran-Sakkarai/Testing-Android-Applications/tree/CustomDialogFragment

    的輸出將是象下面這樣。 Custom Fragment with backbutton

    +0

    非常感謝,我會研究這個! – tjm1706