การสร้างหน้าจอการตั้งค่าด้วยการสนับสนุนแถบเครื่องมือ (v21)


116

ฉันประสบปัญหาในการใช้แถบเครื่องมือดีไซน์ Material ใหม่ในไลบรารีการสนับสนุนบนหน้าจอการตั้งค่า

ฉันมีไฟล์ settings.xml ดังต่อไปนี้:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="@string/AddingItems"
        android:key="pref_key_storage_settings">

        <ListPreference
            android:key="pref_key_new_items"
            android:title="@string/LocationOfNewItems"
            android:summary="@string/LocationOfNewItemsSummary"
            android:entries="@array/new_items_entry"
            android:entryValues="@array/new_item_entry_value"
            android:defaultValue="1"/>

    </PreferenceCategory>
</PreferenceScreen>

สตริงถูกกำหนดไว้ที่อื่น


stackoverflow.com/a/27455363/2247612คำตอบนี้เป็นโซลูชันที่สมบูรณ์แบบสำหรับ Support Library
harishannam

คำตอบ:


110

โปรดค้นหา GitHub Repo: ที่นี่


ไปงานปาร์ตี้ช้าไปหน่อย แต่นี่เป็นวิธีแก้ปัญหาของฉันที่ฉันใช้เป็นวิธีแก้ปัญหาในการใช้งานต่อไปPreferenceActivity:

settings_toolbar.xml :

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    app:navigationContentDescription="@string/abc_action_bar_up_description"
    android:background="?attr/colorPrimary"
    app:navigationIcon="?attr/homeAsUpIndicator"
    app:title="@string/action_settings"
    />

SettingsActivity.java :

public class SettingsActivity extends PreferenceActivity {

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

        LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
        Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
        root.addView(bar, 0); // insert at top
        bar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }

}

Result :

ตัวอย่าง


UPDATE (ความเข้ากันได้ของ Gingerbread):

ตามความคิดเห็น Gingerbread Devices จะส่งคืน NullPointerException ในบรรทัดนี้:

LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();

การแก้ไข:

SettingsActivity.java :

public class SettingsActivity extends PreferenceActivity {

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        Toolbar bar;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent();
            bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
            root.addView(bar, 0); // insert at top
        } else {
            ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
            ListView content = (ListView) root.getChildAt(0);

            root.removeAllViews();

            bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
            

            int height;
            TypedValue tv = new TypedValue();
            if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
                height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
            }else{
                height = bar.getHeight();
            }

            content.setPadding(0, height, 0, 0);

            root.addView(content);
            root.addView(bar);
        }

        bar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
}

ปัญหาใด ๆ ข้างต้นแจ้งให้เราทราบ!


อัปเดต 2: การแก้ไขปัญหาการย้อมสี

ตามที่ระบุไว้ในบันทึกย่อของนักพัฒนาจำนวนมากPreferenceActivityไม่สนับสนุนการย้อมสีขององค์ประกอบอย่างไรก็ตามการใช้คลาสภายในสองสามอย่างคุณสามารถบรรลุสิ่งนี้ได้ นั่นคือจนกว่าคลาสเหล่านี้จะถูกลบออก (ทำงานโดยใช้ appCompat support-v7 v21.0.3)

เพิ่มการนำเข้าต่อไปนี้:

import android.support.v7.internal.widget.TintCheckBox;
import android.support.v7.internal.widget.TintCheckedTextView;
import android.support.v7.internal.widget.TintEditText;
import android.support.v7.internal.widget.TintRadioButton;
import android.support.v7.internal.widget.TintSpinner;

จากนั้นแทนที่onCreateViewวิธีการ:

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    // Allow super to try and create a view first
    final View result = super.onCreateView(name, context, attrs);
    if (result != null) {
        return result;
    }

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        // If we're running pre-L, we need to 'inject' our tint aware Views in place of the
        // standard framework versions
        switch (name) {
            case "EditText":
                return new TintEditText(this, attrs);
            case "Spinner":
                return new TintSpinner(this, attrs);
            case "CheckBox":
                return new TintCheckBox(this, attrs);
            case "RadioButton":
                return new TintRadioButton(this, attrs);
            case "CheckedTextView":
                return new TintCheckedTextView(this, attrs);
        }
    }

    return null;
}

Result:

ตัวอย่างที่ 2


AppCompat 22.1

AppCompat 22.1 นำเสนอองค์ประกอบสีใหม่ซึ่งหมายความว่าไม่จำเป็นต้องใช้คลาสภายในอีกต่อไปเพื่อให้ได้ผลเช่นเดียวกับการอัปเดตล่าสุด ทำตามสิ่งนี้แทน (ยังคงลบล้างonCreateView):

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    // Allow super to try and create a view first
    final View result = super.onCreateView(name, context, attrs);
    if (result != null) {
        return result;
    }

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        // If we're running pre-L, we need to 'inject' our tint aware Views in place of the
        // standard framework versions
        switch (name) {
            case "EditText":
                return new AppCompatEditText(this, attrs);
            case "Spinner":
                return new AppCompatSpinner(this, attrs);
            case "CheckBox":
                return new AppCompatCheckBox(this, attrs);
            case "RadioButton":
                return new AppCompatRadioButton(this, attrs);
            case "CheckedTextView":
                return new AppCompatCheckedTextView(this, attrs);
        }
    }

    return null;
}

หน้าจอที่กำหนดไว้ล่วงหน้า

หลายคนกำลังประสบปัญหาเกี่ยวกับการรวม Toolbar ไว้ในที่ซ้อนกัน<PreferenceScreen />อย่างไรก็ตามฉันได้พบวิธีแก้ไขแล้ว !! - หลังจากลองผิดลองถูกมาหลายครั้ง!

เพิ่มสิ่งต่อไปนี้ในของคุณSettingsActivity:

@SuppressWarnings("deprecation")
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
    super.onPreferenceTreeClick(preferenceScreen, preference);

    // If the user has clicked on a preference screen, set up the screen
    if (preference instanceof PreferenceScreen) {
        setUpNestedScreen((PreferenceScreen) preference);
    }

    return false;
}

public void setUpNestedScreen(PreferenceScreen preferenceScreen) {
    final Dialog dialog = preferenceScreen.getDialog();

    Toolbar bar;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        LinearLayout root = (LinearLayout) dialog.findViewById(android.R.id.list).getParent();
        bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
        root.addView(bar, 0); // insert at top
    } else {
        ViewGroup root = (ViewGroup) dialog.findViewById(android.R.id.content);
        ListView content = (ListView) root.getChildAt(0);

        root.removeAllViews();

        bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);

        int height;
        TypedValue tv = new TypedValue();
        if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
            height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
        }else{
            height = bar.getHeight();
        }

        content.setPadding(0, height, 0, 0);

        root.addView(content);
        root.addView(bar);
    }

    bar.setTitle(preferenceScreen.getTitle());

    bar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dialog.dismiss();
        }
    });
}

สาเหตุที่ทำให้PreferenceScreenเจ็บปวดนั้นเป็นเพราะมันมีพื้นฐานมาจากไดอะล็อกของ Wrapper ดังนั้นเราจึงต้องจับเค้าโครงไดอะล็อกเพื่อเพิ่มแถบเครื่องมือเข้าไป


แถบเครื่องมือเงา

โดยการออกแบบการนำเข้าToolbarไม่อนุญาตให้มีการยกระดับและเงาในอุปกรณ์รุ่นก่อน v21 ดังนั้นหากคุณต้องการมีระดับความสูงToolbarคุณจำเป็นต้องห่อด้วยAppBarLayout:

settings_toolbar.xml :

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

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

</android.support.design.widget.AppBarLayout>

ไม่ลืมที่จะเพิ่มไลบรารี Design Support ที่เป็นตัวอ้างอิงในbuild.gradleไฟล์:

compile 'com.android.support:support-v4:22.2.0'
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:design:22.2.0'

Android 6.0

ฉันได้ตรวจสอบปัญหาทับซ้อนที่รายงานแล้วและฉันไม่สามารถสร้างปัญหาซ้ำได้

รหัสเต็มที่ใช้งานด้านบนสร้างสิ่งต่อไปนี้:

ใส่คำอธิบายภาพที่นี่

หากฉันขาดอะไรไปโปรดแจ้งให้เราทราบผ่านrepo นี้และฉันจะตรวจสอบ


มันให้ข้อยกเว้น nullpointer ใน gingebread รูทเป็น null .. วิธีแก้ปัญหาใด
andQlimax

โซลูชันของคุณใช้งานได้ดี แต่มีปัญหากับแนวทางนี้ infact โดยไม่ต้องขยาย ActionBarActivity ซึ่งเป็นข้อบังคับ (จากเอกสารประกอบ) เพื่อให้ได้ธีมวัสดุบน <5.0, colorAccent (เพื่อสร้างตัวอย่าง) จะไม่ถูกนำไปใช้กับช่องทำเครื่องหมายในอุปกรณ์ <5.0 นี่ดูเหมือนจะเป็นความเจ็บปวดจริงๆ .. บางทีฉันอาจต้องลบกิจกรรมการตั้งค่าและใช้เลย์เอาต์เชิงเส้นเพื่อจำลองหน้าจอความชอบมิฉะนั้นฉันจะไม่เห็นวิธีใดในการใช้ธีมวัสดุในอุปกรณ์ตั้งแต่ระดับ API 8 ถึง 21 ส่วนการตั้งค่าคือ "only"> 11 :(
andQlimax

1
@andQlimax ฉันได้อัปเดตคำตอบพร้อมวิธีแก้ปัญหาการย้อมสีแล้ว
David Passmore

3
@DavidPassmore สำหรับฉันรายการความชอบซ้อนทับบนแถบเครื่องมือ
Shashank Srivastava

1
@ShashankSrivastava สิ่งนี้สะท้อนให้เห็นหากคุณใช้ Android 6 ฉันกำลังหาวิธีแก้ปัญหานี้ ขอบคุณสำหรับการอัพเดท.
David Passmore

107

คุณสามารถใช้ a PreferenceFragmentเพื่อเป็นทางเลือกในการPreferenceActivity. ดังนั้นนี่คือActivityตัวอย่างการห่อ:

public class MyPreferenceActivity extends ActionBarActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pref_with_actionbar);

        android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(uk.japplications.jcommon.R.id.toolbar);
        setSupportActionBar(toolbar);

        getFragmentManager().beginTransaction().replace(R.id.content_frame, new MyPreferenceFragment()).commit();
    }
}

