我在首选项屏幕上的支持库中使用新的Material Design工具栏时遇到了问题。
我有一个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>
字符串在别处定义。
答案 0 :(得分:108)
请找到GitHub回购: Here
派对有点晚了,但这是我用来继续使用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:
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
之所以如此痛苦是因为它们基于包装器对话框,因此我们需要捕获对话框布局以将工具栏添加到其中。
通过设计导入Toolbar
不允许在v21之前的设备中进行高程和阴影,因此如果您希望对Toolbar
进行提升,则需要将其包含在{{1}中}}:
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
我已经调查了报告的重叠问题,我无法重现这个问题。
上面使用的完整代码产生以下内容:
如果我遗失了某些内容,请通过this repo告诉我,我会进行调查。
答案 1 :(得分:105)
您可以使用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);
}
}
我希望这有助于某人。
答案 2 :(得分:48)
全新更新。
通过一些实验,我似乎找到了适用于嵌套首选项屏幕的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>
在此之前,网上的解决方案没有真正的区别。实际上,即使你没有嵌套屏幕,没有标题,只有一个屏幕,你也可以使用它。
我们对所有较深的页面使用通用PreferenceFragment
,并根据标题中的extra
参数进行区分。每个页面都有一个单独的XML,内部有一个PreferenceScreen
(xml/settings_page1.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()
进行添加工具栏等所有操作。
唯一真正的区别在于,使用嵌套屏幕的原因是你可以对片段使用相同的方法。您可以以相同的方式使用他们的{{1}},膨胀您自己的布局而不是系统布局,添加工具栏的方式与活动相同。
答案 3 :(得分: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>
答案 4 :(得分:17)
随着Android支持库22.1.0和新的AppCompatDelegate的发布,您可以在这里找到一个很好的PreferenceActivity实现示例,其中包含具有向后兼容性的材料支持。
<强>更新强> 它也适用于嵌套屏幕。
答案 5 :(得分:6)
虽然上面的答案看起来很复杂,但是如果你想要一个快速修复解决方案来使用支持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 :(得分:6)
我也一直在寻找将 v7 支持工具栏( API 25 )添加到AppCompatPreferenceActivity(在添加SettingsActivity时由AndroidStudio自动创建)的解决方案。在阅读了几个解决方案并尝试了每个解决方案之后,我努力将生成的PreferenceFragment示例也显示在工具栏中。
一种改进的解决方案,其工作方式来自&#34; Gabor &#34;。
我遇到的一个警告是“onBuildHeaders&#39;只发射一次。如果您将设备(如手机)侧向翻转,则会重新创建视图,并且PreferenceActivity将再次没有工具栏,但PreferenceFragments会保留它们。
我尝试使用&#39; onPostCreate&#39;调用&#39; setContentView&#39;,虽然这可以在方向更改时重新创建工具栏,但PreferenceFragments将呈现为空白。
我提出的内容充分利用了我能读到的有关此主题的每个提示和答案。我希望其他人也觉得它很有用。
我们将从 Java
开始首先(生成的) AppCompatPreferenceActivity.java 我修改了&#39; setSupportActionBar&#39;像这样:
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);
}
}
}
为简洁起见,部分代码已被排除在活动之外。这里的关键组件是&#39; onAttachedFragment &#39; <#39; onPostCreate &#39;以及&#39; GeneralPreferenceFragment&#39;现在扩展自定义&#39; AppCompatPreferenceFragment &#39;而不是PreferenceFragment。
代码摘要:如果存在片段,片段会注入新的布局并调用已修改的&#39; setSupportActionBar&#39;功能。如果片段不存在,则SettingsActivity会在&#39; onPostCreate&#39;
上注入新的布局现在开始 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>
最终结果:
答案 7 :(得分:5)
我有一个新的(可能更整洁的)解决方案,它使用Support v7示例中的AppCompatPreferenceActivity
。有了这个代码,我创建了自己的布局,其中包括一个工具栏:
<?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
的好处。
答案 8 :(得分:5)
让我们保持简单&amp;在这里干净,不破坏任何内置布局
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();
}
});
}
答案 9 :(得分: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
方法
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及以上)
答案 10 :(得分: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.setTitle(R.string.pref_title_general);
设置相应的标题(例如)。
不需要在所有PreferenceFragment中实现getSupportActionBar()
,因为只有片段的视图在每次提交时都会更改,而不是工具栏;
无需创建一个假的ToolbarPreference类,以便在每个preference.xml中添加(参见Gábor的回答)。
答案 11 :(得分:1)
这是我创建的基于AOSP代码的库,它为首选项和对话框添加了着色,添加了操作栏,并支持API 7中的所有版本:
https://github.com/AndroidDeveloperLB/MaterialPreferenceLibrary
答案 12 :(得分:1)
嗯,这对我来说仍然是个问题(2015年11月18日)。我已经尝试过这个主题的所有解决方案,但有两件事我无法解决:
所以我最终创建了一个包含更复杂解决方案的库。基本上,如果我们使用pre-Lollipop设备,我必须在内部将样式应用于首选项,并且我还使用自定义片段处理嵌套屏幕(使用PreferenceScreen 键恢复所有嵌套层次结构 )。
图书馆就是这个:https://github.com/ferrannp/material-preferences
如果您对源代码感兴趣(这里发布的时间太长),这基本上就是它的核心:https://github.com/ferrannp/material-preferences/blob/master/library/src/main/java/com/fnp/materialpreferences/PreferenceFragment.java