Solution 1 :
First, you need to add more constructors to SomeDialog
. The Context
constructor is not enough since the Preference
will be inflated from xml
. Having the following three constructors is usually sufficient:
public SomeDialog(Context context) {
super(context);
}
public SomeDialog(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SomeDialog(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
In addition to that, the SettingsFragment
in your SettingsActivity
needs to implement onDisplayPreferenceDialog(Preference preference)
to show a custom dialog for the custom Preference
.
public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
if (preference instanceof SomeDialog) {
MyDialogFragment dialogFragment = new MyDialogFragment();
Bundle b = new Bundle();
b.putString(MyDialogFragment.KEY, preference.getKey());
b.putInt(MyDialogFragment.KEY_LAYOUT_RES_ID, ((SomeDialog) preference).getDialogLayoutResource());
dialogFragment.setArguments(b);
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(getFragmentManager(), null);
} else super.onDisplayPreferenceDialog(preference);
}
}
And, last not least, you also have to provide the custom dialog itself. This is done via a class extending DialogFragment
.
My very simple DialogFragment
has a TextView
inside a FrameLayout
, just to show it works
MyDialogFragment code:
public class MyDialogFragment extends DialogFragment {
public static final String KEY = "key";
public static final String KEY_LAYOUT_RES_ID = "resid";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(requireArguments().getInt(KEY_LAYOUT_RES_ID), container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
TextView textView = view.findViewById(R.id.textView);
textView.setText(requireArguments().getString(KEY));
}
}
Problem :
-
Here is a random layout called some_layout.xml:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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""> <!-- Some views in here --> </androidx.constraintlayout.widget.ConstraintLayout>
-
Here is a class SomeDialog.java that extends DialogPreference:
import android.content.Context; import androidx.preference.DialogPreference; public class SomeDialog extends DialogPreference { public SomeDialog(Context context) { super(context); } @Override public int getDialogLayoutResource() { return R.layout.some_layout; } }
-
And here’s the preference screen:
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns_android="http://schemas.android.com/apk/res/android"> <android.example.perappbrightness.SomeDialog android_title="@string/rate_app" android_summary="@string/rate_summary" android_key="rate_app"/> </PreferenceScreen>
Relevant part of crash error. The line at which MainActivty
crashes is PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
:
java.lang.RuntimeException: Unable to start activity ComponentInfo{android.example.perappbrightness/android.example.perappbrightness.MainActivity}: android.view.InflateException: Binary XML file line #36: Error inflating class android.example.perappbrightness.SomeDialog
Caused by: android.view.InflateException: Binary XML file line #36: Error inflating class android.example.perappbrightness.SomeDialog
android.example.perappbrightness.MainActivity.onCreate(MainActivity.java:72)
SettingsActivity.java is an untouched. It’s from the template of Android Studio.
What am I doing wrong?
Comments
Comment posted by Bö macht Blau
Please add the rest of the error message as well as the code where you actually use the PreferenceScreen resource. Ideally as much code as I need to reproduce the issue.
Comment posted by User104163
@BömachtBlau Hi. My SettingsActivity is untouched, like Android Studio generates it by default. But I will post it anyway.
Comment posted by Bö macht Blau
Yes, thanks. My Android Studio complains that the …SomeDialog element is not allowed in the PreferenceScreen. When I start the app anyway, it crashes with the same message
Comment posted by Bö macht Blau
That’s what I’m trying to find out – or rather I’m trying to find out what’s missing in your setup (and I’ not doing preference screens every week 😉 )…. The problem seems to be that you only have the constructor with parameter Context for SomeDialog. If I add all the constructors except for SomeDialog(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes), the app does not crash anymore
Comment posted by Bö macht Blau
This seems to be the case for anything (Views) which may be inflated from xml. If you write a custom View class and you’re sure that you only will create it programmatically then the Context constructor will do.
Comment posted by brassmookie
since setTargetFragment is now deprecated, is there an alternative to this method?
Comment posted by “Share data between fragments”
@brassmookie – there are various alternatives. One option is to have a shared ViewModel for Fragment and DialogFragment, see for example