และนี่คือไฟล์เลย์เอาต์ (pref_with_actionbar):

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_height="@dimen/action_bar_height"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:theme="@style/ToolbarTheme.Base"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_below="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

และสุดท้ายPreferenceFragment:

public static class MyPreferenceFragment extends PreferenceFragment{
    @Override
    public void onCreate(final Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
    }
}

ฉันหวังว่านี่จะช่วยใครบางคนได้


39
ฉันได้ลองใช้แนวทางนี้แล้ว ปัญหาคือมันไม่แสดงแถบเครื่องมือในหน้าจอการตั้งค่าลูก
Madhur Ahuja

2
ฉันคิดว่าเขากำลังพูดถึง PreferenceScreen ที่ฝังอยู่ใน XML ค่ากำหนดของรูท
Lucas S.

5
ฉันชอบวิธีการนี้ แต่น่าเสียดายที่จะใช้ไม่ได้หาก API เป้าหมายน้อยกว่า API 11
midhunhk

12
มันจะไม่ทำงานด้วย ในทางปฏิบัติดูเหมือนจะไม่มีวิธีใดในการสร้างหน้าจอการตั้งค่าตามความชอบแบบซ้อนกันที่ออกแบบอย่างเป็นรูปธรรม หากคุณใช้ActionBarActivityเพื่อรับแถบเครื่องมือและฟังก์ชันที่เกี่ยวข้องจะไม่มีonBuildHeaders()การลบล้างและไม่มีการสนับสนุนค่ากำหนดที่แท้จริงในกิจกรรม หากคุณใช้แบบเก่าPreferenceActivityคุณจะไม่มีแถบเครื่องมือและฟังก์ชันที่เกี่ยวข้อง (ใช่คุณสามารถมีToolbarเค้าโครงและ แต่คุณไม่สามารถเรียกsetSupportActionBar()ได้ดังนั้นไม่ว่าจะด้วยส่วนหัวค่ากำหนดหรือหน้าจอค่ากำหนดที่ซ้อนกันเราจึงดูเหมือนติดขัด
Gábor

1
ฉันเห็นด้วยกับความคิดเห็นของ Gabor โซลูชันนี้ใช้ไม่ได้โดยทั่วไป มีการร้องที่ดีกว่าด้วยการเลียนแบบ Toolbar (ไม่มี ActionBar แต่ใครจะสนใจ) และยังมีการสนับสนุน lib ใหม่ที่เปิดตัวพร้อม AppCompatDelegate บนบอร์ด
Eugene Wechsler

48

อัปเดตใหม่ทั้งหมด

จากการทดลองบางอย่างดูเหมือนว่าฉันจะพบโซลูชัน AppCompat 22.1+ ที่ใช้งานได้สำหรับหน้าจอค่ากำหนดที่ซ้อนกัน

ครั้งแรกที่มีการกล่าวถึงในคำตอบที่หลายคน (รวมทั้งคนหนึ่งที่นี่) AppCompatDelegateคุณจะต้องใช้ใหม่ ใช้AppCompatPreferenceActivity.javaไฟล์จากการสาธิตการสนับสนุน ( https://android.googlesource.com/platform/development/+/58bf5b99e6132332afb8b44b4c8cedf5756ad464/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreference ) PreferenceActivityจากมันหรือคัดลอกฟังก์ชั่นที่เกี่ยวข้องเข้าไปในของคุณเอง ฉันจะแสดงแนวทางแรกที่นี่:

public class SettingsActivity extends AppCompatPreferenceActivity {

  @Override
  public void onBuildHeaders(List<Header> target) {
    loadHeadersFromResource(R.xml.settings, target);

    setContentView(R.layout.settings_page);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    ActionBar bar = getSupportActionBar();
    bar.setHomeButtonEnabled(true);
    bar.setDisplayHomeAsUpEnabled(true);
    bar.setDisplayShowTitleEnabled(true);
    bar.setHomeAsUpIndicator(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
    bar.setTitle(...);
  }

  @Override
  protected boolean isValidFragment(String fragmentName) {
    return SettingsFragment.class.getName().equals(fragmentName);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case android.R.id.home:
        onBackPressed();
        break;
    }
    return super.onOptionsItemSelected(item);
  }
}

เค้าโครงประกอบค่อนข้างเรียบง่ายและปกติ ( layout/settings_page.xml):

<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.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:background="?attr/colorPrimary"
      android:elevation="4dp"
      android:theme="@style/..."/>
  <ListView
      android:id="@id/android:list"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>
</LinearLayout>

ค่ากำหนดเองถูกกำหนดตามปกติ ( xml/settings.xml):

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
  <header
      android:fragment="com.example.SettingsFragment"
      android:summary="@string/..."
      android:title="@string/...">
    <extra
        android:name="page"
        android:value="page1"/>
  </header>
  <header
      android:fragment="com.example.SettingsFragment"
      android:summary="@string/..."
      android:title="@string/...">
    <extra
        android:name="page"
        android:value="page2"/>
  </header>
  ...
</preference-headers>

ไม่มีความแตกต่างอย่างแท้จริงกับการแก้ปัญหาบนเน็ตจนถึงจุดนี้ จริงๆแล้วคุณสามารถใช้สิ่งนี้ได้แม้ว่าคุณจะไม่มีหน้าจอซ้อนกันไม่มีส่วนหัวเพียงแค่หน้าจอเดียวก็ตาม

เราใช้ทั่วไปPreferenceFragmentสำหรับเพจที่ลึกขึ้นทั้งหมดโดยแยกตามextraพารามิเตอร์ในส่วนหัว แต่ละหน้าจะมี XML แยกกันโดยมีPreferenceScreenอยู่ภายใน ( xml/settings_page1.xmlet al.) แฟรกเมนต์ใช้เค้าโครงเดียวกันกับกิจกรรมรวมถึงแถบเครื่องมือ

public class SettingsFragment extends PreferenceFragment {

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActivity().setTheme(R.style...);

    if (getArguments() != null) {
      String page = getArguments().getString("page");
      if (page != null)
        switch (page) {
          case "page1":
            addPreferencesFromResource(R.xml.settings_page1);
            break;
          case "page2":
            addPreferencesFromResource(R.xml.settings_page2);
            break;
          ...
        }
    }
  }

  @Override
  public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View layout = inflater.inflate(R.layout.settings_page, container, false);
    if (layout != null) {
      AppCompatPreferenceActivity activity = (AppCompatPreferenceActivity) getActivity();
      Toolbar toolbar = (Toolbar) layout.findViewById(R.id.toolbar);
      activity.setSupportActionBar(toolbar);

      ActionBar bar = activity.getSupportActionBar();
      bar.setHomeButtonEnabled(true);
      bar.setDisplayHomeAsUpEnabled(true);
      bar.setDisplayShowTitleEnabled(true);
      bar.setHomeAsUpIndicator(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
      bar.setTitle(getPreferenceScreen().getTitle());
    }
    return layout;
  }

  @Override
  public void onResume() {
    super.onResume();

    if (getView() != null) {
      View frame = (View) getView().getParent();
      if (frame != null)
        frame.setPadding(0, 0, 0, 0);
    }
  }
}

ในที่สุดสรุปสั้น ๆ ว่าสิ่งนี้ใช้งานได้จริงอย่างไร สิ่งใหม่นี้AppCompatDelegateช่วยให้เราสามารถใช้กิจกรรมใด ๆ กับคุณสมบัติของ AppCompat ไม่เพียง แต่สิ่งที่ขยายออกไปจากกิจกรรมจริงใน AppCompat ซึ่งหมายความว่าเราสามารถเปลี่ยนของดีPreferenceActivityให้กลายเป็นของใหม่และเพิ่มแถบเครื่องมือได้ตามปกติ จากจุดนั้นเราสามารถยึดติดกับโซลูชันเก่า ๆ เกี่ยวกับหน้าจอการตั้งค่าและส่วนหัวโดยไม่มีการเบี่ยงเบนจากเอกสารที่มีอยู่ มีจุดสำคัญเพียงอย่างเดียวคืออย่าใช้onCreate()ในกิจกรรมเพราะจะนำไปสู่ข้อผิดพลาด ใช้onBuildHeaders()สำหรับการดำเนินการทั้งหมดเช่นการเพิ่มแถบเครื่องมือ

ข้อแตกต่างที่แท้จริงเพียงอย่างเดียวคือและนั่นคือสิ่งที่ทำให้มันทำงานกับหน้าจอที่ซ้อนกันคือคุณสามารถใช้วิธีการเดียวกันกับส่วนย่อย คุณสามารถใช้onCreateView()วิธีเดียวกันนี้คือขยายเค้าโครงของคุณเองแทนที่จะเป็นระบบเพิ่มแถบเครื่องมือแบบเดียวกับในกิจกรรม


2
ช่างเป็นวิธีแก้ปัญหาเล็กน้อยที่ยอดเยี่ยม! นี่เป็นทางออกเดียวที่ฉันพบซึ่งจะแสดงแถบเครื่องมือวัสดุใน PreferenceScreen ที่สืบทอดมา ทำได้ดีครับ
สตริง

ฉันใช้ทรัพยากรจากไลบรารี appcompat สำหรับไอคอนขึ้น:R.drawable.abc_ic_ab_back_mtrl_am_alpha
Ridcully

ด้วยวิธีนี้ฉันคิดว่า Toolbar จะเลื่อนไปพร้อมกับเนื้อหาใช่ไหม เนื่องจากเป็นเพียงรายการใน ListView ภายในเท่านั้น
tasomaniac

ไม่ใช่กับโซลูชันใหม่ที่อัปเดตนี้ ได้ผลตามที่คาดไว้
Gábor

น่าแปลกที่การแก้ปัญหานี้ดูเหมือนจะไม่รู้จักแทนPreferenceFragmentCompat PreferenceFragmentการตั้งค่าpreference-headerด้วยxmlns:app="http://schemas.android.com/apk/res-auto" แล้วapp:fragmentแทนที่จะandroid:fragmentไม่โหลดหน้าจอคำนำหน้าใหม่ ดังนั้นมีปัญหาเกี่ยวกับความเข้ากันได้ย้อนหลัง ... คำแนะนำ?
fattire

18

หากคุณต้องการใช้ PreferenceHeaders คุณสามารถใช้แนวทางต่อไปนี้:

import android.support.v7.widget.Toolbar;

public class MyPreferenceActivity extends PreferenceActivity

   Toolbar mToolbar;

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

        ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
        LinearLayout content = (LinearLayout) root.getChildAt(0);
        LinearLayout toolbarContainer = (LinearLayout) View.inflate(this, R.layout.activity_settings, null);

        root.removeAllViews();
        toolbarContainer.addView(content);
        root.addView(toolbarContainer);

        mToolbar = (Toolbar) toolbarContainer.findViewById(R.id.toolbar);
    }

    @Override
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.pref_headers, target);
    }

    // Other methods

}

