I want to create a custom list dialog when I click on a ListPreference in Settings Activity.
ListPreference in root_preferences.xml:
<ListPreference
android:icon="@drawable/pref_language"
app:defaultValue="en"
app:entries="@array/language_entries"
app:entryValues="@array/language_values"
app:iconSpaceReserved="false"
app:key="@string/prefkey_language"
app:summary="%s"
app:title="@string/language_title" />
I want it to have rounded corners, and I also want custom listitem views (e.g. images instead of the default radiobuttons).
Actual result:
Expected result:
Can I do this in a way that I use ListPreference, but replace @array entries with an adapter?
Is there any other way to achieve this without needing to get rid of the PreferenceScreen?
Meanwhile, I have found a solution. It's probably not the cleanest one, but it works for me. If anyone knows a better solution, don't hesitate to let us know.
Create a class that extends DialogPreference. Create as many classes as many custom dialogs you want to have, e.g. LanguagePreference, UnitPreference, etc.
public class LanguagePreference extends DialogPreference implements Preference.OnPreferenceChangeListener {
public LanguagePreference(Context context, AttributeSet attrs) {
super(context, attrs);
setOnPreferenceChangeListener(this);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// do something
return true;
}
}
Now you can use these in root_preferences.xml.
<PreferenceCategory app:title="@string/category">
<com.company.yourapp.preferences.LanguagePreference
android:icon="@drawable/pref_language"
app:title="@string/language" />
<com.company.yourapp.preferences.UnitPreference
android:icon="@drawable/pref_unit"
app:title="@string/unit" />
</PreferenceCategory>
Create a class that extends DialogFragment (may be abstract). Remove default background and title in onViewCreated().
public abstract class RoundedPreferenceDialog extends DialogFragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
if (getDialog() != null && getDialog().getWindow() != null) {
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // remove default background so that dialog can be rounded
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); // remove default title
}
super.onViewCreated(view, savedInstanceState);
}
}
Extend classes from RoundedPreferenceDialog, e.g. LanguagePreferenceDialog, UnitPreferenceDialog.
public class LanguagePreferenceDialog extends RoundedPreferenceDialog {
public static LanguagePreferenceDialog newInstance() {
return new LanguagePreferenceDialog();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialogpreference_language, container, false);
// init UI, list adapter, listeners
return view;
}
}
Override onDisplayPreferenceDialog in SettingsFragment. Create a condition for each custom dialog you have.
@Override
public void onDisplayPreferenceDialog(Preference preference) {
if (preference instanceof LanguagePreference) { // rounded language dialog
LanguagePreferenceDialog.newInstance().show(getParentFragmentManager(), null);
} else if (preference instanceof UnitPreference) { // rounded unit dialog
UnitPreferenceDialog.newInstance().show(getParentFragmentManager(), null);
} else {
super.onDisplayPreferenceDialog(preference);
}
}
Now you can display a custom dialog instead of the default one. You just have to customize it the way you want. To make it rounded, set the background of the root layout to a custom rounded layout.
dialogpreference_language.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialogLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_dialog_rounded">
<!-- titleTextView, languageListView, cancelButton, etc. -->
</RelativeLayout>
bg_dialog_rounded.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="@dimen/dialog_radius" />
<solid android:color="@color/white" />
</shape>
Final result: