Dismiss DialogFragment onClick not working properly - android

I have an dialogfragment and its view consists of a simple seekbar and positive and negative buttons. When I dismiss dialogfragment onclick, a new dialogfragment is created and showed. After second click on button, dialog is dismissed, but my desire is dismissing after first click. Also I should note that my activity hosts two fragments and I call dialog.show() from first fragment.
MyListFragment.java
FragmentManager manager = getFragmentManager();
fndSrchFragment dialog = new fndSrchFragment();
dialog.setTargetFragment(MyListFragment.this, REQUEST_COLOR);
dialog.show(manager, SRCH_FND);
fndSrchFragment.java
public class fndSrchFragment extends DialogFragment {
.
.
//variable definition
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.color_picker, null);
rSb=(SeekBar) view.findViewById(R.id.r_seek_bar);
.
.
//code for interacting with seekbar
.
.
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
int ccolor = android.graphics.Color.rgb(rComponent, gComponent, bComponent);
sendResult(Activity.RESULT_OK, ccolor);
// two click is needed for dismiss which I don't know why?
dismiss();
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// two click is needed for dismiss which I don't know why?
dismiss();
}
});
return builder.create();
}
Thank You in Advance.

Set up a log command inside your onMenuItemActionExpand(). I bet you'll see this method is called right after you dismissed the dialog. Most likely, this method is being called by the system once focus is returned from the dialog to the activity. You should but your call to dialog.show() inside a something like onOptionsItemSelected(MenuItem item) instead.

Related

How to set the title and text in FragmentDialog?

I have a MainActivity containing 5 fragments, 2 of which have a help icon on the toolbar on top right. I have hidden this icon on other 3 fragments. Upon clicking help icon, an alert dialog shows up with title, message and a positive button.
This is my Alert Dialog code:
public class HelpDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Help");
builder.setMessage("Placeholder");
builder.setPositiveButton("Got It", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {}
});
return builder.create();
}
}
and this is how I am showing it from MainActivity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_help:
DialogFragment helpDialog = new HelpDialogFragment();
helpDialog.show(getSupportFragmentManager(), "dialogHelp");
return true;
}
return super.onOptionsItemSelected(item);
}
The above code works but I would like to show different message based on the fragment selected so how to change the message? I tried this to change title
helpDialog.getDialog().setTitle("Some Text");
Please note I want to change Dialog message, i.e main content, I only got setTitle() method on getDialog() and not setMessage(), the above setTitle is just for example purpose but even it is throwing NullPointerException.
As you can see in the above screenshot, "Placeholder" text is the default text I added at the time of creating AlertDialog but now how to change it?
From reading your post and comments it looks like you need to set different titles depending on whatever fragment is visible. And the creation of dialogs happens from Activity so you are not sure what title to set.
The problem is essentially identifying the visible fragment and set message according to it.
You can pass the message with arguments like this.
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putString(message, "My title");
fragment.setArguments(bundle);
Then in your Fragment, get the data (e.g. in onCreate() method)
Bundle bundle = this.getArguments();
if (bundle != null) {
String message = bundle.getString(message, defaultValue);
}
How to identify the currently visible fragment? You can do this as suggested in these answers. Once you get the current fragment, just send the message in the arguments above according to it.
By combining the above 2 ideas you can do this.
Another way would be to start the dialog from the fragment and not from the Activity but that would involve more changes so the above approach is better.
First pass the required message over a bundle while calling HelpDialogFragment class
HelpDialogFragment helpDialog = new HelpDialogFragment();
Bundle bundle = new Bundle();
bundle.putString("placeholder", "Custom placeholder");
helpDialog.setArguments(bundle);
helpDialog.show(getSupportFragmentManager(), "dialogHelp");
Now modify your HelpDialogFragment class create the dialog like this
public class HelpDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Help");
if (getArguments() != null)
builder.setMessage(getArguments().getString("placeholder",""));
builder.setPositiveButton("Got It", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {}
});
return builder.create();
}
}

Change textview after select an option in a RadioButtonGroup