รูปแบบ / activity_settings.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_height="?attr/actionBarSize"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:theme="@style/AppTheme"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

</LinearLayout>

คุณสามารถใช้เลย์เอาต์ที่คุณต้องการได้ที่นี่เพียงตรวจสอบให้แน่ใจว่าคุณได้ปรับแต่งในโค้ด Java ด้วย

และสุดท้ายไฟล์ของคุณที่มีส่วนหัว (xml / pref_headers.xml)

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">

    <header
        android:fragment="com.example.FirstFragment"
        android:title="@string/pref_header_first" />
    <header
        android:fragment="com.example.SecondFragment"
        android:title="@string/pref_header_second" />

</preference-headers>

root.addView (แถบเครื่องมือ); ทำไม? root.addView (toolbarContainer);
Crossle Song

อ๊ะพลาดตัวแปรขณะเปลี่ยนชื่อแก้ไขแล้ว
Sven Dubbeld

1
คำตอบที่ยอดเยี่ยม กุญแจสำคัญในที่นี้คือandroid.R.id.contentเมื่อพิจารณาว่าเราเคยส่งผ่านListViewด้วยandroid.R.id.listสำหรับรายการการตั้งค่าเอง (และยังคงทำหากใช้วิธีที่ไม่เป็นส่วนน้อยไม่มีส่วนหัว) แทน
davidcsb

