Getting information from DialogFragment using onDismiss() - android

I am working on an app and I am using a custom dialog which extends DialogFragment. This dialog will contain certain field that I want to pass to the parent activity. I tried implementing OnDismissListener but the parameter is a Dialog Interface.
Any Idea?
parent Activity:
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
BreakCreator mDialog = new BreakCreator();
mDialog.show(getSupportFragmentManager(), "start break Creator");
}
});
listener:
#Override
public void onDismiss(DialogInterface dialog) {
Log.d("debug", "in onDismiss");
BreakCreator mBreakCreator = BreakCreator.class.cast(dialog);// This MIGHT not work
//TODO cast and shit
if(!mBreakCreator.isCancelled() ){
int startMinute = mBreakCreator.getStartMinute();
int startHour = mBreakCreator.getStartHour();
int endMinute = mBreakCreator.getEndMinute();
int endHour = mBreakCreator.getEndHour();
String day = mBreakCreator.getDay();
Break mBreak = new Break(new ultramirinc.champs_mood.Time(startHour, startMinute),
new ultramirinc.champs_mood.Time(endHour, endMinute), day);
breakList.add(mBreak);
Log.d("created", "break added");
recyclerView.invalidate();
}else{
Log.d("debug", "is not cancelled");
}
}
Dialog Class:
public void onDismiss(final DialogInterface dialog) {
super.onDismiss(dialog);
final Activity activity = getActivity();
if (activity instanceof DialogInterface.OnDismissListener) {
((DialogInterface.OnDismissListener) activity).onDismiss(dialog);
}
}

Use a custom listener, below is an example on how this could be implemented. This is also explained in the Android Developer Guide.
public class CustomDialog extends DialogFragment {
public interface CustomListener{
void onMyCustomAction(CustomObject co);
}
private CustomListener mListener;
public void setMyCustomListener(CustomListener listener){
mListener = listener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
Code to create dialog
...
}
#Override
public void onDismiss(DialogInterface dialog) {
if(mListener != null){
CustomObject o = new CustomObject();
mListener.onMyCustomAction(o);
}
super.onDismiss();
}
}
And when the custom dialog is created, set the listener.
CustomDialog awesomeDialog = new CustomDialog();
awesomeDialog.setMyCustomListener(new CustomDialog.CustomListener() {
#Override
public void onMyCustomAction(CustomObject o){
Log.i("TAG",o.toString());
}
});

Related

How to set up a custom listener in a custom dialog for android?

