I had gone through How to add toolbars to AppCompatPreferenceActivity?
I'm using appcompat-v7:23.0.1
and support-v4:23.0.1
Before using AppCompayPreferenceActivity
, my PreferenceActivity
looks the following without toolbar.
public class JStockPreferenceActivity extends PreferenceActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// Display the fragment as the main content.
JStockPreferenceFragment jStockPreferenceFragment = JStockPreferenceFragment.newInstance();
jStockPreferenceFragment.setArguments(this.getIntent().getExtras());
this.getFragmentManager().beginTransaction().replace(android.R.id.content, jStockPreferenceFragment).commit();
}
}
After using AppCompayPreferenceActivity
, with some Toolbar
initialization code, the outcome looks as the following
The outcome isn't as expected :-
Toolbar
overlaps with PreferenceFragment
Toolbar
, the event will be consumed by PreferenceFragment
. This means, when you touch on toolbar, "Table header" preference will be touched instead.public class JStockPreferenceActivity extends AppCompatPreferenceActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// Display the fragment as the main content.
JStockPreferenceFragment jStockPreferenceFragment = JStockPreferenceFragment.newInstance();
jStockPreferenceFragment.setArguments(this.getIntent().getExtras());
this.getFragmentManager().beginTransaction().replace(android.R.id.content, jStockPreferenceFragment).commit();
}
initToolbar();
}
private void initToolbar() {
Toolbar toolbar;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
ViewGroup root = (ViewGroup) findViewById(android.R.id.list).getParent().getParent().getParent();
toolbar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.toolbar, root, false);
root.addView(toolbar, 0);
} else {
toolbar = null;
}
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
My toolbar is
<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"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" >
<!-- android:elevation="4dp" is used due to http://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-elevation-android- -->
</android.support.v7.widget.Toolbar>
I was wondering, what I had did wrong, which causes Toolbar
overlapped with PreferenceFragment
After some research and getting advice from Ian Lake, I manage to make it work by
AppCompatPreferenceActivity
, to AppCompatActivity
+PreferenceFragmentCompat
The following solution is workable for API 10 and above.
public class JStockPreferenceActivity extends AppCompatActivity {
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jstock_preference_activity);
initToolbar();
if (savedInstanceState == null) {
// Display the fragment as the main content.
JStockPreferenceFragment jStockPreferenceFragment = JStockPreferenceFragment.newInstance();
jStockPreferenceFragment.setArguments(this.getIntent().getExtras());
this.getSupportFragmentManager().beginTransaction().replace(R.id.content, jStockPreferenceFragment).commit();
}
}
public class JStockPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
public static JStockPreferenceFragment newInstance() {
return new JStockPreferenceFragment();
}
However, by doing so, there is a shortcoming. Your previous custom DialogPreference
no longer work. To solve this, you need to
DialogPreference
with PreferenceDialogFragmentCompat
.DialogPreference
in XML with ListPreference
. (I'm not exactly sure whether ListPreference
as replacement is a right way. It works anyway)PreferenceDialogFragmentCompat
, in PreferenceFragmentCompat
's onPreferenceDisplayDialog
.public class JStockPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
public static JStockPreferenceFragment newInstance() {
return new JStockPreferenceFragment();
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Showing custom dialog preference.
private void showPreferenceDialogFragmentCompat(PreferenceDialogFragmentCompat preferenceDialogFragmentCompat) {
preferenceDialogFragmentCompat.setTargetFragment(this, 0);
preferenceDialogFragmentCompat.show(this.getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG");
}
private void showCurrencySymbolPreferenceDialogFragmentCompat(Preference preference) {
CurrencySymbolPreferenceDialogFragmentCompat currencySymbolPreferenceDialogFragmentCompat = CurrencySymbolPreferenceDialogFragmentCompat.newInstance(preference.getKey());
showPreferenceDialogFragmentCompat(currencySymbolPreferenceDialogFragmentCompat);
}
// Showing custom dialog preference.
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// Callback when we are using custom dialog preference.
@Override
public Fragment getCallbackFragment() {
return this;
}
@Override
public boolean onPreferenceDisplayDialog(PreferenceFragmentCompat preferenceFragmentCompat, Preference preference) {
final String key = preference.getKey();
if (_CURRENCY_SYMBOL_OPTIONS.equals(key)) {
showCurrencySymbolPreferenceDialogFragmentCompat(preference);
return true;
}
return false;
}
// Callback when we are using custom dialog preference.
////////////////////////////////////////////////////////////////////////////////////////////////
public class CurrencySymbolPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat {
public CurrencySymbolPreferenceDialogFragmentCompat() {
}
public static CurrencySymbolPreferenceDialogFragmentCompat newInstance(String key) {
CurrencySymbolPreferenceDialogFragmentCompat fragment = new CurrencySymbolPreferenceDialogFragmentCompat();
Bundle b = new Bundle(1);
b.putString("key", key);
fragment.setArguments(b);
return fragment;
}
@Override
public void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
...
this.getPreference().setSummary(getSummary());
...
}
}
}
<android.support.v7.preference.ListPreference
android:title="@string/preference_currency_symbol_title"
android:key="_CURRENCY_SYMBOL_OPTIONS" />
Please note that, you need to add the following item in your theme.
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
However, the theme-ing isn't perfect yet - PreferenceFragmentCompat requires preferenceTheme to be set
This is a known issues : https://code.google.com/p/android/issues/detail?id=183376
There is proposed workaround https://stackoverflow.com/a/32108439/72437 But, the workaround will only work for v14 and above, not v7 and above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With