サポートライブラリv21にアップグレードした後、PreferenceActivityにActionBarがありません


83

サポートライブラリv21にアップグレードした後、私のActionBarPreferenceActivityはなくなりました。

テーマを再度アクティブにするために、テーマのいくつかの属性を見逃しましたか?黒のActionBarでも同様の問題が発生しまし

またToolbar、ルートレイアウトにを追加して少しハックを追加しようとしましたが、期待どおりに機能しませんでした。


あなたは好みフラグメントを使用する必要があります。developer.android.com/reference/android/preference/...
ジャレドバローズ

1
@ JaredBurrows3.0より前のPreferenceFragmentは使用できません
tyczj 2014年

1
私も使っています。AFIKPreferenceFragmentsを使用するPreferenceActivityにリンクする必要があります。ただし、tycyjが指摘しているように、レガシーサポートにも必要です。
rekire

1
ツールバーは単なるビューです。どこにでも追加できます。
Jared Burrows

1
私がここで作成した例を確認できます:github.com/AndroidDeveloperLB/MaterialPreferenceLibrary –android
開発者

回答:


170

GitHubリポジトリを見つけてください:ここ


独自のコードと非常に似ていますが、タイトルを設定できるように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 :

例


更新(ジンジャーブレッドの互換性):

ここで指摘されているように、GingerbreadDevicesは次の行で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サポート-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.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それらがラッパーダイアログとして基づいているので、我々はそれにツールバーを追加するには、ダイアログのレイアウトをキャプチャする必要があるので、のは、このような痛みですが、あります。


ツールバーシャドウ

設計上インポートすると、Toolbarv21より前のデバイスでは標高とシャドウイングが許可されないため、標高を設定したい場合は、次のようToolbarにラップする必要があります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>

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'

Android 6.0

報告された重複する問題を調査しましたが、問題を再現できません。

上記のように使用されている完全なコードは、次のように生成されます。

ここに画像の説明を入力してください

何か足りないものがある場合は、このリポジトリからお知らせください。調査させていただきます。


いいですね:私は最初のアプローチを使用しました(ジンジャーブレッドは私の目標にはありません)。ありがとうございました!
JJ86 2015年

この例を使用すると、ジンジャーブレッドで上ボタンが壊れているようです。
idunnololz 2015年

1
あなたの素晴らしい答えをありがとう、私は数日前にあなたに受け入れられた状態を与えました。見栄えが良くなるように、着色部分をコピーしました:)
2015

1
私は自分自身を正さなければなりません。android:themeこの問題を回避するには、唯一のAndroid 5.0以上のためのツールバーで黒のテキストの色を修正します。新しいサポートライブラリで何かが変更されたように見えます(私は22.2.0を使用しています)。
トニー2015年

4
android.R.id.listの親はandroidNのFrameLayoutです
zys 2016年

45

AppCompatActivity&PreferenceFragmentを使用して、問題を解決します。

AppCompatActivity:

public class SettingsActivity extends AppCompatActivity {

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

PreferenceFragment:

public class SettingsFragment extends PreferenceFragment {

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

1
ActionBarActivityは非推奨です。
rekire 2015

@rekire its android.support.v7.app.ActionBarActivity
Abdullah

4
ActionBarActivityの代わりにAppCompatActivityを拡張するだけです。
SammyT 2015年

1
私のために働いた、そして上記よりはるかに簡単。
Aaron Blenkush 2015年

1
単純な設定画面の場合、これは実装がはるかに簡単なソリューションです。
Chris Cirefice 2016

7

私はこの単純なコードでツールバーを自分で追加することになりました:

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

これが私のpreferences_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" />

私はそれをonCreate()に入れたと思います
2016年

6

「独自の」アクションバーをロールするよりも優れたソリューションは、AppCompatDelegateクラスを使用することです。これにより、サポートライブラリから実際のアクションバーを取り込むことができます。これは、この質問に対するĽubomírKučeraの回答から抜粋した、それを使用するためのサンプルコードです。

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

4
公式v7サンプルからの別名AppCompatPreferenceActivity
Avinash R

4

こんにちは私はあなたがまだこの問題を抱えているかどうかではありません。しかし、私はこれを解決するために私がしたことを投稿し、それが誰かを助けることを願っています。

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.

これで解決するはずです。

乾杯!


4
「クラスをPreferenceActivityがActionBarActivityを拡張するようにします」-しかし、どのように?
vbence 2015年

こちらのリンクをチェックしてください: code.hootsuite.com/…– AfrikAndroid 2015
1

1
おかげで、これは可能な限り近いと思います。本当の問題は、PreferenceActivityにloadHeadersFromResourceを介したナビゲーションが組み込まれていることです。フラグメントを使用して、ナビゲーションを自分で作成する必要があります。
vbence 2015年

0

受け入れられた質問と同様のことをしましたが、他のアクティビティでもレイアウトを使用している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);
}

0

私も同じ問題を抱えていました。アクティビティのテーマを、ActionBarが含まれているテーマに変更してみてください。SettingsActivityのアクティビティタグに次の行を追加すると、うまくいきました。

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


-1

私が理解した簡単な方法は、オーバーライドすることです。

@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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.