I'm currently having trouble setting up my custom listener. I just want to pass a string from my dialog to my fragment (where I set up the dialog). I was trying to follow this tutorial: https://www.youtube.com/watch?v=ARezg1D9Zd0.
At minute 10:38, he sets up the listener.
This only problem is that in this, he uses DialogFragment, but I'm extending dialog and I don't know how to attach the context to the listener.
I've tried to set it up in onAttachedToWindow() and in the dialog constructor but it crashes.
What should I actually do?
I'd also appreciate it if someone could explain what the difference is between:
onAttachedToWindow() vs. onAttach(Context context).
Thanks!
MY CUSTOM DIALOG BOX:
public class NewListDialog extends Dialog implements View.OnClickListener {
private Activity c;
private TextInputLayout textInputLayout;
private TextInputEditText editText;
private LinearLayout dialog_root_view;
private Animation fade_out;
private String list_name;
private NewListDialogListener listener;
NewListDialog(Activity a) {
super(a);
this.c = a;
//ANOTHER ATTEMPT TO ATTACH CONTEXT TO LISTENER
//listener = (NewListDialogListener) a.getApplicationContext();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.new_list_dialog);
MaterialButton cancel = findViewById(R.id.dialog_new_list_cancel_button);
MaterialButton create = findViewById(R.id.dialog_new_list_create_button);
textInputLayout = findViewById(R.id.dialog_text_input_layout);
editText = findViewById(R.id.dialog_edit_text);
dialog_root_view = findViewById(R.id.dialog_root);
fade_out = AnimationUtils.loadAnimation(c, R.anim.fade_out_dialog);
editText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isTextValid(editText.getText())) {
textInputLayout.setError(null);
return true;
}
return false;
}
});
cancel.setOnClickListener(this);
create.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
//Cancel Button
case R.id.dialog_new_list_cancel_button:
dialog_root_view.startAnimation(fade_out);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
dismiss();
}
}, 200);
break;
//Create Button
case R.id.dialog_new_list_create_button:
if (!isTextValid(editText.getText())) {
textInputLayout.setError(c.getString(R.string.dialog_error));
} else {
textInputLayout.setError(null);
//record input string
list_name = editText.getText().toString();
//send information to parent activity
//What to put here?
listener.createListName(list_name);
dismiss();
}
break;
default:
break;
}
}
private boolean isTextValid(#Nullable Editable text) {
return text != null && text.length() > 0;
}
//ATTEMPT TO ATTACH CONTEXT TO LISTENER
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
try {
listener = (NewListDialogListener) c.getBaseContext();
} catch (ClassCastException e) {
throw new ClassCastException(c.getBaseContext().toString() + "must implement ExampleDialogListener");
}
}
public interface NewListDialogListener {
void createListName(String listname);
}
}
In case you define a custom dialog then you can declare a method to allow other components call it or listen events on this dialog. Add this method to you custom dialog.
public void setNewListDialogListener(NewListDialogListener listener){
this.listener = listener;
}
NewListDialog.java
public class NewListDialog extends Dialog implements View.OnClickListener {
private Activity c;
private TextInputLayout textInputLayout;
private TextInputEditText editText;
private LinearLayout dialog_root_view;
private Animation fade_out;
private String list_name;
private NewListDialogListener listener;
NewListDialog(Activity a) {
super(a);
this.c = a;
}
public void setNewListDialogListener(NewListDialogListener listener) {
this.listener = listener;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.new_list_dialog);
MaterialButton cancel = findViewById(R.id.dialog_new_list_cancel_button);
MaterialButton create = findViewById(R.id.dialog_new_list_create_button);
textInputLayout = findViewById(R.id.dialog_text_input_layout);
editText = findViewById(R.id.dialog_edit_text);
dialog_root_view = findViewById(R.id.dialog_root);
fade_out = AnimationUtils.loadAnimation(c, R.anim.fade_out_dialog);
editText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isTextValid(editText.getText())) {
textInputLayout.setError(null);
return true;
}
return false;
}
});
cancel.setOnClickListener(this);
create.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
//Cancel Button
case R.id.dialog_new_list_cancel_button:
dialog_root_view.startAnimation(fade_out);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
dismiss();
}
}, 200);
break;
//Create Button
case R.id.dialog_new_list_create_button:
if (!isTextValid(editText.getText())) {
textInputLayout.setError(c.getString(R.string.dialog_error));
} else {
textInputLayout.setError(null);
//record input string
list_name = editText.getText().toString();
//send information to parent activity
//What to put here?
if (listener != null) {
listener.createListName(list_name);
}
dismiss();
}
break;
default:
break;
}
}
private boolean isTextValid(#Nullable Editable text) {
return text != null && text.length() > 0;
}
public interface NewListDialogListener {
void createListName(String listname);
}
}
In other components such as an activity which must implements NewListDialogListener.
NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(this);
If you don't want the activity implements NewListDialogListener then you can pass a listener instead.
NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(new NewListDialog.NewListDialogListener() {
#Override
public void createListName(String listname) {
// TODO: Your code here
}
});
In android Fragments and Activity has lifecycles. Fragments are hosted inside Activity and get the context of host activity via onattach method.
On the other hand Dialog is extended from Object (God class) without any lifecycle and should be treaded as an object.
If your activity is implementing NewListDialogListener then you can do
listener = (NewListDialogListener) a;
onAttachedToWindow : mean the dialog will be drawn on screen soon
and
getApplicationContext() will give you the context object of the application (one per app) which is surely not related with your listener and hence won't work
Reference :
Android DialogFragment vs Dialog
Difference between getContext() , getApplicationContext() , getBaseContext() and “this”
You can use RxAndroid instead of using listener, in this situation I use RxAndroid to get data from dialogs to activities or fragments.
Just need to create a PublishSubject and get the observed data. on activity or fragment :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PublishSubject<String > objectPublishSubject = PublishSubject.create();
objectPublishSubject.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread())
.subscribe(this::onNext);
CustomDialog customDialog = new CustomDialog(this, objectPublishSubject);
customDialog.show();
}
private void onNext(String data) {
Log.i("DIALOG_DATA", data);
}
and you can create dialog like this :
public class CustomDialog extends Dialog implements View.OnClickListener {
private PublishSubject<String> subject;
public CustomDialog(#NonNull Context context, PublishSubject<String> subject) {
super(context);
this.subject = subject;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_dialog);
findViewById(R.id.button).setOnClickListener(this);
}
#Override
public void onClick(View v) {
subject.onNext("Data");
dismiss();
}

