環境設定画面のサポートライブラリにある新しいマテリアルデザインツールバーの使用で問題が発生しました。
私は次のように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>
文字列は別の場所で定義されます。
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);
}
}
これが誰かの助けになることを願っています。
GitHubリポジトリを見つけてください:ここ
パーティーに少し遅れましたが、これは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
でエレベーションを使用する場合は、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
ファイルの依存関係として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'
報告された重複する問題を調査しましたが、問題を再現できません。
上記のように使用中の完全なコードは以下を生成します
何か不足している場合は、 this repo でお知らせください。調査します。
完全に新しい更新
いくつかの実験で、ネストされた設定画面用の動作する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
を使用します。各ページには、共通のPreferenceScreen
が内部にある個別のXMLがあります(xml/settings_page1.xml
et al。)。フラグメントは、ツールバーを含むアクティビティと同じレイアウトを使用します。
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
を新しいものに変え、通常どおりツールバーを追加できることを意味します。その時点から、既存のドキュメントから逸脱することなく、設定画面とヘッダーに関する古いソリューションに固執することができます。重要な点が1つだけあります。アクティビティでonCreate()
を使用しないでください。エラーが発生する可能性があります。ツールバーの追加など、すべての操作にonBuildHeaders()
を使用します。
唯一の本当の違いは、ネストされた画面で機能することです。それは、フラグメントで同じアプローチを使用できることです。 onCreateView()
を同じ方法で使用して、システムのレイアウトではなく独自のレイアウトを拡張し、アクティビティと同じ方法でツールバーを追加できます。
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
}
layout/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>
Android Support Library 22.1.0および新しいAppCompatDelegateのリリースでは、後方互換性のあるマテリアルサポートを備えたPreferenceActivityの実装のニースサンプルを見つけることができます。
Updateネストされた画面でも動作します。
私もv7サポートツールバー(API 25)をAppCompatPreferenceActivity(自動作成)に追加するソリューションを探していましたSettingsActivityを追加するときにAndroidStudioによって)。いくつかのソリューションを読み、それぞれを試してみた後、生成されたPreferenceFragmentの例を取得してツールバーで表示するのに苦労しました。
修正された解決策は、「Gabor」からのものでした。
私が直面した警告の1つは、「onBuildHeaders」が1回だけ起動することでした。デバイス(電話など)を横向きにすると、ビューが再作成され、PreferenceActivityにはツールバーが再び表示されなくなりますが、PreferenceFragmentsはそれらを保持します。
「onPostCreate」を使用して「setContentView」を呼び出してみましたが、これは向きが変更されたときにツールバーを再作成するために機能し、PreferenceFragmentsは空白になりました。
私が考え出したものは、ほぼすべてのヒントと答えで、このテーマについて読むことができました。他の人にもそれが役立つことを願っています。
Javaから始めます
Firstin(generated)AppCompatPreferenceActivity.Java私は 'setSupportActionBar'を次のように変更しました:
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
ActionBar bar = getDelegate().getSupportActionBar();
bar.setHomeButtonEnabled(true);
bar.setDisplayHomeAsUpEnabled(true);
}
Second、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);
}
}
これはガボールの答えの一部でした。
最後、一貫性を得るために、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);
}
}
}
簡潔にするため、一部のコードはアクティビティから除外されています。ここでの主要なコンポーネントは、「onAttachedFragment」、「onPostCreate」、および「GeneralPreferenceFragment」がカスタム「PreferenceFragmentの代わりにAppCompatPreferenceFragment '。
コードの概要:フラグメントが存在する場合、フラグメントは新しいレイアウトを挿入し、変更された「setSupportActionBar」関数を呼び出します。フラグメントが存在しない場合、SettingsActivityは「onPostCreate」に新しいレイアウトを挿入します
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>
最終結果:
上記の回答は複雑に見えますが、PreferenceActivity
を拡張しながら、サポートAPI 7以上でツールバーを使用するクイックフィックスソリューションが必要な場合は、以下のこのプロジェクトから助けを得ました。
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;
}
}
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
の利点を維持しながら。
ここでは、組み込みのレイアウトを壊さずに、シンプルできれいにしましょう
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();
}
});
}
この作業中にこの簡単な解決策を見つけました。最初に、設定アクティビティのレイアウトを作成する必要があります。
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(Jelly bean以上)を超えるすべてのAPIでほぼ機能するはずです。
ジェームズクロスのマークされたソリューションを継続したいと思います。その後、SettingsActivityも閉じない方法で、アクティブなネストされた画面(PreferenceFragment)のみを閉じるという問題があるためです。
実際、それはすべてのネストされた画面で動作します(したがって、私は成功せずに試したGáborの解決策を理解していません、特定のポイントまで動作しますが、複数のツールバーの混乱です)ユーザーがサブ設定画面をクリックすると、フラグメントのみが変更されます(<FrameLayout Android:id="@+id/content_frame" .../>
を参照)常にアクティブで表示されたままのツールバーではなく、butそれに応じて各フラグメントを閉じるカスタム動作を実装する必要があります。
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();
}
}
選択したネストされた画面のtitleについては、ツールバーの参照を取得し、toolbar.setTitle(R.string.pref_title_general);
で適切なタイトルを設定する必要があります(たとえば)。
すべてのPreferenceFragmentにgetSupportActionBar()
を実装するには必要なしがあります。これは、ツールバーではなく、コミットのたびにフラグメントのビューのみが変更されるためです。
不要があり、各preference.xmlに追加する偽のToolbarPreferenceクラスを作成します(Gáborの答えを参照)。
AOSPコードに基づいて作成したライブラリは次のとおりです。AOSPコードは、設定とダイアログの両方に色合いを追加し、アクションバーを追加し、API 7のすべてのバージョンをサポートします。
https://github.com/AndroidDeveloperLB/MaterialPreferenceLibrary
まあ、これは今日(2015年11月18日)私にとってまだ問題です。このスレッドからすべてのソリューションを試しましたが、解決できない主なものが2つありました。
それで、私はより複雑なソリューションでライブラリを作成することになりました。基本的に、Lollipop以前のデバイスを使用している場合は、内部でスタイルを設定に適用する必要があり、カスタムフラグメントを使用してネストされた画面も処理しました(PreferenceScreenkey)).
ライブラリは次のとおりです。 https://github.com/ferrannp/material-preferences
そして、ソースコードに興味がある場合(ここに投稿するには長すぎます)、これが基本的にそのコアです: https://github.com/ferrannp/material-preferences/blob/master/library/ src/main/Java/com/fnp/materialpreferences/PreferenceFragment.Java