Action Bar兼容性已添加到支持库的修订版18中。它现在具有ActionBarActivity
用于在旧版本的Android上使用Action Bar创建活动的类。
有什么方法可以将Action Bar从支持库添加到PreferenceActivity
吗?
以前,我使用ActionBarSherlock并具有SherlockPreferenceActivity
。
Action Bar兼容性已添加到支持库的修订版18中。它现在具有ActionBarActivity
用于在旧版本的Android上使用Action Bar创建活动的类。
有什么方法可以将Action Bar从支持库添加到PreferenceActivity
吗?
以前,我使用ActionBarSherlock并具有SherlockPreferenceActivity
。
Answers:
编辑:在appcompat-v7 22.1.0中,Google添加了AppCompatDelegate抽象类作为委托,您可以用来将AppCompat的支持扩展到任何活动。
像这样使用它:
...
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;
}
}
没有更多的黑客攻击。来自AppCompatPreferenceActivity.java的代码。
(ViewGroup) getWindow().getDecorView().getRootView()
我设法创建了一种类似于Google Play商店使用的解决方法。链接到原始答案
与您自己的代码非常相似,但添加了xml以允许设置标题:
继续使用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 :
正如指出的在这里,姜饼设备是在这条线返回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 />
s中但是,我找到了解决方案!-经过大量的反复试验!
将以下内容添加到您的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
:
`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'
我已经调查了所报告的重叠问题,因此无法重现该问题。
上面使用的完整代码产生以下内容:
如果我遗漏了一些东西,请通过此仓库让我知道,我将进行调查。
:)
PreferenceActivity
在屁股上这么疼???应该节省时间。我不妨进行常规活动,然后自己亲自以线性布局布置所有设置。Fuuuuck!
找到了基于support-v4 Fragment的PreferenceFragment实现:
https://github.com/kolavar/android-support-v4-preferencefragment
编辑:我刚刚测试了它,并且效果很好!
整合 PreferenceActivity
至少对我而言,无法与ABC。我尝试了两种可能找到的可能性,但没有一种可行:
ActionBarPreferenceActivity
延伸PreferenceActivity
。执行此操作时,您会受到的限制ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
。另外,您需要实现ActionBar.Callbacks
无法访问的内容
ActionBarPreferenceActivity
延伸ActionBarActivity
。这种方法需要重写一个全新的PreferenceActivity
,PreferenceManager
并且可能PreferenceFragment
意味着您需要访问诸如这样com.android.internal.util.XmlUtils
的隐藏类。解决方案只能来自Google开发人员,他们实施了ActionBarWrapper
可以添加到任何活动中的。
如果您真的需要进行偏好活动,那么我的建议是ActionBarSherlock
。
但是,我设法在这里实现它。
在OP想知道我们怎样才能把MenuItem
S IN的ActionBar
的PreferenceActivity
预蜂窝,因为Android的支持库具有不允许这种情况发生的错误。
我已经找到一种比已经提出的方法更清洁的方法来实现目标(并在Android Docs中找到了它):
android:parentActivityName
活动的逻辑父级的类名称。此处的名称必须与赋予相应元素的android:name属性的类名称匹配。
当用户按下操作栏中的“向上”按钮时,系统会读取该属性以确定应该开始哪个活动。系统还可以使用此信息与TaskStackBuilder合成活动的后向堆栈。
为了支持API级别4-16,您还可以使用指定“ android.support.PARENT_ACTIVITY”值的元素声明父活动。例如:
<activity android:name="com.example.app.ChildActivity" android:label="@string/title_child_activity" android:parentActivityName="com.example.myfirstapp.MainActivity" > <!-- Parent activity meta-data to support API level 4+ --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.app.MainActivity" /> </activity>
现在,执行您通常在自己的计算机中执行的操作onOptionsItemSelected()
。由于它是Android文档的一部分,因此没有任何副作用。
快乐的编码。:)
如果您以棒棒糖为目标,此解决方案将不再起作用。如果您使用的是AppCompat,那么此答案就是您所需要的。
PreferencesActivity
无法将任何物品放入ActionBar
,特别是后退按钮。我的答案是一个很好的解决方案。
:)
我能够android.app.Actionbar
通过使用获得getActionBar()
。它首先返回一个空值...然后我进入清单并将主题更改为:
android:theme="@style/Theme.AppCompat"
然后,我又有了操作栏。我假设这仅适用于某些构建级别。因此,您可能需要检查内部版本号或检查返回的值是否为null。
对我来说很好,因为我正在使用的应用程序是ICS/4.0
+。
现在,此问题的正式答案已经发布。这是v7 / v14首选项支持库。
请参阅如何使用v7 / v14首选项支持库?讨论如何使用它。