Listener Null Object Reference

my onAttach() method assigns the context to the listener, however, my listener is null somehow. How can I fix this problem properly? I hope you can provide me the code with some instructions?
ChooseScreen class which initializes the dialog (In this case nameDialog):
public class ChooseScreen extends AppCompatActivity {
private Button vsFriend;
private Button vsAndroid;
private NameDialog.NameDialogListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_choose_screen);
vsFriend = findViewById(R.id.vsF);
vsAndroid = findViewById(R.id.vsA);
vsFriend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openDialog();
}
});
}
public void openDialog() {
NameDialog nameDialog = new NameDialog();
nameDialog.show(getSupportFragmentManager(), "example");
}
}
NameDialog class with getTexts interface:
public class NameDialog extends AppCompatDialogFragment {
private EditText firstPlayer;
private EditText secondPlayer;
private NameDialogListener listener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.layout_dialog, null);
firstPlayer = view.findViewById(R.id.edit_player1);
secondPlayer = view.findViewById(R.id.edit_player2);
builder.setView(view)
.setTitle("Names")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String player1 = firstPlayer.getText().toString();
String player2 = secondPlayer.getText().toString();
listener.getTexts(player1, player2);
// Intent intent = new Intent(NameDialog.this.getActivity(), Game.class);
// startActivity(intent);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
listener = (NameDialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement");
}
}
public interface NameDialogListener {
void getTexts(String player1, String player2);
}
}
Game class which implements NameDialogListener and overrides the interface method(getTexts):
public class Game extends AppCompatActivity implements
NameDialog.NameDialogListener {
private TextView player1Name;
private TextView player2Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
player1Name = findViewById(R.id.player1TextView);
player2Name = findViewById(R.id.player2TextView);
}
#Override
public void getTexts(String player1, String player2) {
player1Name.setText(player1);
player2Name.setText(player2);
}
}
Error: If I don't use try-catch block, the error will be NullPointerException because listener is null!
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.user.tictactoe, PID: 30462
java.lang.ClassCastException: com.example.user.tictactoe.ChooseScreen#1a0a489must implement
at com.example.user.tictactoe.NameDialog.onAttach(NameDialog.java:62)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1372)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
When you attach your Fragment you attempt to get a Listener from your ChoooseScreen Activity. That Activity does not implement NameDialogListener, so you get a ClassCastException. In your examples you show another Activity, Game that does implement the listener, however any activity you add your Fragment in will need to implement the listener to work with your onAttach() code.
Short answer: if you want to show the Fragment in ChooseScreen, your code requires ChooseScreen to implement NameDialogListener.
onAttach will get the context of your parent activity. when you open your Dialog from ChooseScreen activity, the parent is ChooseScreen. The interface callback will be given to ChooseScreen itself. Then what you need to do is to call Intent with player1Name and player2Name.
Anyways I will share the code for you.
Your ChooseScreen
public class ChooseScreen extends AppCompatActivity implements NameDialog.NameDialogListener {
private Button vsFriend;
private Button vsAndroid;
private NameDialog.NameDialogListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_choose_screen);
vsFriend = findViewById(R.id.vsF);
vsAndroid = findViewById(R.id.vsA);
vsFriend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openDialog();
}
});
}
public void openDialog() {
NameDialog nameDialog = new NameDialog();
nameDialog.show(getSupportFragmentManager(), "example");
}
#Override
public void getTexts(String player1, String player2) {
Intent intent = new Intent(this, Game.class);
intent.putExtra("PLAYER_ONE", player1);
intent.putExtra("PLAYER_TWO", player2);
startActivity(intent);
}
}
Your NameDialog
public class NameDialog extends AppCompatDialogFragment {
private EditText firstPlayer;
private EditText secondPlayer;
private NameDialogListener listener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.layout_dialog, null);
firstPlayer = view.findViewById(R.id.edit_player1);
secondPlayer = view.findViewById(R.id.edit_player2);
builder.setView(view)
.setTitle("Names")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String player1 = firstPlayer.getText().toString();
String player2 = secondPlayer.getText().toString();
listener.getTexts(player1, player2);
//TODO you can simply use below code and comment listener.getTexts();
// Intent intent = new Intent(NameDialog.this.getActivity(), Game.class);
// intent.putExtra("PLAYER_ONE", player1);
// intent.putExtra("PLAYER_TWO", player2);
// startActivity(intent);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (NameDialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement");
}
}
public interface NameDialogListener {
void getTexts(String player1, String player2);
}
}
Your Game
public class Game extends AppCompatActivity
/* implements NameDialog.NameDialogListener*/ {
private TextView player1Name;
private TextView player2Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
player1Name = findViewById(R.id.player1TextView);
player2Name = findViewById(R.id.player2TextView);
player1Name.setText(
getIntent().getStringExtra("PLAYER_ONE"));
player2Name.setText(
getIntent().getStringExtra("PLAYER_TWO"));
}
// #Override
// public void getTexts(String player1, String player2) {
// }
}
Try this and let me know...

