升级到支持库 v21 后 PreferenceActivity 中没有 ActionBar [英] No ActionBar in PreferenceActivity after upgrade to Support Library v21

查看:29
本文介绍了升级到支持库 v21 后 PreferenceActivity 中没有 ActionBar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

升级到支持库 v21 后,我的 ,Gingerbread 设备在这一行返回 NullPointerException:

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

修正:

SettingsActivity.java :

公共类 SettingsActivity 扩展 PreferenceActivity {@覆盖protected void onPostCreate(Bundle savedInstanceState) {super.onPostCreate(savedInstanceState);工具栏;如果 (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);//在顶部插入} 别的 {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);整数高度;TypedValue tv = new TypedValue();如果 (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());}别的{高度 = bar.getHeight();}content.setPadding(0, height, 0, 0);root.addView(内容);root.addView(bar);}bar.setNavigationOnClickListener(new View.OnClickListener() {@覆盖public void onClick(View v) {结束();}});}}

以上有任何问题请告诉我!


更新 2:着色解决方法

正如许多开发说明中所指出的,PreferenceActivity 不支持元素着色,但是通过使用一些内部类,您可以实现这一点.直到这些类被删除.(使用 appCompat support-v7 v21.0.3 工作).

添加以下导入:

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

然后覆盖onCreateView方法:

@Override公共视图 onCreateView(字符串名称,上下文上下文,属性集属性){//允许超级先尝试创建一个视图最终视图结果 = super.onCreateView(name, context, attrs);如果(结果!= null){返回结果;}如果 (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {//如果我们正在运行 pre-L,我们需要注入"我们的色彩感知视图来代替//标准框架版本开关(名称){案例EditText":返回新的 TintEditText(this, attrs);案例旋转器":返回新的 TintSpinner(this, attrs);案例复选框":返回新的 TintCheckBox(this, attrs);案例RadioButton":返回新的 TintRadioButton(this, attrs);案例CheckedTextView":返回新的 TintCheckedTextView(this, attrs);}}返回空;}

结果:


AppCompat 22.1

AppCompat 22.1 引入了新的着色元素,这意味着不再需要利用内部类来实现与上次更新相同的效果.而是遵循这个(仍然覆盖 onCreateView):

@Override公共视图 onCreateView(字符串名称,上下文上下文,属性集属性){//允许超级先尝试创建一个视图最终视图结果 = super.onCreateView(name, context, attrs);如果(结果!= null){返回结果;}如果 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {//如果我们正在运行 pre-L,我们需要注入"我们的色彩感知视图来代替//标准框架版本开关(名称){案例EditText":返回新的 AppCompatEditText(this, attrs);案例旋转器":返回新的 AppCompatSpinner(this, attrs);案例复选框":返回新的 AppCompatCheckBox(this, attrs);案例RadioButton":返回新的 AppCompatRadioButton(this, attrs);案例CheckedTextView":返回新的 AppCompatCheckedTextView(this, attrs);}}返回空;}


嵌套首选项屏幕

很多人在将工具栏包含在嵌套的 <PreferenceScreen/> 中时遇到问题,但是,我找到了解决方案!!- 经过大量的反复试验!

将以下内容添加到您的 SettingsActivity:

@SuppressWarnings(弃用")@覆盖公共布尔 onPreferenceTreeClick(PreferenceScreen 首选项屏幕,首选项首选项){super.onPreferenceTreeClick(preferenceScreen,preference);//如果用户点击了偏好屏幕,则设置屏幕if (preference instanceof PreferenceScreen) {setUpNestedScreen((PreferenceScreen) 偏好);}返回假;}public void setUpNestedScreen(PreferenceScreen preferredScreen) {最终的对话对话框=preferenceScreen.getDialog();工具栏;如果 (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);//在顶部插入} 别的 {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);整数高度;TypedValue tv = new TypedValue();如果 (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());}别的{高度 = bar.getHeight();}content.setPadding(0, height, 0, 0);root.addView(内容);root.addView(bar);}bar.setTitle(preferenceScreen.getTitle());bar.setNavigationOnClickListener(new View.OnClickListener() {@覆盖public void onClick(View v) {dialog.dismiss();}});}

PreferenceScreen 之所以如此痛苦,是因为它们基于包装对话框,因此我们需要捕获对话框布局以向其中添加工具栏.


工具栏阴影

通过设计导入 Toolbar 不允许在 v21 之前的设备中进行高程和阴影,所以如果你想在你的 Toolbar 上有高程,你需要换行它在 AppBarLayout 中:

`settings_toolbar.xml :

如果我遗漏了什么,请通过这个 repo 告诉我,我会调查.

After I upgraded to the Support Library v21 my ActionBar in my PreferenceActivity is gone.

Did I miss some attributes in my theme to activate it again? I had some similar trouble with a black ActionBar.

I also tried to add it a little hackish by adding a Toolbar to the root layout, but that did not work as expected.

解决方案

Please find the GitHub Repo: Here


Very Similar to your own code but added xml to allow for set title:

Continuing to use 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 Compatibility) :

As pointed out here, Gingerbread Devices are returning NullPointerException on this line:

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

FIX:

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

Any issues with the above let me know!


UPDATE 2: TINTING WORKAROUND

As pointed out in many dev notes PreferenceActivity does not support tinting of elements, however by utilising a few internal classes you CAN achieve this. That is until these classes are removed. (Works using appCompat support-v7 v21.0.3).

Add the following imports:

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;

Then override the onCreateView method:

@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

AppCompat 22.1 introduced new tinted elements, meaning that there is no longer a need to utilise the internal classes to achieve the same effect as the last update. Instead follow this (still overriding 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;
}


NESTED PREFERENCE SCREENS

A lot of people are experiencing issues with including the Toolbar in nested <PreferenceScreen />s however, I have found a solution!! - After a lot of trial and error!

Add the following to your 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();
        }
    });
}

The reason that PreferenceScreen's are such a pain is because they are based as a wrapper dialog, so we need to capture the dialog layout to add the toolbar to it.


Toolbar Shadow

By design importing the Toolbar does not allow for elevation and shadowing in pre-v21 devices, so if you would like to have elevation on your Toolbar you need to wrap it in a AppBarLayout:

`settings_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>

Not forgetting to add the add the Design Support library as a dependency in build.gradle file:

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

I have investigated the reported overlapping issue and I cannot reproduce the issue.

The full code in use as above produces the following:

If I am missing something please let me know via this repo and I will investigate.

这篇关于升级到支持库 v21 后 PreferenceActivity 中没有 ActionBar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