2
ฉันคิดว่าควรตรวจสอบโค้ดของ Android เพื่อดูสิ่งที่ต้องการแทนที่จะไปยุ่งกับมุมมองที่มีให้เช่า (ลบ / เพิ่มมุมมองที่มี) ฉันคิดว่ามันปลอดภัยกว่าด้วยวิธีนี้ ฉันขอแนะนำให้ตรวจสอบไฟล์ "likest_list_content"
นักพัฒนา Android

2
นี่คือคำตอบที่ดีที่สุดในกระทู้นี้ ผู้เขียนบทความนี้ขยายไปสู่การใช้งานอ้างอิงแบบเต็มซึ่งฉันใช้ อันที่จริงนี่เป็นโซลูชันเดียวที่ใช้งานได้สำหรับรองรับการตั้งค่าที่ซับซ้อนในแอปของคุณ
Eugene Wechsler

17

ด้วยการเปิดตัว Android Support Library 22.1.0 และ AppCompatDelegate ใหม่ที่นี่คุณจะพบตัวอย่างที่ดีของการใช้งาน PreferenceActivity พร้อมการสนับสนุนวัสดุที่เข้ากันได้แบบย้อนหลัง

อัปเดต มันทำงานบนหน้าจอที่ซ้อนกันด้วย

https://android.googlesource.com/platform/development/+/marshmallow-mr3-release/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java


1
โอ้เป็นข่าวดี! ดังนั้นจึงดูเหมือนว่าโซลูชันที่ใช้ "ขยาย PreferenceActivity" จะดีกว่าโซลูชัน "ขยาย ActionBarActivity" ในมุมมองใหม่นี้
Eugene Wechsler

1
@EugeneWechsler ใช่แน่นอนตอนนี้ ActionBarActivity เลิกใช้แล้ว
MrBrightside

ใช้โซลูชันนี้บนหน้าจอที่ซ้อนกันด้วยหรือไม่ มีตัวอย่างที่ดีกว่านี้ไหม?
Tomas

@ โทมัสฉันยังไม่ได้ลอง แต่ควรใช้กับหน้าจอที่ซ้อนกันด้วย หากเหมาะกับคุณโปรดแจ้งให้เราทราบ
MrBrightside

ขอบคุณมาก ! ทำงานให้ฉันบน Galaxy Nexus (4.3) และบนโปรแกรมจำลองที่มีหน้าจอซ้อนกัน (อมยิ้ม)
Tim Autin

6

แม้ว่าคำตอบข้างต้นจะดูซับซ้อน แต่หากคุณต้องการวิธีแก้ไขปัญหาอย่างรวดเร็วเพื่อใช้ Toolbar ที่รองรับ API 7 ขึ้นไปในขณะที่ขยายPreferenceActivityฉันได้รับความช่วยเหลือจากโครงการด้านล่างนี้

https://github.com/AndroidDeveloperLB/ActionBarPreferenceActivity

activity_settings.xml

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

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/app_theme_light"
    app:popupTheme="@style/Theme.AppCompat.Light"
    app:theme="@style/Theme.AppCompat" />

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/padding_medium" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

SettingsActivity.java

public class SettingsActivity extends PreferenceActivity {

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

    setContentView(R.layout.activity_settings);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

    addPreferencesFromResource(R.xml.preferences);

    toolbar.setClickable(true);
    toolbar.setNavigationIcon(getResIdFromAttribute(this, R.attr.homeAsUpIndicator));
    toolbar.setTitle(R.string.menu_settings);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            finish();
        }
    });

}