Why does not this AlertDialog show?

I created an AlertDialog :
public class MessageDialogView extends AlertDialog {
private Context ctxt;
private View contenu, titleBar;
#SuppressLint("NewApi")
public MessageDialogView(Context context, LayoutInflater inflater) {
super(context);
ctxt = context;
contenu = inflater.inflate(R.layout.msg_dialog, null);
titleBar = inflater.inflate(R.layout.custom_dialog_title, null);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCustomTitle(titleBar);
setView(contenu, 0, 0, 0, 0);
setButton(DialogInterface.BUTTON_POSITIVE, ctxt.getResources().getString(R.string.button_ok), new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
}
public void setTitre(String titre) {
if (titre != null)
((TextView)titleBar.findViewById(R.id.titre)).setText(titre);
}
public void setMsg(String text){
if (text != null)
((TextView)contenu.findViewById(R.id.msgText)).setText(text);
}
}
The xml layout are very simple ( not necessary to copy their code here :) )
When I try to show the AlertDialog then nothing is showing : just the screen is darkened !
public class SyncActivity extends Activity {
private RadioButton webVersMobile = null;
private MessageDialogView dlg = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.syncro);
webVersMobile = (RadioButton) findViewById(R.id.webMobile);
dlg = new MessageDialogView(SyncActivity.this, getLayoutInflater());
}
...
public void displayError(String msg) {
dlg.setTitre(getString(R.string.titreErrMsgBox));
dlg.setMsg(msg);
dlg.show();
}
...
}
I call the dialog like this :
private class RequestTask extends AsyncTask<String, Void, String> {
...
#Override
protected String doInBackground(String... s_url) {
...
}
#Override
protected void onPostExecute(String result) {
if (error) {
displayError(result);
} else {
}
}
private void displayError(String msg) {
dlg.setTitre(getString(R.string.titreErrMsgBox));
dlg.setMsg(msg);
dlg.show();
}
}
So what is wrong in my code ?
You forgot to call show() method to display the dialog.
dlg = new MessageDialogView(SyncActivity.this, getLayoutInflater());
After this line write dlg.show(); in onCreate() method.
Ok , I found that the reason of my error is that I implemented the onCreate method. When I removed the implementation then the Dialog is shown :)
public class MessageDialogView extends AlertDialog {
private View contenu, titleBar;
#SuppressLint("InlinedApi")
public MessageDialogView(Context context, LayoutInflater inflater) {
super(context, AlertDialog.THEME_HOLO_DARK);
contenu = inflater.inflate(R.layout.msg_dialog, null);
titleBar = inflater.inflate(R.layout.custom_dialog_title, null);
setCustomTitle(titleBar);
setView(contenu, 0, 0, 0, 0);
setButton(DialogInterface.BUTTON_POSITIVE, context.getResources().getString(R.string.button_ok), new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
}
public void setTitre(String titre) {
if (titre != null)
((TextView)titleBar.findViewById(R.id.titre)).setText(titre);
}
public void setMsg(String text){
if (text != null)
((TextView)contenu.findViewById(R.id.msgText)).setText(text);
}
}

onAttach() never called in DialogFragment

I try to implement a callback from a DialogFragment.
There is a good example, but they don't open this DialogFragment from a Fragment.
http://developer.android.com/guide/topics/ui/dialogs.html#PassingEvents
So here is my code:
public class EditDateDialogFragment extends DialogFragment {
// Use this instance of the interface to deliver action events
EditDateDialogListener mListener;
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface EditDateDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
public static EditDateDialogFragment newInstance( int currentCategoryId ) {
EditDateDialogFragment p = new EditDateDialogFragment();
Bundle args = new Bundle();
args.putInt("currentRecordId", currentCategoryId);
p.setArguments(args);
return p;
}
#Override
public void onCreate(Bundle savedInstanceState) {
mCurrentRecordId = getArguments().getInt("currentRecordId");
super.onCreate(savedInstanceState);
}
public void onAttach(SherlockActivity activity) {
super.onAttach(activity);
try {
// Instantiate the EditDateDialogListener so we can send events to the host
mListener = (EditDateDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString() + " must implement EditDateDialogListener");
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
final View v = inflater.inflate(R.layout.fragment_dialog_edit_date, null);
return new AlertDialog.Builder(getActivity()).setTitle("Set Date...").setView(v).setCancelable(true).setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d("", "Dialog confirmed");
mListener.onDialogPositiveClick(EditDateDialogFragment.this);
}
}).setNegativeButton("Abort", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d("", "Dialog abort");
dialog.cancel();
}
}).create();
}
}
In RecordDetailFragment.java i implement the interface and create a new instance of the EditDateDialogFragment at this way (just the important parts):
public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener {
...
DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame");
#Override
public void onDialogPositiveClick(DialogFragment dialog) {
LOGD(TAG, "Overriden Dialog confirmed");
//((EditDateDialogFragment) dialog).mDatePicker;
}
#Override
public void onDialogNegativeClick(DialogFragment dialog) {
// TODO Auto-generated method stub
}
...
}
Now the public void onAttach(SherlockActivity activity) in the EditDateDialogFragment is never called, because I create the DialogFragment from a Fragment instead of an Activity?
How to fix this?
UPDATE:
In the RecordDetailFragment I insert this into the onCreate()
if (savedInstanceState != null) {
EditDateDialogFragment dpf = (EditDateDialogFragment) getActivity().getSupportFragmentManager().findFragmentByTag("EditDateDialogFragment");
if (dpf != null) {
dpf.setListener((EditDateDialogListener) this);
}
}
I changed the instantiation of the DialogFragment to
EditDateDialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDateFragment.setListener((EditDateDialogListener) this);
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFragment");
Note the EditDateDialogFragment instead of DialogFragment.
I'm not sure how to update the reference in the dialog.
Just jumped into the same problem, the solution was very simple. Instead of overriding
public void onAttach(Context context) {}
override this:
public void onAttach(Activity activity) {}
Everything is now fine with DialogFragment.
How to fix this?
I'm guessing that you want the RecordDetailFragment instance to behave as the EditDateDialogListener for the DialogFragment. If yes then you need to explicitly set it(and update it) as the listener:
DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDataFragment.setListener(RecordDetailFragment.this);
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame");
Where setListener() is a method in the EditDialogFragment like this:
public void setListener(EditDateDialogListener listener) {
mListener = listener;
}
As the user rotates the phone, for example, the Activity along with its fragments will be recreated and you need to re set the listener to point to the newly created RecordDetailFragment instance(you may want to use a WeakReference for mListener). Something similar you can find in this answer(you'll look for the two fragments in the onCreate).
Edit: In the onCreate method of the Activity:
if (savedInstanceState != null) {
RecordDetailFragment df = (RecordDetailFragment) getSupportFragmentManager().findFragmentByTag("rdf"); // "rdf" is the tag used when you add the RecordDetailFragment to the activity
EditDateDialogFragment s = (EditDateDialogFragment) getSupportFragmentManager().findFragmentByTag("tag"); // "tag" is the string set as the tag for the dialog when you show it
if (s != null) {
// the dialog exists so update its listener
s.setListener(df);
}
}
Somewhere in the onCreateDialog cast the mListener to the getActivity():
try {
mListener = (EditDateDialogListener) getActivity();
} catch (Exception e) {
throw new ClassCastException(getActivity().toString()
+ " must implement EditDateDialogListener");
}
A more "modern" approach is to use the new Fragment Result API.
Add a result listener on Fragment A (parent) onCreate:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
childFragmentManager.setFragmentResultListener("requestKey", this) { key, bundle ->
val result = bundle.getString("bundleKey")
}
}
Wherever you need, set result on child Fragment B (on a button click listener, for instance):
button.setOnClickListener {
val result = "resultSample"
setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}
More info on the docs: https://developer.android.com/guide/fragments/communicate#kotlin

