IT

지원 (v21) 사용하여 환경 설정 화면 만들기

lottoking 2020. 7. 21. 07:43
반응형

지원 (v21) 사용하여 환경 설정 화면 만들기


환경 설정 화면의 지원 라이브러리에서 새 재질 디자인 도구 모음을 사용하는 데 문제가 있습니다.

여기서 같이 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>

어디에서나 정의되어 있습니다.


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 :

예


업데이트 (진저 브레드 새로운) :

의견에 따라 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;
}

필수 환경 설정 화면

많은 사람들이 중첩되는 데 문제가 발생 <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는 래퍼 대화 상자를 기반으로하기 때문에 도구 모음을 추가하기 위해 대화 상자를 레이아웃해야하기 때문입니다.


도구 그림자

가져 오기 오기를 디자인하면 Toolbarv21 이전 장치에서 고도 및 음영을 허용하지 않도록 고도를 높이려면 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>

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'

안드로이드 6.0

보고 된 겹치는 문제를 조사한 결과 문제를 재현 할 수 없습니다.

위와 같이 사용중인 전체 코드는 다음을 생성합니다.

여기에 이미지 설명을 입력하십시오

누락 된 내용이 있으면이 리포지토리 를 통해 알려 주시면 조사하겠습니다.


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

나는 누군가를 돕기를 바랍니다.


완전히 새로운 업데이트.

몇 가지 실험을 통해 중첩 된 환경 설정 화면을위한 AppCompat 22.1 + 솔루션이 작동하는 것이 있습니다.

먼저 많은 답변 (여기에서 답변 포함)에서 언급했듯이 새로운 내용을 포함합니다 AppCompatDelegate. AppCompatPreferenceActivity.java지원 데모 ( https://android.googlesource.com/platform/development/+/58bf5b99e6132332afb8b44b4c8cedf5756ad464/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java ) 에서 파일을 사용 하고 확장하십시오. 그것으로부터, 또는 관련 기능을 자신의 복사하십시오 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>

이 시점까지 인터넷상의 솔루션과 유일한 차이는 없습니다. 실제로 중첩 된 화면이없고 머리글이없고 단일 화면 만 있어도이를 사용할 수 있습니다.

헤더 PreferenceFragmentextra변수로 구분 된 모든 더 깊은 페이지에 공통 사용합니다 . 각 페이지에는 공통 PreferenceScreen내부 (예 : xml/settings_page1.xml기타) 가있는 별도의 XML이 있습니다 . 조각은 기사를 포함하여 활동과 동일한 레이아웃을 사용합니다.

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()활동과 도구 모음 같은 방법으로 추가, 시스템 하나 대신 자신의 레이아웃을 확장, 같은 방법으로.


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>

여기에서 원하는 레이아웃을 사용할 수 있습니다. 자바 코드를 조정하십시오.

마지막으로 헤더가있는 파일 (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>

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


위의 답변은 정교 해 보이지만 확장하는 동안 도구를 지원 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;
}
}

나도 v7 지원 기능 ( API 25 )을 AppCompatPreferenceActivity (SettingsActivity를 추가 할 때 AndroidStudio에 의해 자동으로 생성됨) 에 추가하는 솔루션을 찾고 생성됨 . 여러 솔루션을 읽고 각 솔루션을 본 후 생성 된 PreferenceFragment 예제를 사용하여 표시하는 데 어려움을 겪습니다.

변형 된 솔루션은 " Gabor "입니다.

내가 거주하는 경고 중 하나는 'onBuildHeaders'가 한 번만 발생한다는 것입니다. 장치 (예 : 전화기)로 돌리면보기가 다시 작성되고 도구 모음없이 PreferenceActivity가 다시 유지되고 PreferenceFragments는 해당 장치를 유지합니다.

'onPostCreate'를 사용하여 'setContentView'를 호출하려고 시도했지만 방향이 변경 될 때 도구 모음을 다시 작성하면 PreferenceFragments가 공백으로 표시됩니다.