I have toolbar where a have a menu. In that menu I have lots of options, one of them, when is pressed open an alertDialog with a RadioButtonGroup (with a setSingleChoiceItems) where the user can choose a property. After user choose the property and clicks on OK button of that AlertDialog I return to my Activity which was in background.
The problem is that after user choose the property in alertDialog and clicks in OK button (alertDialog disappears as normal) the textViews of my activity (that which is on the background) should change (according to the property chosen by user) and they are not changing.
All my activities (that can run in background while the user choose the property in alertdialog) extends an activity I have with the all events of Toolbar (including choose that property, share app, etc). I mean I have an activity for all things relate to toolbar menu. Every time user choose a different property I save it in database for then I could read it.
How can I do for when user choose a value of that property, the texviews of my background activity change? (I thought with the onResume it was easy to do, but it doesn't work.). Thanks
Please check if the screenshot helps you to understand my problem.In red what I want to change.
I don't think a dialog changes the activity stack, meaning onPause/onResume are not called.
As #sahu commented you can determine that your dialog closed in the positive/negative buttons:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Do it?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
// change your textviews
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
// cancel pressed, probably don't need to do anything
}
});
builder.create().show();
}
EDIT:
If your dialog code is in a different class you will need to add an interface to communicate from the toolbar back to your activity. This is not much different than fragment to activity communication:
http://developer.android.com/training/basics/fragments/communicating.html
In your toolbar you will need to define an interface that your activity can call.
public class MyToolbar extends Toolbar {
OnInfoChangedListener mCallback;
// Don't forget to call this from your activity to setup the listener
public setOnInfoChangedListener(OnInfoChangedListener callback) {
mCallback = callback;
}
// Container Activity must implement this interface
public interface OnInfoChangedListener {
// you can add arguments here as needed
public void onInfoChanged();
}
...
}
Then in your setPositive button tell your activity that the info changed:
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
if (mCallback != null) mCallback.onInfoChanged();
// change your textviews
}
})
Then in your activity:
public static class MainActivity extends Activity
implements OnInfoChangedListener {
...
#Override
public void onCreate(bundle) {
super.onCreate(bundle);
Toolbar toolbar = // get the toolbar;
toolbar.setOnInfoChangedListener(this); // set myself as listener
}
public void onInfoChanged() {
// The user selected something from your toolbar
// update your views
}
}
You can define your interface to pass whatever you want from your toolbar into your activity, this is just a simple 'hey something changed notification'.
try
radiogroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(RadioGroup group, int checkedId)
{
switch(checkID)
case 0: textview.setText("your text");
break;
...
it may help !

the diff with onCreateView and onCreateDialog in DialogFragment

I had a working DialogFragment that was using an inner class to do a bunch of things on some objects, set menu icons etc. When i went to Android Studio i realised that was incorrect and i've been trying to change the inner class to be static.
In so doing, I am now trying to use onCreateDialog to, as per Google docs, "doPositiveClick" and "doNegativeClick", so that the calling MainActivity can do the work on those objects instead of the fragment doing it.
What is now confusing me however, is how do I set the layout in the fragment - I can enter a title, message and buttons as such:
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.alert_title)
.setMessage(R.string.alert_message)
.setPositiveButton(R.string.set,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((MainActivity)getActivity()).doPositiveClick();
}
}
)
.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((MainActivity)getActivity()).doNegativeClick();
}
}
)
But previously I was doing the layout like:
final EditText input = new EditText(MainActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(20, 20);
input.setText("5");
input.setLayoutParams(lp);
input.setRawInputType(Configuration.KEYBOARD_QWERTY);
Problem is, where does this go in onCreateDialog ? The Google docs shows how to set text on a dialog textView, but that is within onCreateView().
My confusion is that the google doc doesnt do both, ie, it doesnt show how to both, set up custom elements, AND set up the positive/negative click in the calling MainActivity - or if it does, i'm sorry I cant see it right now.
So can anyone make it clearer for me, using the above onCreateDialog, how can I have an editText field, with a default value that takes user input, and then get back that input to the doPositiveClick() to process.
DialogFragment can use in 2 ways: dialog or view.
case1: use DialogFragment as a dialog. you have to implement onCreateDialog() to return a dialog. and then have to show the dialog in the following way. see the example:
public static class MyAlertDialogFragment extends DialogFragment {
public static MyAlertDialogFragment newInstance(int title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
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(R.drawable.alert_dialog_icon)
.setTitle(title)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((FragmentAlertDialog)getActivity()).doPositiveClick();
}
}
)
.setNegativeButton(R.string.alert_dialog_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((FragmentAlertDialog)getActivity()).doNegativeClick();
}
}
)
.create();
}
}
Create and have to show dialog as the following way. show this way don't care, whether onCreateView() is implemented or not.
// Create the fragment and show it as a dialog.
DialogFragment newFragment = MyDialogFragment.newInstance();
newFragment.show(getFragmentManager(), "dialog");
case2: use as view (it is not feature of dialog). it is only view. you have to implement onCreateView() and show dialog as the following way:
public static class MyDialogFragment extends DialogFragment {
static MyDialogFragment newInstance() {
return new MyDialogFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.hello_world, container, false);
View tv = v.findViewById(R.id.text);
((TextView)tv).setText("This is an instance of MyDialogFragment");
return v;
}
}
and have to show view as follow. the same as use Fragment class. show this way don't care, whether onCreateDialog() is implemented or not.
FragmentTransaction ft = getFragmentManager().beginTransaction();
DialogFragment newFragment = MyDialogFragment.newInstance();
ft.add(R.id.embedded, newFragment);
ft.commit();
summary:
in design, you can implement onCreateView() and onCreateDialog() together and use the same source code with this DialogFragment lifecycle. If the screen is small, use DialogFragment as Dialog. If the screen is big, use DialogFragment as view (the same common Fragment class).
Notice that use the correct way to show DialogFragment to suitable with onCreateView() and onCreateDialog() to prevent exception.
sorry guys I thought I exhausted my searches but just after I posted this I was able to fix it, putting the text field/layout inside the onCreateDialog BEFORE the Builder and then doing setView() to that input as such:
**LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(20, 20);
final EditText input = new EditText(getActivity());
input.setText("5");
input.setLayoutParams(lp);
input.setRawInputType(Configuration.KEYBOARD_QWERTY);**
// Use the Builder class for convenient dialog construction
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.alert_title)
.setMessage(R.string.alert_message)
**.setView(input)**
.setPositiveButton(R.string.set,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((MainActivity)getActivity()).doPositiveClick();
}
}
)
Only question now is how do I get the value back after the user inputs ?

