I understand this question have been asking many times here but after spending the last 1,5 hour reading and trying to sort out my issue, I can't.
Problem statement:
When calling setStyle
method in DialogFragment
i get the RuntimeException error stated in the title.
This is my original code, which does not throws this exception:
public class MapDialogFragment extends DialogFragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.maps_dialog, container, false);
return view;
}
}
Now, I have just added ImmersiveMode throughout my application. As some of you may know, the immersive mode is lost when showing Dialogs, so one must override these fragments and set appropriate flags so that the mode is kept. I have successfully accomplished this - it works. But, I have to comment out line: setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
, so I am losing my dialog's style and this is the problem.
Having a closer look at the setStyle
method in the DialogFragment, I can't really see how requestFeature()
is being invoked:
public void setStyle(int style, int theme) {
mStyle = style;
if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
mTheme = com.android.internal.R.style.Theme_DeviceDefault_Dialog_NoFrame;
}
if (theme != 0) {
mTheme = theme;
}
}
Finally, this is my DialogFragment class where the exception is happening. Note the getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
and also the clearFlag, which were necessary to have the ImmersiveMode working (hopefully this will be useful for someone):
public class MapDialogFragmentv2 extends DialogFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
//I have also tried the code here, before the super.OnCreate but to no avail
//setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
super.onCreate(savedInstanceState);
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
MyDialog mDialog = new MyDialog(getActivity());
mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
view = getActivity().getLayoutInflater().inflate(R.layout.maps_dialog, null);
//Line below throws exception. Needs to be commented out
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
mDialog.setContentView(view);
return mDialog;
}
public class MyDialog extends Dialog {
public MyDialog(Context context) {
super(context);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
getWindow().getDecorView().setSystemUiVisibility(MainActivity.getImmersiveModeFlags());
}
@Override
public void show() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
super.show();
}
}
}
I have also tried using a mix of onCreate
, onCreateView
and onCreateDialog
but it didn't work. I also read here at Stackoverflow someone commenting that it was not a good idea to have onCreateView and onCreateDialog at the same time.
And also tried adding the style to my xml layout itself, but also didn't work:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/lib/com.google.android.gms.plus"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/transparent"
style="@android:style/Theme.Holo.Dialog" >
Thank you
The problem is that you mash together too many different things and that you don't respect the lifecycle of each class.
Firstly you need to stop nesting classes like you do. This is partly the source of the error. If you really want/have to nest a Fragment
or Dialog
then it is important that you declare the nested Fragments
, Dialogs
as static. If you don't declare them as static you can cause memory leaks and problems like yours. But the best thing you can do is to only limit yourself to one class per file unless you have an actual reason to nest it. This also has the added benefit of improving readability and maintainability of your code.
But the main cause of your error is that you completely ignore the lifecycle of the Dialog
. Pretty much all of the following code should be in the proper lifecycle methods of the Dialog
:
mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
view = getActivity().getLayoutInflater().inflate(R.layout.maps_dialog, null);
//Line below throws exception. Needs to be commented out
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
mDialog.setContentView(view);
So to fix your error you need to do 3 things:
Either declare MapDialogFragmentv2
and MyDialog
static like this:
public class MainActivity extends Activity {
...
public static class MapDialogFragmentv2 extends Fragment {
...
public static class MyDialog extends Dialog {
...
}
}
}
Or even better move them to their own files all together.
Move the code from onCreateDialog()
in MapDialogFragmentv2
in the correct lifecycle methods in MyDialog
. It should then look something like this:
public static class MyDialog extends Dialog {
private final LayoutInflater mInflater;
public MyDialog(Context context) {
super(context);
mInflater = LayoutInflater.from(context);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
getWindow().getDecorView().setSystemUiVisibility(MainActivity.getImmersiveModeFlags());
View view = mInflater.inflate(R.layout.maps_dialog, null);
setContentView(view);
}
@Override
public void show() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
super.show();
}
}
Add setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
to the onCreate()
method of your MapDialogFragmentv2
after the super.onCreate()
call.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
}
Your MapDialogFragmentv2
should then just look like this:
public static class MapDialogFragmentv2 extends DialogFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
return new MyDialog(getActivity());
}
}
I tested everything on my Nexus 5 running Android 5.0.1 (Lollipop) and it works.
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