내가 생각해 낸 것은 거의 모든 팁과 답변을 활용합니다. 다른 사람들도 유용하게 사용하기를 바랍니다.

우리는 자바로 시작할 것입니다

먼저 (생성 된) 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'는 이제 PreferenceFragment 대신 사용자 정의 ' AppCompatPreferenceFragment '를 확장합니다 .

코드 요약 : 프래그먼트가있는 경우 프래그먼트는 새 레이아웃을 삽입하고 수정 된 'setSupportActionBar'함수를 호출합니다. 프래그먼트가 설정 활동가 '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>

최종 결과 :

설정 활동

일반 환경 설정


AppCompatPreferenceActivity지원 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.


내장 된 레이아웃을 깨지 않고 간단하고 깔끔하게 유지하십시오.

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

이 작업을하는 동안이 간단한 해결을 찾았습니다. 먼저 설정 활동을위한 레이아웃을 먼저 지정합니다.

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설정 활동에 (재정의) 메소드 를 추가하는 것입니다

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합니다. 이것은 16 이상의 모든 API (Jelly Bean 이상)에서 거의 작동합니다.


James Cross의 솔루션을 계속 유지하고 싶습니다. 그 후에 SettingsActivity도 닫지 않는 방식으로 활성 중첩 화면 (PreferenceFragment) 만 닫는 문제가 있습니다.

모든 중첩 된 화면에서 작동합니다 (그래서 성공하지 않고 시도한 Gábor 솔루션을 이해하지 못합니다. 특정 시점까지 작동하지만 여러 도구 모음의 혼란입니다). 사용자가 하위 환경 설정 화면을 클릭하면 만 조각이 (참조 변경 <FrameLayout android:id="@+id/content_frame" .../>) 항상 적극적이고 계속 표시 도구 모음 하지만, 행동이 행동이 따라 추가의 조각을 닫습니다.

메인 클래스 에서 다음 메소드 SettingsActivity를 확장 ActionBarActivity해야합니다. private 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.setTitle(R.string.pref_title_general);(예를 들어) 설정해야합니다.

없습니다 필요 을 구현하는 getSupportActionBar()조각의 뷰가없는 도구 모음, 커밋마다에서 변경되기 때문에 모든 PreferenceFragment으로는;

없습니다 필요 (가보의 답변을 참조) 각 preference.xml에 추가하는 가짜의 ToolbarPreference 클래스를 만들 수는.


다음은 AOSP 코드를 기반으로 만든 라이브러리입니다.이 라이브러리는 환경 설정과 대화 상자 모두에 색조를 추가하고 작업 표시 줄을 추가하며 API 7의 모든 버전을 지원합니다.

https://github.com/AndroidDeveloperLB/MaterialPreferenceLibrary


글쎄요, 이것은 오늘날 저에게 여전히 문제입니다 (2015 년 11 월 18 일). 이 스레드에서 모든 솔루션을 시도했지만 해결할 수없는 두 가지 주요 사항이 있습니다.

  • 도구 모음없이 중첩 된 기본 설정 화면이 나타남
  • 롤리팝 이전 기기에서 환경 설정에 머티리얼 모양이 없었습니다.

그래서 결국 더 복잡한 솔루션으로 라이브러리를 만들었습니다. 기본적으로 사전 롤리팝 장치를 사용하는 경우 내부적으로 기본 설정에 스타일을 적용해야하고 사용자 지정 프래그먼트를 사용하여 중첩 된 화면도 처리했습니다 (PreferenceScreen 를 활용하여 모든 중첩 된 계층 구조 복원 ).

라이브러리는 https://github.com/ferrannp/material-preferences입니다.

그리고 소스 코드에 관심이 있다면 (여기에 게시하기에는 너무 길다), 이것이 기본적으로 핵심입니다 : https://github.com/ferrannp/material-preferences/blob/master/library/src/main/ java / com / fnp / materialpreferences / PreferenceFragment.java

참고 URL : https://stackoverflow.com/questions/26564400/creating-a-preference-screen-with-support-v21-toolbar

반응형