private static int getResIdFromAttribute(final Activity activity, final int attr) {
    if (attr == 0) {
        return 0;
    }
    final TypedValue typedvalueattr = new TypedValue();
    activity.getTheme().resolveAttribute(attr, typedvalueattr, true);
    return typedvalueattr.resourceId;
}
}

6

ฉันก็กำลังมองหาวิธีแก้ปัญหาในการเพิ่มแถบเครื่องมือการสนับสนุนv7 ( API 25 ) ไปยัง AppCompatPreferenceActivity (ที่ AndroidStudio สร้างขึ้นโดยอัตโนมัติเมื่อเพิ่ม SettingsActivity) หลังจากอ่านวิธีแก้ปัญหาหลายวิธีและลองใช้วิธีแก้ปัญหาแต่ละข้อฉันก็พยายามหาตัวอย่าง PreferenceFragment ที่สร้างขึ้นเพื่อแสดงด้วยแถบเครื่องมือเช่นกัน

โซลูชันที่ได้รับการแก้ไขซึ่งได้ผลมาจาก " Gabor "

คำเตือนอย่างหนึ่งที่ฉันเผชิญคือ 'onBuildHeaders' จะยิงเพียงครั้งเดียว หากคุณหมุนอุปกรณ์ (เช่นโทรศัพท์) ไปด้านข้างมุมมองจะสร้างขึ้นใหม่และ PreferenceActivity จะถูกปล่อยทิ้งไว้โดยไม่มีแถบเครื่องมืออีกครั้งอย่างไรก็ตาม PreferenceFragments จะยังคงอยู่

ฉันลองใช้ 'onPostCreate' เพื่อเรียก 'setContentView' ในขณะที่สิ่งนี้ทำงานเพื่อสร้างแถบเครื่องมือใหม่เมื่อการวางแนวเปลี่ยนไป PreferenceFragments จะแสดงผลว่างเปล่า

สิ่งที่ฉันได้มาจากการใช้ประโยชน์จากทุกเคล็ดลับและคำตอบที่ฉันสามารถอ่านเกี่ยวกับเรื่องนี้ ฉันหวังว่าคนอื่นจะพบว่ามีประโยชน์เช่นกัน

เราจะเริ่มต้นด้วยJava

อันดับแรกใน (ที่สร้างขึ้น) AppCompatPreferenceActivity.javaฉันแก้ไข 'setSupportActionBar' ดังนี้:

public void setSupportActionBar(@Nullable Toolbar toolbar) {
    getDelegate().setSupportActionBar(toolbar);
    ActionBar bar = getDelegate().getSupportActionBar();
    bar.setHomeButtonEnabled(true);
    bar.setDisplayHomeAsUpEnabled(true);
}

อย่างที่สองฉันสร้างคลาสใหม่ชื่อAppCompatPreferenceFragment.java (ปัจจุบันเป็นชื่อที่ไม่ได้ใช้แม้ว่ามันจะไม่เป็นอย่างนั้นก็ตาม!):

abstract class AppCompatPreferenceFragment extends PreferenceFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_settings, container, false);
        if (view != null) {
            Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar_settings);
            ((AppCompatPreferenceActivity) getActivity()).setSupportActionBar(toolbar);
        }
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        View frame = (View) getView().getParent();
        if (frame != null) frame.setPadding(0, 0, 0, 0);
    }
}

นี่คือส่วนหนึ่งของคำตอบของ Gabor ที่ได้ผล

สุดท้ายเพื่อให้ได้ความสม่ำเสมอเราจำเป็นต้องทำการเปลี่ยนแปลงบางอย่างในSettingsActivity.java :

public class SettingsActivity extends AppCompatPreferenceActivity {

