升级到 Support Library v21后,Preferences 活动中没有 ActionBar

在我升级到支持库 v21之后,我的 PreferenceActivity中的操作栏就不见了。

我错过了一些属性在我的主题激活它吗? 我有一些类似的问题与 一个黑色的动作条

我还试图通过在根布局中添加 Toolbar来添加一些骇客行为,但是这并没有像预期的那样起作用。

40505 次浏览

嗨,我不是,如果你还有这个问题。但是我想我会把我所做的来解决这个问题,并且希望它能帮助到别人。

1)首先,你可能已经注意到 PreferenceActivity 扩展了 ListActivity,而 ListActivity 又依次从 Activity 扩展。

根据开发人员博客(http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html)上的评论,要使用 v21,所有活动都必须从 ActionBarActivity 继承。这就是你的问题所在。

2)我过去解决的步骤是:

a) Make sure that you set the Theme of your PreferenceActivity to inherits one ot the Theme.AppCompat Themes.


b) Make your class PreferenceActivity extends ActionBarActivity.


c) Use the PreferenceFragment as your container for all your preferences.

这应该能解决问题。

干杯!

最后,我用这个简单的代码自己添加了工具栏:

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

下面是我的偏好 _ toolbar. xml:

<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
app:navigationContentDescription="@string/abc_action_bar_up_description"
android:background="?attr/colorPrimary"
app:navigationIcon="?attr/homeAsUpIndicator"
app:theme="@style/Theme.Toolbar" />

请找到 GitHub Repo: < a href = “ https://github.com/davcpas1234/Materials Settings”rel = “ noReferrer”> Here


与您自己的代码非常相似,但是添加了 xml 以支持设置 title:

继续使用 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 :

example


更新(姜饼兼容性) :

正如 给你所指出的,姜饼设备在这一行返回 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.JELLY_BEAN) {
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:

example 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.JELLY_BEAN) {
// 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的高度你需要把它包装在一个 AppBarLayout:

设置 _ toolbar.xml:

<android.support.design.widget.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">


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


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

别忘了在 build.gradle文件中添加 Design Support 库作为依赖项:

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

我已经调查了所报告的重叠问题,但我无法复制这个问题。

正在使用的上述完整代码产生以下内容:

enter image description here

如果我错过了什么,请通过 这个回购让我知道,我会调查。

使用 AppCompatActivity & Preferences 片段来解决这个问题:

活动:

public class SettingsActivity extends AppCompatActivity {


@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}}

偏好片段:

public class SettingsFragment extends PreferenceFragment {


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_preferences);
}}

比“滚动您自己的”操作栏更好的解决方案是使用 应用程序同伴代理类,它允许您从支持库中引入一个实际的操作栏。下面是使用它的示例代码,摘自 Ľubomír Kučera 对 ABc1的回答。

...
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
...


public class SettingsActivity extends PreferenceActivity {


private AppCompatDelegate mDelegate;


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


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


public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}


public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}


@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}


@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}


@Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}


@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}


@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}


@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}


@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}


@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}


@Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}


@Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}


public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}


private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}

我想到了一个简单的方法,那就是重写:

@android:style/Theme.Material.Light.DarkActionBar

以你的风格:

<style name="SettingsTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
<item name="android:colorPrimary">@color/sunshine_blue</item>
<item name="android:colorPrimaryDark">@color/sunshine_dark_blue</item>
</style>

我做了一些类似的接受问题,但我使用我的布局在其他活动以及(MainActivity太) ,所以我不能只硬编码一个箭头在它。

对我有效的方法是:

private void setupActionBar() {
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar toolbar = (Toolbar)LayoutInflater.from(this).inflate(R.layout.app_bar, root, false);
root.addView(toolbar, 0);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
}

我也有同样的问题。只需尝试将活动的主题更改为包含任何 ActionBar 的主题即可。在 SettingsActivity 的活动标签中添加以下一行对我来说很合适:

android:theme="Theme.AppCompat.DayNight.DarkActionBar"