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();
}
Related
I am trying to send some data from a DialogFragment to a TextView from a Fragment.
After inserting the data in the available input and pressing SAVE, the app crashes.
I assume there is something wrong with the IncomeDialogListener.
I would appreciate some hints where I did wrong.
This is the Dialog Class
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_incomedialog, null);
builder.setView(view)
.setTitle("Add Income")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
incomeDialogListener.addDetails(Amount, Note, Date);
}
});
enter_income_amount = view.findViewById(R.id.enter_income_amount);
enter_income_note = view.findViewById(R.id.enter_income_note);
enter_income_date = view.findViewById(R.id.enter_income_date);
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
incomeDialogListener = (IncomeDialogListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "Must Implement IncomeDialogListener");
}
}
public interface IncomeDialogListener {
void addDetails(String Amount, String Note, String Date);
}
This is the Fragment to which I want to send the data
public class IncomeFragment extends Fragment implements
IncomeDialog.IncomeDialogListener {
DatabaseHelper myDB;
Button btn_add_income;
TextView display_income;
public IncomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_placeholder2 , container, false);
display_income = (TextView) v.findViewById(R.id.display_income);
btn_add_income = (Button) v.findViewById(R.id.btn_add_income);
myDB = new DatabaseHelper(getActivity());
btn_add_income.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openIncomeDialog();
}
});
return v;
}
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.show(fragmentTransaction, "income dialog" );
}
#Override
public void addDetails(String Amount, String Note, String Date) {
display_income.setText(Amount);
}
}
Here is my solution for you:
IncomeFragment.java
public static final int INCOME_DIALOG_FRAGMENT = 1; // Add this line
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.setTargetFragment(IncomeFragment.this, INCOME_DIALOG_FRAGMENT); // Add this line
incomeDialog.show(fragmentTransaction, "income dialog");
}
IncomeDialog.java
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
IncomeDialogListener listener = (IncomeDialogListener) getTargetFragment();
listener.addDetails(Amount, Note, Date);
}
Update: There is no magic behind, when you open dialog from fragment, you passed itself to dialog by calling setTargetFragment. Then in the dialog you can refer to the fragment that opened it by calling getTargetFragment. Actually there are 2 solutions you can use.
IncomeFragment incomeFragment = (IncomeFragment) getTargetFragment();
incomeFragment.addDetails(Amount, Note, Date);
or
IncomeDialogListener listerner = (IncomeDialogListener) getTargetFragment();
listerner.addDetails(Amount, Note, Date);
I prefer to use the second one because the dialog don't need to know about specific fragment that opened it. This makes the dialog is usable. Imagine a situation, three days later, you would like to open the dialog from another fragment, in that case you don't need to modify the dialog again, just let the another fragment implements IncomeDialogListener. If you use the first one, you must go to the dialog and modify it to make sure it works for the another fragment.
How can I create a custom popup class that accepts a simple string message? Im new to Android and help with code will be appreciated.
When a button is pushed in the main layout, the popup must pop up on the screen.
Custom popup class
public class CustomPopup extends PopupWindow {
private String message;
private Double anchorX;
private Double anchorY;
PopupWindow popup;
public CustomPopup(String message) {
super();
this.message = message;
}
public void showPopup(Activity context) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
}
Main Class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText messageTxt = (EditText) findViewById(R.id.messageTxt);
Button generateBtn = (Button) findViewById(R.id.generateBtn);
String message = messageTxt.getText().toString();
final CustomPopup popup = new CustomPopup(message);
generateBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
popup.showPopup();
}
});
}
}
You can change the following code any way you need. This is just an example of how you make and implement a custom DialogFragment.
He is the code I use. I find it quite flexible because you can create several similar dialogs for slightly different tasks. You will need to create a layout file - this gives you a great deal of flexibility on function and style.
My layout file is fragment_ok_cancel_dialog.
To satisfy your requirements just create your own layout file with all the elements in it you need (like your image).
In the Activity that calls the dialog you will need to implement the Listener.
implements OkCancelDialogFragment.OkCancelDialogListener
Another advantage is with my code you can change the title and the message to fit the needs of any Activity.
private void callMyDialog(){
//Customize the title and message as needed
String title = "This is my dialog title";
String mess = "This is my dialog message";
OkCancelDialogFragment dialog = OkCancelDialogFragment.newInstance(title, mess);
dialog.show(getFragmentManager(), "OkCancelDialogFragment2");
}
Now you need to implement the dialog callback in the Activity that calls the DialogFragment.
#Override
public void onFinishOkCancelDialog(boolean submit) {
if(submit){
// Do something positive
}
else{
// Do something negative
}
}
Now the code for the DialogFragment:
public class OkCancelDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
private static final String ARG_MESSAGE = "message";
Context context = null;
private String title;
private String message;
private boolean submitData = false;
private OkCancelDialogListener mListener;
public OkCancelDialogFragment() {
}
public static OkCancelDialogFragment newInstance(String title, String message) {
OkCancelDialogFragment fragment = new OkCancelDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putString(ARG_MESSAGE, message);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
title = getArguments().getString(ARG_TITLE);
message = getArguments().getString(ARG_MESSAGE);
}
}
#Override
public Dialog onCreateDialog(Bundle saveIntsanceState){
context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View rootView = inflater.inflate(R.layout.fragment_ok_cancel_dialog, null, false);
final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);
titleView.setText(title);
messView.setText(message);
builder.setView(rootView)
// .setTitle(title)
.setPositiveButton(R.string.ok_button_dialog_title, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = true;
if(mListener == null) mListener = (OkCancelDialogListener) context;
mListener.onFinishOkCancelDialog(submitData);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = false;
if(mListener == null) mListener = (OkCancelDialogListener) context;
mListener.onFinishOkCancelDialog(submitData);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
if(mListener == null) mListener = (OkCancelDialogListener) context;
}
catch (Exception ex){
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OkCancelDialogListener {
void onFinishOkCancelDialog(boolean submit);
}
}
Please note that .setTitle(title) is valid for API 23 or higher (or maybe API 21 or higher?).
You can create your custom xml layout
and in the OnClickListener of the button you can put this :
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
alertLayout = inflater.inflate(R.layout.YOUR_CUSTOM_POPUP_LAYOUT, null);
final AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setView(alertLayout);
TextView msg= alertLayout.findViewById(R.id.YOUR_TEXTVIEW_ID);
alert.show();
after that you can add another button in your popup and set a listener on it to dismiss the layout after the click.
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 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.
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")