    boolean mAttachedFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mAttachedFragment = false;
        super.onCreate(savedInstanceState);
    }

    @Override
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.pref_headers, target);
    }

    @Override
    public void onAttachFragment(Fragment fragment) {
        mAttachedFragment = true;
        super.onAttachFragment(fragment);
    }

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

        //if we didn't attach a fragment, go ahead and apply the layout
        if (!mAttachedFragment) {
            setContentView(R.layout.activity_settings);
            setSupportActionBar((Toolbar)findViewById(R.id.toolbar_settings));
        }
    }

    /**
     * This fragment shows general preferences only. It is used when the
     * activity is showing a two-pane settings UI.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static class GeneralPreferenceFragment extends AppCompatPreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            addPreferencesFromResource(R.xml.pref_general);
            setHasOptionsMenu(true);

            bindPreferenceSummaryToValue(findPreference("example_text"));
            bindPreferenceSummaryToValue(findPreference("example_list"));
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            if (id == android.R.id.home) {
                startActivity(new Intent(getActivity(), SettingsActivity.class));
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
}

โค้ดบางส่วนถูกปล่อยออกจากกิจกรรมเพื่อความกะทัดรัด ส่วนประกอบสำคัญที่นี่คือ ' onAttachedFragment ', ' onPostCreate ' และตอนนี้ 'GeneralPreferenceFragment' ขยาย ' AppCompatPreferenceFragment ' แบบกำหนดเองแทน PreferenceFragment

สรุปโค้ด : หากมีแฟรกเมนต์แฟรกเมนต์จะแทรกเลย์เอาต์ใหม่และเรียกใช้ฟังก์ชัน 'setSupportActionBar' ที่แก้ไขแล้ว ถ้าส่วนย่อยไม่มีอยู่ SettingsActivity จะแทรกเค้าโครงใหม่บน 'onPostCreate'

ตอนนี้ไปที่XML (ง่ายมาก):

activity_settings.xml :

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

    <include
        layout="@layout/app_bar_settings"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

app_bar_settings.xml :

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".SettingsActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.NoActionBar.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar_settings"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.NoActionBar.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_settings" />

</android.support.design.widget.CoordinatorLayout>

content_settings.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".SettingsActivity"
    tools:showIn="@layout/app_bar_settings">

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

ผลลัพธ์สุดท้าย :

SettingsActivity

GeneralPreferenceFragment


ดูมีแนวโน้ม แต่ไม่ได้ผลสำหรับฉัน imgur.com/lSSVCIo (โปรแกรมจำลอง Pixel C)
Thomas Vos

Github Linkสำหรับคนขี้เกียจ
Martin Sing

5

ฉันมีโซลูชันใหม่ (อาจจะดีกว่า) ซึ่งใช้AppCompatPreferenceActivityจากตัวอย่าง Support v7 ด้วยรหัสนี้ฉันสร้างเลย์เอาต์ของตัวเองที่มีแถบเครื่องมือ:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:fitsSystemWindows="true" tools:context="edu.adelphi.Adelphi.ui.activity.MainActivity">

    <android.support.design.widget.AppBarLayout android:id="@+id/appbar"
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

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

    </android.support.design.widget.AppBarLayout>

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

</android.support.design.widget.CoordinatorLayout>

จากนั้นในของAppCompatPreferenceActivityฉันฉันเปลี่ยนsetContentViewเพื่อสร้างเลย์เอาต์ใหม่ของฉันและวางเลย์เอาต์ที่ให้ไว้ภายในFrameLayout:

@Override
public void setContentView(@LayoutRes int layoutResID) {
    View view = getLayoutInflater().inflate(R.layout.toolbar, null);
    FrameLayout content = (FrameLayout) view.findViewById(R.id.content);
    getLayoutInflater().inflate(layoutResID, content, true);
    setContentView(view);
}

จากนั้นฉันก็ขยายAppCompatPreferenceActivityอนุญาตให้ฉันโทรsetSupportActionBar((Toolbar) findViewById(R.id.toolbar))และขยายรายการเมนูในแถบเครื่องมือได้เช่นกัน ทั้งหมดนี้ยังคงรักษาผลประโยชน์ของไฟล์PreferenceActivity.


5

มาทำให้มันง่ายและสะอาดที่นี่โดยไม่ทำลายเค้าโครงใด ๆ ที่สร้างขึ้น

import android.support.design.widget.AppBarLayout;
import android.support.v4.app.NavUtils;
import android.support.v7.widget.Toolbar;

private void setupActionBar() {
    Toolbar toolbar = new Toolbar(this);

    AppBarLayout appBarLayout = new AppBarLayout(this);
    appBarLayout.addView(toolbar);

    final ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
    final ViewGroup window = (ViewGroup) root.getChildAt(0);
    window.addView(appBarLayout, 0);

    setSupportActionBar(toolbar);

    // Show the Up button in the action bar.
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onBackPressed();
        }
    });
}

ไม่ได้ผลสำหรับฉันroot.getChildAt(0);กลับnullมา
Eido95

4

ฉันพบวิธีง่ายๆนี้ในขณะที่ทำงานนี้ ก่อนอื่นเราต้องสร้างเค้าโครงสำหรับกิจกรรมการตั้งค่า

activity_settings.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.my.package">

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:elevation="@dimen/appbar_elevation"
        app:navigationIcon="?attr/homeAsUpIndicator"
        app:navigationContentDescription="@string/abc_action_bar_up_description"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <ListView
        android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tool_bar" />

</RelativeLayout>

ตรวจสอบให้แน่ใจว่าคุณเพิ่มมุมมองรายการด้วยandroid:id="@android:id/list"มิฉะนั้นจะโยนNullPointerException

ขั้นตอนต่อไปคือการเพิ่มonCreateวิธีการ(Override) ในกิจกรรมการตั้งค่าของคุณ

Settings.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_settings);
    Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
    toolbar.setTitle(R.string.action_settings);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });
}

android.suppoer.v7.widget.Toolbarให้แน่ใจว่าคุณนำเข้า สิ่งนี้น่าจะใช้ได้กับ API ทั้งหมดที่สูงกว่า 16 (Jelly Bean ขึ้นไป)


1

ฉันต้องการดำเนินการแก้ปัญหาที่ทำเครื่องหมายไว้ของ James Cross ต่อไปเนื่องจากหลังจากนั้นมีปัญหาในการปิดเฉพาะหน้าจอซ้อนที่ใช้งานอยู่ (PreferenceFragment) เพื่อไม่ให้ปิด SettingsActivity เช่นกัน

จริงๆแล้วมันใช้งานได้กับหน้าจอที่ซ้อนกันทั้งหมด (ดังนั้นฉันไม่เข้าใจวิธีแก้ปัญหาของGáborที่ฉันลองแล้วไม่ประสบความสำเร็จมันใช้งานได้ดีจนถึงจุดหนึ่ง แต่มันยุ่งกับแถบเครื่องมือหลายอัน) เพราะเมื่อผู้ใช้คลิกหน้าจอการตั้งค่าย่อย เฉพาะส่วนที่เปลี่ยนแปลงเท่านั้น (ดู<FrameLayout android:id="@+id/content_frame" .../>) ไม่ใช่แถบเครื่องมือที่ยังคงใช้งานและมองเห็นได้เสมอแต่ควรใช้ลักษณะการทำงานที่กำหนดเองเพื่อปิดแต่ละส่วนให้สอดคล้องกัน

ในคลาสหลักSettingsActivityที่ขยายActionBarActivityวิธีการต่อไปนี้ควรดำเนินการ โปรดทราบว่าส่วนตัวsetupActionBar()ถูกเรียกจากonCreate()

private void setupActionBar() {
    Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
    //Toolbar will now take on default Action Bar characteristics
    setSupportActionBar(toolbar);
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

}

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

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0) {
        getFragmentManager().popBackStackImmediate();
        //If the last fragment was removed then reset the title of main
        // fragment (if so the previous popBackStack made entries = 0).
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            getSupportActionBar()
                .setTitle(R.string.action_settings_title);
        }
    } else {
        super.onBackPressed();
    }
}

สำหรับชื่อของหน้าจอที่ซ้อนกันที่เลือกคุณควรได้รับการอ้างอิงของ Toolbar ของคุณและตั้งชื่อที่เหมาะสมด้วยtoolbar.setTitle(R.string.pref_title_general);(เช่น)

นอกจากนี้ไม่จำเป็นที่จะใช้getSupportActionBar()ในทุก PreferenceFragment ตั้งแต่เพียงมุมมองของชิ้นส่วนที่มีการเปลี่ยนแปลงทุกครั้งที่กระทำไม่ได้แถบเครื่องมือ;

นอกจากนี้ไม่จำเป็นต้องมีการสร้างระดับปลอม ToolbarPreference ที่จะเพิ่มในแต่ละ preference.xml (ดูคำตอบของGábor)


1

นี่คือไลบรารีที่ฉันสร้างขึ้นโดยใช้รหัส AOSP ซึ่งเพิ่มการย้อมสีให้กับทั้งการตั้งค่าและกล่องโต้ตอบเพิ่มแถบการดำเนินการและรองรับทุกเวอร์ชันจาก API 7:

https://github.com/AndroidDeveloperLB/MaterialPreferenceLibrary


จากการดูโค้ดมันใช้ไม่ได้กับค่ากำหนดที่ซ้อนกัน ... ?
Tim Rae

@ TimRae ฉันไม่แน่ใจว่าฉันได้ทดสอบสิ่งที่คุณกำลังพูดถึง โปรดอธิบายว่าคุณหมายถึงอะไร สถานการณ์ที่คุณพยายามจะใช้คืออะไร?
นักพัฒนา android

เมื่อคุณมีPreferenceScreenภายในPreferenceScreenเช่นนี้
ทิมแร

ฉันไม่เคยใช้สิ่งนี้ อ่านเอกสาร:: developer.android.com/reference/android/preference/…ฉันเห็นว่ามันสามารถช่วยในการไปมาระหว่างหน้าจอได้ คุณบอกว่าฉันควรจะเพิ่มด้วย? ฉันจะตรวจสอบมันออกมา . ขอบคุณ. นอกจากนี้โปรดใช้ Github ในครั้งต่อไปสำหรับสิ่งดังกล่าว (คำขอและปัญหา)
นักพัฒนา Android

ใช่มันมีประโยชน์เมื่อคุณมีค่ากำหนดมากเกินไปสำหรับหน้าจอเดียว ... มีหลายที่แล้วในหัวข้อนี้ที่ผู้คนพูดถึงหน้าจอที่ซ้อนกันดังนั้นฉันคิดว่าที่นี่เป็นสถานที่ที่เหมาะสมในการแสดงความคิดเห็น
Tim Rae

1

นี่ยังคงเป็นปัญหาสำหรับฉันในวันนี้ (18 พ.ย. 2558) ฉันได้ลองวิธีแก้ปัญหาทั้งหมดจากเธรดนี้แล้ว แต่มีสองสิ่งหลักที่ฉันแก้ไม่ได้:

  • หน้าจอค่ากำหนดที่ซ้อนกันปรากฏขึ้นโดยไม่มีแถบเครื่องมือ
  • ค่ากำหนดไม่มีรูปลักษณ์วัสดุในอุปกรณ์รุ่นก่อนอมยิ้ม

ดังนั้นฉันจึงลงเอยด้วยการสร้างไลบรารีด้วยโซลูชันที่ซับซ้อนมากขึ้น โดยทั่วไปฉันต้องใช้สไตล์ภายในกับค่ากำหนดหากเราใช้อุปกรณ์ pre-Lollipop และฉันยังจัดการหน้าจอที่ซ้อนกันโดยใช้แฟรกเมนต์ที่กำหนดเอง (เรียกคืนลำดับชั้นที่ซ้อนกันทั้งหมดโดยใช้ประโยชน์จากคีย์ PreferenceScreen )

ห้องสมุดคือห้องสมุดนี้: https://github.com/ferrannp/material-preferences

และหากคุณสนใจซอร์สโค้ด (ยาวเกินไปที่จะโพสต์ที่นี่) นี่คือหลักของมัน: https://github.com/ferrannp/material-preferences/blob/master/library/src/main/ java / co.th / FNP / materialpreferences / PreferenceFragment.java

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.