Can't use onDismiss() when using custom dialogs - Android

I'm working on a little program, and I need to add a custom dialog that passes some info to the calling acitivity when it closes.
I extended the dialog class, and when I try to capture the custom dialog when it closes,using an onDismiss listener, it never reaches it because I used a custom dialog.
This is part of my activity -
.
.
.
attributes customizeDialog = new attributes(con,position,pick.getLastVisiblePosition());
customizeDialog.show();
(The attributes being the name of the class that extends the dialog class).
Here is the event listener I set up when the dialog finishes -
customizeDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
Log.v("LOG_CAT",attributes.selectedIndexes.get(0) + " " + attributes.selectedIndexes.get(1) + " " + attributes.selectedIndexes.get(2) + " " + attributes.selectedIndexes.get(3) + " " + attributes.selectedIndexes.get(5) + " ");
}
});
I know i'm doing it wrong,I just don't know how to fix it.
I would really appreciate any help with this problem.
Thanks!
I tend to have my activity implement listeners like this...
public class MyActivity extends Activity
implements DialogInterface.OnDismissListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
attributes customizeDialog = new attributes(con,position,pick.getLastVisiblePosition());
customizeDialog.setOnDismissListener(this);
customizeDialog.show();
}
#Override
public void onDismiss(DialogInterface dialog) {
// Do whatever
}
}
You could have your calling activity implement a custom listener interface that is called when the dialog closes:
public interface MyDialogListener {
void OnCloseDialog();
}
public class MyActivity implements MyDialogListener {
public void SomeMethod() {
MyDialog myDialog = new MyDialog(this, this);
myDialog.show();
}
public void OnCloseDialog() {
// Do whatever you want to do on close here
}
}
public class MyDialog extends Dialog {
MyDialogListener mListener;
public MyDialog (Context context, MyDialogListener listener) {
super(context, R.style.Dialog);
mListener = listener;
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.CloseButton:
mListener.OnCloseDialog();
dismiss()
break;
default:
//...
}
}
}
This is especially useful if you want to send stuff back to the caller at any other time besides on dismissal.
And if you want to have some sort of saving inside the dialog, again, you have to use onDicmissListener since for custom dialogs onDismiss is not called by default:
public class CustomDialog extends Dialog implements DialogInterface.OnDismissListener {
public CustomDialog(Context context) {
super(context);
setupLayout(context);
}
public CustomDialog(Context context, int theme) {
super(context, theme);
setupLayout(context);
}
protected CustomDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
setupLayout(context);
}
private void setupLayout(Context context) {
this.context = context;
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.custom_dialog);
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = WindowManager.LayoutParams.FILL_PARENT;
getWindow().setAttributes(params);
setOnDismissListener(this);
loadPreferences();
}
private void loadPreferences() {
// ...
}
private void savePreferences() {
// ...
}
#Override
public void onDismiss(DialogInterface dialogInterface) {
savePreferences();
}
}
If you are using custom dialog and can't dismiss it, try below code.
It worked for me.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
dialog.dismiss();
}
}, 1500);
One thing to remember is that an OnDismissListener is listening for the dismiss of the child processes. The parent of your customer dialog needs the onDismissListener, not the dialog itself.
"Interface used to allow the creator of a dialog to run some code when the dialog is dismissed."
To add dialog inside CustomDialog class:
public class MessageBoxDialog extends Dialog implements DialogInterface.OnDismissListener
{
#Override
protected void onCreate(Bundle savedInstanceState) {
...
setOnDismissListener(this);
...
}
#Override
public void onDismiss(DialogInterface dialogInterface) {
}
}

Categories

Resources