How to prevent DialogFragment from being dismissed when activity gets resumed

I have an Activity which shows a DialogFragment when an event occurs in the Activity. When my application is running the user can press home button to make the app run in background. When app is running in background, as soon as the event occurs, the activity should show the DialogFragment, so that when user resumes the app the dialog should be on top of the activity, however I am not getting the results I want. As soon as I resume the app from launcher icon or notification, the dialog does not appear on the activity.
Here is my DialogFragment class:
public static class MyDialog extends DialogFragment {
public static DialogInterface.OnClickListener mListener;
public static String mTitle, mBody;
public static boolean mConfirm;
public static MyDialog getInstance(String body, boolean confirm,
DialogInterface.OnClickListener listener) {
mListener = listener;
mTitle = "MyDialog";
mBody = body;
mConfirm = confirm;
MyDialog fragment = new MyDialog();
return fragment;
}
#Override
public Dialog onCreateDialog(Bundle savedIntanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle(mTitle).setMessage(mBody)
.setPositiveButton("Ok", mListener);
if (mConfirm)
builder.setNegativeButton("Cancel", mListener);
return builder.create();
}
}
The dialog works fine when activity is in foreground.
Here is how I show the dialog:
MyDialog.getInstance("This is dialog body text", true,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
// positive button pressed
}else //negative button pressed
}
}).show(getSupportFragmentManager(), "dialog");
I want a dialog that remains on the activity even if the activity is in background, and as soon as I resume the activity, the dialog should be on top of the activity. How can I achieve this behavior?
You can declare a global boolean to determine if you should show the dialog or not. Then in your activity onResume() method you show the dialog depending on the boolean value.
If the user is finished interacting with the dialog you can set this boolean to false which will cause it not to show again when your activity is in the foreground (onResume).
Try using Fragment's or Activity's showDialog(int) methods and your dialog will be retained automatically.

Reset Android DialogFragment

I am using a custom DialogFragment to let a user change his login credentials. There are some text fields and two buttons (save/cancel). The layout is set in DialogFragment's onCreateView method.
If I open the dialog text fields are filled with default values. When the user changes text in a text field and clicks the cancel button the dialog is dismissed. Next time the dialog opens the text field changed before does not contain the default value as i expected but the text the user changed before. The text fields are not reset. This is almost the same problem mentioned here Reset an Android Dialog. The problem is that the solution provided refers to a Dialog which is deprecated in API level 11 and i cannot use onPrepareDialog with a DialogFragment.
Is there a similar way to reset the content of a DialogFragment?
You can override onResume() in your class, which extends DialogFragmet, as follows:
private static class MyDialogFragment extends DialogFragment {
public static MyDialogFragment newInstance() {
// ...
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// ...
}
#Override
public void onResume() {
super.onResume();
Dialog dialog = getDialog();
// reset code goes here - use dialog as you would have in onPrepareDialog()
}
}
You can also use .setText() method in Your activity as reaction after negative button click. Eg:
In DialogFragment.java, onCreateDialog(...)define AlertDialog.Builder
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
then
//this is better than creating button in layout
builder.setNegativeButton(R.string.button_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((MainAct) getActivity()).cancelDialog(DialogFragment.this);
}
}
);
In MainActivity.java create method cancelDialog(DialogFragment df) {
//here use df to reset text fields
}

Categories

Resources