I created a DialogFragment which should be shown after onActivityResult is called.
But right after dialog.show() is called, the Dialog dismissed automatically for no reason.
I am using the BarcodeScanner lib to scan a QR-Code, in onActivityResult I just save the Data (I also tried to show the Dialog at this point, but it didn't worked.)
if ((requestCode == REQUEST_BARCODESCANNER) && (resultCode == RESULT_OK)) {
mBarcodeScanned = true;
mBarcodeScanResult = getBarcodeScannerResult(data.getExtras());
}
in onResume I am checking now for this variables:
if(mBarcodeScanResult == null && mBarcodeScanned){
mBarcodeScanned = false;
showDialog(MyDialogFragment.getInvalidQrCodeDialog(this));
} else if(mBarcodeScanResult != null && mBarcodeScanned){
showDialog(MyDialogFragment.getSomeDialog(this, v1, v2));
}
in showDialog() I just call show:
dialog.show(getSupportFragmentManager(), MyDialogFragment.class.getSimpleName());
Now it should show the Dialog, if a QR-Code was scanned.
For some reason right after dialog.show() I checked onDismiss() inside of the MyDialogFragment class, and it was called as well, but I really don't know why?
The MyDialogFragment is using the onCreateDialog methode, which creates AlertDialogs to return. The methode getSomeDialog() and getInvalidQrCodeDialog() are just instanciate the Fragment.
EDIT: the MyDialogClass
public class MyDialogFragment extends DialogFragment {
private static final String BUNDLE_DIALOG_TYPE = "bundle_dialog_type";
private DialogType mDialogType;
public enum DialogType{
QR_CODE_INVALID, SOME_DIALOG
}
public static Fragment getInvalidQrCodeDialog(final Context context) {
Bundle args = new Bundle();
args.putString(BUNDLE_DIALOG_TYPE, DialogType.QR_CODE_INVALID.name());
return MyDialogFragment.instantiate(context, MyDialogFragment.class.getName(), args);
}
public static Fragment getSomeDialog(final Context context) {
Bundle args = new Bundle();
args.putString(BUNDLE_DIALOG_TYPE, DialogType.SOME_DIALOG.name());
return MyDialogFragment.instantiate(context, MyDialogFragment.class.getName(), args);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleArguments();
}
private void handleArguments() {
final Bundle arguments = getArguments();
if(arguments != null) {
mDialogType = DialogType.valueOf(arguments.getString(BUNDLE_DIALOG_TYPE, DialogType.SOME_DIALOG.name()));
}
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
switch(mDialogType){
case QR_CODE_INVALID: return DialogHelper.showQRCodeInvalidDialog(getActivity());
case SOME_DIALOG: return DialogHelper.showSomeDialog(getActivity());
default: return null;
}
}
}
and the DialogHelper does something like this:
public static AlertDialog showQRCodeInvalidDialog(final Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.barcode_invalid);
builder.setTitle(R.string.barcode_invalid_title);
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
The problem seems to be the support-package DialogFragment.
I just changed it from support to the original DialogFragment and everything worked like expected.
Related
1) In my application, the user may receive a lot of notifications from FCM
2) If the user has an application open, he needs to display the custom DialogFragment
3) If the DialogFragment is already displayed, then the next time the notification arrives, it is necessary to prohibit the repeated display of this DialogFragment
4) My dialogue code:
public final class NotificationEventDialog extends DialogFragment implements DialogInterface.OnKeyListener, View.OnClickListener {
private Activity mCurrentActivity;
private NotificationEventDialogListener mNotificationEventDialogListener;
public interface NotificationEventDialogListener {
void showEvent();
}
public NotificationEventDialog() {
}
public static NotificationEventDialog newInstance() {
NotificationEventDialog notificationEventDialog = new NotificationEventDialog();
notificationEventDialog.setCancelable(false);
return notificationEventDialog;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mCurrentActivity = (Activity)context;
try {
mNotificationEventDialogListener = (NotificationEventDialogListener) mCurrentActivity;
} catch (ClassCastException e) {
throw new ClassCastException(mCurrentActivity.toString() + " must implemented NotificationEventDialogListener");
}
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(mCurrentActivity);
#SuppressLint("InflateParams") View view = inflater.inflate(R.layout.dialog_notification_event, null);
Button btnNotificationEventYes = view.findViewById(R.id.notification_event_dialog_yes);
btnNotificationEventYes.setOnClickListener(this);
Button btnNotificationEventNo = view.findViewById(R.id.notification_event_dialog_no);
btnNotificationEventNo.setOnClickListener(this);
AlertDialog.Builder builder = new AlertDialog.Builder(mCurrentActivity);
builder.setView(view);
return builder.create();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
if (getDialog() != null && getDialog().getWindow() != null) {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().setOnKeyListener(this);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onDetach() {
super.onDetach();
mCurrentActivity = null;
mNotificationEventDialogListener = null;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.notification_event_dialog_yes:
dismiss();
mNotificationEventDialogListener.showEvent();
break;
case R.id.notification_event_dialog_no:
dismiss();
break;
}
}
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
dismiss();
return true;
} else return false;
}
}
5) Each time I receive a notification from FCM, I create a dialog box:
DialogFragment notificationEventDialog = NotificationEventDialog.newInstance();
notificationEventDialog.show(getSupportFragmentManager(), "");
6) How to check if DialogFragment is already displayed? Every time I create a new object of this window and I cannot make it as Singleton, because This leads to a memory leak.
Found an answer in which a person suggests using Weak links to solve this problem:
Also you can store a weak link to the shown dialog in that singletone
class. Using such method, you can detect is your dialog currently
shown or not.
There was also such an answer:
I suggest to save link to the dialog in single instance class. In that
instance create method ensureShowDialog(Context context). That method
would check is current shown dialog or not. If yes, you can show the
dialog. In another casr you can pass new data you to the dialog.
But, honestly, I can’t quite understand how to use these tips in practice. Please can help with this realization or suggest another way? Thanks in advance.
You can use:
val ft: FragmentTransaction = fragmentManager!!.beginTransaction()
val prev: Fragment? = fragmentManager!!.findFragmentByTag("typeDialog")
if (prev == null) {
val fm = fragmentManager
val courseTypeListDialogFragment =
CourseTypeListDialogFragment()
courseTypeListDialogFragment.isCancelable = false
courseTypeListDialogFragment.setStyle(
DialogFragment.STYLE_NO_TITLE,
0
)
courseTypeListDialogFragment.setTargetFragment(this, 1)
if (fm != null) {
courseTypeListDialogFragment.show(ft, "typeDialog")
}
}
You can check if dialog fragment is showing by calling isAdded () inside DialogFragment or by
DialogFragment notificationEventDialog = NotificationEventDialog.newInstance();
notificationEventDialog.isAdded()
from activity
It will return true if fragment is added to an Activity, in case of dialog fragment - is shown.
You can store last shown dialog fragment date via putting System.currentTimeMillis() in SharedPreferences
I think you'v got the idea.
I am trying to create a listener of a button of a customdialog which extends DialogFragment class and I want to locate the listener of custom buttons out of customdialog fragment class .However when I try to call the view of CustomDialog Fragment then I am getting null exception. What I do is to create an new instance of the customdialog fragment in somewhere else and say
customdialog.getView().findViewById(R.id.custombutton);
but I am getting null.
public class CustomDialog extends DialogFragment {
public final int RES_NONE = -1;
private TextViewCustomFont dialogTitle, view2, dialogBodyBottom,
dialogBodyTop;
private EditTextCustomFont dialogEditText;
private ButtonCustomFont dialogLeftButton;
private ButtonCustomFont dialogRightButton;
private Typeface GothamBold, GothamMedium, GothamUltra;
private static int title1, bodyTop1, bodyBottom1, EditTextHint1,
leftButton1, rightButton1;
onSubmitListener mListener;
private Dialog dialog;
interface onSubmitListener {
void setOnSubmitListener(String arg);
}
public static CustomDialog newInstance(int title, int bodyTop,
int bodyBottom, int EditTextHint, int leftButton, int rightButton) {
title1 = title;
bodyTop1 = bodyTop;
bodyBottom1 = bodyBottom;
EditTextHint1 = EditTextHint;
leftButton1 = leftButton;
rightButton1 = rightButton;
CustomDialog frag = new CustomDialog();
return frag;
}
public ButtonCustomFont getDialogLeftButton() {
return dialogLeftButton;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialog = new Dialog(getActivity());
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//dialog.setContentView(R.layout.dialog_layout);
//dialog.show();
initLayout();
return dialog;
}
private void initLayout(){
dialog.setContentView(R.layout.dialog_layout);
setDialogView();
setCustomDialog();
}
public void setDialogView(){
//Create an java object of each dialog view item
dialogTitle = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_title);
dialogBodyTop = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_body_top);
dialogBodyBottom = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_body_bottom);
dialogEditText = (EditTextCustomFont) dialog.findViewById(R.id.custom_dialog_body_et);
dialogLeftButton = (ButtonCustomFont) dialog.findViewById(R.id.custom_dialog_body_btn_left);
dialogRightButton = (ButtonCustomFont) }
public class LoginSelectionFragment extends Fragment {
public static LoginSelectionFragment newInstance() {
LoginSelectionFragment fragment = new LoginSelectionFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_loginselection,
container, false);
}
I am trying to pull the dialogLeftButton of CustomDialog Fragment and assing a listener on it inside the LoginSelectionFragment.
Here is how it looks like after I added method 2. This a part of LoginSelectionFragment
private void TwoButtonTextEditTextDialog(){
String title = getResources().getString(R.string.invalid_info_header);
String body = getResources().getString(R.string.invalid_info_body);
String body2 = getResources().getString(R.string.hint_newemail);
String btn1 = getResources().getString(R.string.cancel_uppercase);
String btn2 = getResources().getString(R.string.ok_alert);
fragmentDialog = CustomDialog.newInstance(title, body, body2, RES_NONE, btn1, btn2);
fragmentDialog.setCustomDialogFragmentListener(mDialogClickListener);
fragmentDialog.show(getFragmentManager(), "");
}
private CustomDialog.CustomDialogFragmentListener mDialogClickListener = new CustomDialog.CustomDialogFragmentListener(){
#Override
public void onNegativeClick() {
// TODO Auto-generated method stub
fragmentDialog.dismiss();
}
#Override
public void onPositiveClick() {
// TODO Auto-generated method stub
fragmentDialog.dismiss();
}
};
#Override
public void onNegativeClick() {
// TODO Auto-generated method stub
}
#Override
public void onPositiveClick() {
// TODO Auto-generated method stub
}
You could create a method as setDialogButtonClickListener(CustomDialog.OnButtonClickListener clickListener); where CustomDialog.OnButtonClickListener is an inner static interface , that way you could listen to click events of the buttons from anywhere.
An example of this could look as below,
public class CustomDialog extends DialogFragment {
.....
public static CustomDialog newInstance(int title, int bodyTop,
int bodyBottom, int EditTextHint, int leftButton, int rightButton) {
CustomDialog frag = new CustomDialog();
Bundle args = new Bundle();
args.putInt("title", title);
......
frag.setArguments(args);
return frag;
}
...
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(title)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
....
.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
if (listener != null) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
listener.onRightButtonClick();
default:
listener.onLeftButtonClick();
}
}
}
...
private CustomDialog.OnButtonClickListener mClickListener;
....
public void setDialogButtonClickListener(CustomDialog.OnButtonClickListener clickListener){
mClickListener = clickListener;
}
...
public static interface OnButtonClickListener {
public void onLeftButtonClick();
public void onRightButtonClick();
}
}
If you notice from the above sample I posted , I have besides solving your problem of setting the click listener on buttons also have introduced you with the Factory Design Pattern on Android , You can see that instead of creating static fields for the button title and Dialog title I've set them in the Bundle Argument and then Retrieve them in the Dialogs onCreate() method.
For more Best Practices of Fragment You can take a look here
Edit
Ok , for your help I am providing you a Glimpse of what your LoginSelectionFragment should look like.
public class LoginSelectionFragment extends Fragment implements CustomDialog.OnButtonClickListener {
......// Method 1
public void showDialog(String title , String message .....) {
CustomDialog dialog = CustomDialog.getInstance(title , message...);
dialog.setDialogButtonClickListener(this);
dialog.show(getSupportFragmentManager(), null);
}
public void onLeftButtonClick(){
...// do something on left button click of dialog
}
public void onRightButtonClick(){
// do something on right button click of dialog
..
}
// Method 2
public void showDialog2(String title , String message .....) {
CustomDialog dialog = CustomDialog.getInstance(title , message...);
dialog.setDialogButtonClickListener(mDialogClickListener);
dialog.show(getSupportFragmentManager(), null);
}
private final CustomDialog.OnButtonClickListener mDialogClickListener = new CustomDialog.OnButtonClickListener() {
public void onLeftButtonClick(){
...// do something on left button click of dialog
}
public void onRightButtonClick(){
// do something on right button click of dialog
..
}
}
}
Now If you look at Method 1 , we have given parameters to showDialog() method so that you could reuse it for showing multiple times with different arguments ie., you could use this approach when you want to show the same dialog with different title , message etc
and in Method 2 we have provided an anonymous inner class for handling click events you could as many anonymous inner classes as you have different varieties of dialog ie dialog with different UI and different Event listeners in the same activity/fragment.
Enjoy!
Try to use this, (did not test this)
public class MyDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.input_warning)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
}
and in your Activity fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.workout_a_fragment, container, false);
Button button = (Button)view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity().getFragmentManager();
MyDialogFragment dialog = new MyDialogFragment();
dialog.show(fm, DIALOG_WARNING);
}
});}
I'm writing an app where the user describes a problem and then receives advice. The user presses a button which shows a dialog with an EditText. Once the user presses OK, I want to get their input, but I'm having trouble with the extras. I've read similar questions, but I can't seem to find the problem. On a summary screen where I display the information, no text ever appears. Any help is appreciated!
I think the problem is when I call getText() on the EditText. Using log.d the mText is just an empty String.
Here is my code:
The fragment AdviceFragment from which the dialog is called:
private static final String DIALOG_TEXT = "text";
private static final int REQUEST_TEXT = 0;
private Advice mAdvice;
private boolean hasText;
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
...
mTextButton = (Button) v.findViewById(R.id.textButton);
mTextButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
FragmentManager fm = getActivity().getSupportFragmentManager();
InputTextFragment dialog = new InputTextFragment();
dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
dialog.show(fm, DIALOG_TEXT);
}
});
}
...
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode != Activity.RESULT_OK)
{
return;
}
if (resultCode == REQUEST_TEXT)
{
String text = data.getStringExtra(InputTextFragment.EXTRA_TEXT);
if (text.length() > 0)
{
mAdvice.setText(text);
hasText = true;
}
else
{
mAdvice.setText(null);
hasText = false;
}
}
InputTextFragment dialog:
public class InputTextFragment extends DialogFragment
{
public static final String EXTRA_TEXT = "text";
private String mText;
private void sendResult(int resultCode)
{
if (getTargetFragment() == null)
{
return;
}
Intent i = new Intent();
i.putExtra(EXTRA_TEXT, mText.toString());
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, i);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_input_text, null);
final EditText editText = new EditText(getActivity());
return new AlertDialog.Builder(getActivity())
.setView(v)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int whichButton)
{
String input = editText.getText().toString();
if (input.length() > 0)
{
mText = input;
}
else
{
return;
}
sendResult(Activity.RESULT_OK);
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
{
...
})
.create();
}
}
final EditText editText = new EditText(getActivity());
You problem is here, your EditText is not added to your Dialog's View Tree. I think you should do like this:
final EditText editText = (EditText)v.findViewById(your_edittext_id);
Thanks, I think this has fixed part of the problem. Using log.d in the
onClick() method of setPositiveButton()shows that it is successfully
assigning the value. However, I'm still not getting anything when I
call onActivityResult(). Do you have any idea what's going wrong?
Look here, another typo problem:
if (resultCode == REQUEST_TEXT)
{
It should be requestCode.
I think this should fix your problem, but you'd better follow bean_droid's suggest and use an interface instead of calling the onActivityResult() method. It's because that method may be called by other part of your code, which you don't want.
Here try this:
Public class AdviceFragment extends Fragment implements OkClickListener{
#Override
Public void onClick(String data){
//DO YOUR CODE HERE
}
}
InputTextFragment
Public Class InputTextFragment extends DialogFragment{
public interface OkClickListener{
public void onClick(String data);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_input_text, null);
final EditText editText = new EditText(getActivity());
return new AlertDialog.Builder(getActivity())
.setView(v)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int whichButton)
{
String input = editText.getText().toString();
if (input.length() > 0)
{
mText = input;
}
else
{
return;
}
((OkClicklistener)getTargetFragment()).onClick(data);
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
{
...
})
.create();
}
}
}
replace sendResult(Activity.RESULT_OK); to getActivity().setResult(resultCode);
This fairly simple dialog dismisses itself after screen rotation despite I setRetainInstance to true. Any ideas whats wrong?
public class StreetDialog extends DialogFragment {
public static StreetDialog newInstance(String[] values) {
StreetDialog f = new StreetDialog();
Bundle args = new Bundle();
args.putStringArray("values", values);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String[] values = getArguments().getStringArray("values");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//build my dialog
return builder.create();
}
#Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
}
If I recall correctly is the normal behaviour. I usually provide a tag to the show method, and when the Activity's onCreate is called again, I look for the tag. If the fragment != null I remove it, before creating and showing the new one. In code, what I usually do is:
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
if (fragment != null) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
new CustomDialogFragment().show(getSupportFragmentManager(), FRAGMENT_TAG );
This is an issue that I believe the best way to solve and using an approach below:
Create a static method to initialize a Dialog, remembering that this is a good practice since we always have the default constructor and the Bundle stores the state of the Fragment.
In onCreateDialog method, initialize the AlertDialog with the data passed in the "constructor method".
In your Activity you can implement an interface (because we can not keep the reference of it, since it may have been destroyed when rotating the device). To open the dialog,
checking that it has been added to FragmentManager otherwise exhibit.
see more here (Link in portuguese - br): http://nglauber.blogspot.com.br/2013_10_01_archive.html
public class SimpleDialog extends DialogFragment implements OnClickListener {
private static final String EXTRA_ID = "id";
private static final String EXTRA_MESSAGE = "message";
private static final String EXTRA_TITLE = "title";
private static final String EXTRA_BUTTONS = "buttons";
private static final String DIALOG_TAG = "SimpleDialog";
private int dialogId;
public static SimpleDialog newDialog(int id,
String title, String message, int[] buttonTexts){
// Using the Bundle to save state
Bundle bundle = new Bundle();
bundle.putInt(EXTRA_ID, id);
bundle.putString(EXTRA_TITLE, title);
bundle.putString(EXTRA_MESSAGE, message);
bundle.putIntArray(EXTRA_BUTTONS, buttonTexts);
SimpleDialog dialog = new SimpleDialog();
dialog.setArguments(bundle);
return dialog;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments() .getString(EXTRA_TITLE);
String message = getArguments().getString(EXTRA_MESSAGE);
int[] buttons = getArguments().getIntArray(EXTRA_BUTTONS);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setMessage(message);
switch (buttons.length) {
case 3:
alertDialogBuilder.setNeutralButton(buttons[2], this);
case 2:
alertDialogBuilder.setNegativeButton(buttons[1], this);
case 1:
alertDialogBuilder.setPositiveButton(buttons[0], this);
}
return alertDialogBuilder.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
// Your Activity must to implements this interface
((FragmentDialogInterface)getActivity()).onClick(dialogId, which);
}
public void openDialog( FragmentManager supportFragmentManager) {
if (supportFragmentManager.findFragmentByTag( DIALOG_TAG) == null){
show(supportFragmentManager, DIALOG_TAG);
}
}
// Interface that was invoked by clicking the button
public interface FragmentDialogInterface {
void onClick(int id, int which);
}
To open the dialog in your activity
public void openSimpleDialog(View v) {
SimpleDialog dialog = SimpleDialog.newDialog(
0, // Id from dialog
"Alert", // title
"Message", // menssage
new int[]{ // texts from buttons
android.R.string.ok,
android.R.string.cancel });
dialog.openDialog(getSupportFragmentManager());
}
#Override
public void onClick(int id, int which) {
Toast.makeText(MainActivity.this,
"Button clicked"+ which, Toast.LENGTH_SHORT)
.show();
}
I have a DialogFragment that displays a list of options to the user, one of these options is "Delete" option, when the user presses the delete option I want to show another DialogFragment as a confirmation, unfortunately, the confirmation dialog doesn't show.
here is my code
First Fragment code
public class ContactDialogOption extends SherlockDialogFragment {
public static final String TAG = ContactDialogOption.class.getSimpleName();
public ContactDialogOption() {
super();
// TODO Auto-generated constructor stub
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle(R.string.options);
builder.setItems(new String[] {
getString(R.string.call), getString(R.string.send_message),
getString(R.string.copy), getString(R.string.edit),
getString(R.string.delete)
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(which == 4) //delete
{
FragmentManager mgr = getActivity().getSupportFragmentManager();
FragmentTransaction ft = mgr.beginTransaction();
Fragment old = mgr.findFragmentByTag("SecondFragment");
if (old != null) {
ft.remove(old);
}
ft.addToBackStack(null);
fragment.show(ft, fragmentTag);
}
}
});
return builder.create();
}
}
I got the exact same problem, this situation does not happen when you try to open a DialogFragment from a Fragment.
The only solution I found was to modify the following call:
fragment.show(ft, fragmentTag);
To:
fragment.show(getFragmentManager(), fragmentTag);
The problem with this solution is that we cannot work on the FragmentTransition.
I don't understand why the behavior is different than with the fragments.
I came across the same problem of not being able to show another DialogFragment from within the positive and negative click listeners of the first DialogFragment. My solution was to immediately pop the first fragment, which allows the second DialogFragment to attach and display successfully.
// Call this before adding the second dialog fragment
activity.getSupportFragmentManager().popBackStackImmediate();
Please check this following code. Hope this will help many of you!
public class SubcategoryFragment extends DialogFragment {
public SubcategoryFragment() {
}
public static SubcategoryFragment newInstance(Integer code, String name) {
SubcategoryFragment fragment = new SubcategoryFragment();
mCode = code;
mTitle = name;
return fragment;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
liststring = new ArrayList<>();
getAdapter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_subcategory, container, false);
gridView = (GridView) view.findViewById(R.id.sub_grid);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
closeDialog = (ImageView) getDialog().findViewById(R.id.closeDialog);
title = (TextView) getDialog().findViewById(R.id.dialogTitle);
gridView = (GridView) getDialog().findViewById(R.id.sub_grid);
title.setText(String.format("Choose %s", mTitle));
closeDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getDialog().dismiss();
}
});
}
#Override
public Dialog onCreateDialog(#NonNull Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// request a window without the title
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
// closeDialog = (ImageView) dialog.findViewById(R.id.closeDialog);
return dialog;
}
public void getAdapter() {
gridAdapter = new HomeSubGridViewAdapter(getContext(), R.layout.gridview_custom_layout, liststring);
gridView.setAdapter(gridAdapter);
}
}
This is the method for calling dialog from fragment
fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
SubcategoryFragment postalFragment = SubcategoryFragment.newInstance(Integer.valueOf(item.getId()), item.getName());
postalFragment.show(fragmentManager, "SubcategoryFragment");
Feel Free to ask if you feel any problem is that
You can call a DialogFragment from Another DialogFragment.
NewDialogFragment newDialogFragment= new NewDialogFragment();
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
newDialogFragment.show(transaction, "New_Dialog_Fragment");
Very recently, I had this problem and none of the options above worked for me. I tried using the method below:
DialogFragment fragment = new MyFragment(); //where MyFragment is my fragment I want to show
fragment.setCancelable(true);
fragment.show(getSupportFragmentManager(), "timePicker");
This will ONLY work if you're using this in an activity (i.e to call a dialog fragment from an activity class).
I however fixed this by downcasting my activity instance to an AppCompat activity and using it to call getSupportFragment() as shown below:
DialogFragment timeFragment = new TimePicker();
timeFragment.setCancelable(true);
AppCompatActivity activity = (AppCompatActivity) getActivity();
timeFragment.show(activity.getSupportFragmentManager(), "timePicker");
I hope this helps.. Merry coding!!
This is the code that works for me:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (getArguments() == null) {
throw new InvalidParameterException("The key types dialog needs the protocol id to be in the arguments");
}
if (mCallback == null) {
throw new InvalidParameterException("The key types dialog needs an callback to be set");
}
mProtocolId = getArguments().getInt(ApplicationConstants.FragmentsConstants.PROTOCOL_ID);
final List<KeyTypeEntity> allKeyTypes = BusinessFacade.getInstance(getActivity()).KeyTypeLogic.getAllKeyTypes();
ArrayAdapter<KeyTypeEntity> keyTypeAdapter = new ArrayAdapter<KeyTypeEntity>(getActivity(), android.R.layout.simple_list_item_1, allKeyTypes);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("").setAdapter(keyTypeAdapter, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final KeyTypeEntity keyTypeEntity = allKeyTypes.get(which);
AlertDialog.Builder number = new AlertDialog.Builder(getActivity());
List<String> keyNumbers = new ArrayList<String>();
for (int i = 0; i < 50; i++) {
keyNumbers.add("" + (i + 1));
}
ArrayAdapter<String> kAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, keyNumbers);
number.setTitle("").setAdapter(kAdapter, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
addNewKey(keyTypeEntity, which + 1);
}
});
number.show();
}
}).setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
mCallback.onDialogClosed();
}
});
mDialog = builder.create();
return mDialog;
}
In the first click handler I just create a new dialog and show it. This will close the first dialog, open the second one, and when the user clicks on an item in the list, the second click handler is called.
Hope this helps, and I am not too late :)
You can pass FragmentManage to newInstance() method of First DialogFragment then you can use it to show new dialogfragment
this is my code.
private static FragmentManager fragmentManager;
public static PlayListDialog newInstance(Context context, FragmentManager fragmentManager1) {
playListDialog = new PlayListDialog();
mContext = context;
fragmentManager = fragmentManager1;
return playListDialog;
}
#Override
public void createNewPlaylist() {
NewPlayListDialog newPlayListDialog = NewPlayListDialog.newInstance(mContext);
newPlayListDialog.showDialog(fragmentManager.beginTransaction(),fragmentManager.findFragmentByTag("newdialog"));
}
Use this:
getActivity().getSupportFragmentManager
instead of
getChildFragmentManager().
Hope this helps.
If you want the kotlin version use this:
val newDialogFragment = NewDialogFragment()
val transaction: FragmentTransaction =
requireActivity().supportFragmentManager.beginTransaction()
newDialogFragment.show(transaction, "New_Dialog_Fragment")