I am creating a custom dialog class in which I extend the default Dialog. I am doing some work there. Once the user closes the dialog, how can my activity know that the dialog is closed and time to update the screen views with results?
Do I pass an instance from my activity to the Dialog class so I can call a public method on it? Or is there a better design?
Thank you
what I'll do is this:
Create an Interface, for example: OnDialogCloseListener, with a method called onDialogClose()
The activity have to implement that interface and override the onDialogClose() method
Create an attribute in yout Dialog class of OnDialogCloseListener type and a constructor method and when you create the Dialog pass the activity as a parameter.
OnDialogCloseListener listener;
public MyDialog(OnDialogCloseListener listener) {
this.listener = listener;
}
Now in your onClick method of the close button of your Dialog call the method of the interface. Ex.:
listener.onDialogClose();
And finally in your activity class in the method that you override from OnDialogCloseListener do whatever you want when the Dialog is close.
Note: You can create all the methods that you want in the interface a call each one whatever you want, not only when the dialog is close, you may have other events that you want check when raised.
Hope that can help you
From the docs: http://developer.android.com/guide/topics/ui/dialogs.html
create an interface in your dialog class:
public interface NoticeDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
Register a listener in onAttach() :
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
And implement that interface in your calling activity.
A dialog overrides several methods that sense when the dialog is closing. The include
#Override
public void onBackPressed() {
super.onBackPressed();
}
#Override
public void setOnCancelListener(#Nullable OnCancelListener listener) {
super.setOnCancelListener(listener);
}
#Override
protected void onStop() {
super.onStop();
}
These methods all detect that action of closing a dialog. However, the most efficient one that I suggest you use is
#Override
public void onDetachedFromWindow() {
Toast.makeText(getContext().getApplicationContext(), "Dialog had disappeared", Toast.LENGTH_SHORT).show();
super.onDetachedFromWindow();
}
Related
I have Activity in my app with few fragments in it. One of these fragments has a DialogFragment, it called by button click. DialogFragment has 3 buttons - positive, negative and neutral.
public class CompanyNotConnectedToSRDialog extends DialogFragment {
public static final String TAG = CompanyNotConnectedToSRDialog.class.getSimpleName();
private NotConnectedDialogListener mNotConnectedDialogListener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity(), R.style.DefaultAlertDialogTheme)
.setTitle("Register")
.setMessage("Do you really want to register?")
.setNeutralButton("Skip", (dialog1, which) -> {
mNotConnectedDialogListener.onSkipBtnNotConnectedDialogPressed();
})
.setNegativeButton("Cancel", null)
.setPositiveButton("Register", (dialog12, which) -> {
mNotConnectedDialogListener.onSendBtnNotConnectedDialogPressed();
})
.create();
}
public interface NotConnectedDialogListener {
void onSkipBtnNotConnectedDialogPressed();
void onSendBtnNotConnectedDialogPressed();
}
public void setListener(NotConnectedDialogListener listener) {
this.mNotConnectedDialogListener = listener;
}
As you can see I created public interface that contains two methods for my skip and register buttons (cancel button listener is null so it doesn't matter) and the Setter for this listener.
Then I implemented this interface in my fragment that calls this dialogFragment, I Overrided methods and called dialogFragment like this:
if (mNotConnectedDialog == null) {
mNotConnectedDialog = new CompanyNotConnectedToSRDialog();
mNotConnectedDialog.setListener(this);
mNotConnectedDialog.show(getActivity().getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
} else {
mNotConnectedDialog.show(mActivity.getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
mNotConnectedDialog.setListener(this);
}
The problem is I get NullPointerException if I press the button in my parent Fragment to show DialogFragment, rotate screen and press any button in my DialogFragment, because my listener is null.
java.lang.NullPointerException: Attempt to invoke interface method 'void com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog$NotConnectedDialogListener.onSendBtnNotConnectedDialogPressed()' on a null object reference
at com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog.lambda$onCreateDialog$1(CompanyNotConnectedToSRDialog.java:31)
How to handle these clicks and set listeners if this solution is wrong?
PS: please don't tell me about android:configChanges.
So the current solution doesn't work because when you rotate the dialog fragment is destroyed and recreated. So setListener isn't called. The solution depends on if your listener is an activity or another fragment.
If it's an activity you can override onAttach in your DialogFragment and set the listener there. If your listener is a fragment then in your OnCreateDialog method you can look the fragment up by the tag and set the listener that way. For example.
Fragment listenerFragment = getActivity().getSupportFragmentManager().findFragmentByTag(getString(R.string.your_listener_fragment_tag));
if( listenerFragment instanceOf NotConnectedDialogListener ) {
listener = (NotConnectedDialogListener) listenerFragment;
} else {
//Handle what to do if you don't have a listener here. Maybe dismiss the dialog.
}
Yes, after orientation change your listener is null. It's easiest to do the callback to the activity:
public static class DialogFragmentA extends DialogFragment {
// Container Activity must implement this interface
public interface NotConnectedDialogListener {
public void onX();
}
NotConnectedDialogListener mListener;
...
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (NotConnectedDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement NotConnectedDialogListener");
}
}
...
}
Now you can call mListener.onX etc. in your dialog anywhere, also after orientation change. Your container Activity must implement the interface and will receive the method call.
https://developer.android.com/guide/components/fragments.html#EventCallbacks
I have an activity and a fragment. If I click a button then a fragment is called. Upon the result I got from the fragment I need some networking call to perform using volley. But I can't do any networking call from activity unless I call this within onClick() method.
I tried to perform networking from within onClick() of the fragment but that did not worked too.
How can i perform networking from the activity upon the result I got from the fragment? Do I must call from within onClick()?
This is the fragment
This is the Activity
I think that you can use callback.
Create intefrace and declare method saveResult() in it.
public interface YourInterface{
void saveResult();
}
After that your Activity must implement this interface and add your code for save result in database in saveResult method body
public class YourActivity implements YourInterface{
#override
void saveResult(){
//your code here
}
}
And finnaly in your fragment call method when you whant or when your fragment is ready.You can call method with help of
callBack.saveResult();
You must override onAttach in your fragment and there must initialize your callback
YourInterface callback;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if(activity instanceof YourInterface ) {
callback = (YourInterface ) activity;
}
}
Try with other on click method in at your onCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mark_distribution);
assign_buttton=(Button)findViewById(R.id.assign_marks);
view_buttton=(Button)findViewById(R.id.view_marks);
update_buttton=(Button)findViewById(R.id.update_marks);
//Like this-->>>
update_buttton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
marks_type=(String)assigned_marks_type.getText().toString();
marks=Integer.parseInt(assigned_marks.getText().toString().trim());
callback.saveResult(marks_type,marks);
}
});
//********************/
Intent i=getIntent();
course_title= i.getExtras().getString("COURSE_TITLE");
}
Hope to help you!
I have an activity that call a dialogfragment, how can I get the fragment result when it dismissed? Is there any method for fragment like onActivityResult?
You have to implement a callback to know the response of your dialog fragment. If you want to implement this, create an interface in your dialog fragment. Like this example:
interface OnResultDialog{
public void onDialogRespond(Object result);
}
private OnResultDialog mCallback;
And implement this interface in your activity. In the onAttach of your DialogFragment, set the activity as an OnResultDialog:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallback = (OnResultDialog)activity;
}
Then, before or after you dismiss your dialog, you can call the method of your callback and pass the parameters you need. Like this:
mCallback.onDialogRespond(object);
Hope it helps
I have an activity which may show some DialogFragments. This activity needs to get the response from the dialogs.
I use a listener. In activity:
ProgressMarkDialog dialog = new ProgressMarkDialog();
dialog.setOnProgressMarkSelected(new ProgressMarkDialog.OnProgressMarkSelected() {
#Override
public void onSelect(final int a) {
//some code..
}
});
In the dialog:
public void setOnProgressMarkSelected(OnProgressMarkSelected onProgressMarkSelected) {
this.onProgressMarkSelected = onProgressMarkSelected;
}
This code works fine until somehow the activity is destroyed, but the dialog still open. The program will crash with NullPointerException because the onProgressMarkSelected is null.
I can use
#Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
onProgressMarkSelected = (OnProgressMarkSelected) activity;
}
and implement the interface in the activity.
But if I have few DialogFragments, that means I should implement few interface in the activity and the code will be very messy.
What is the Android best practice for this case?
In my opinion the best way is to stick to the standard positive/negative buttons and attaching DialogInterface.OnClickListener as shown in the http://developer.android.com/reference/android/app/DialogFragment.html
Look at it this way: standard Android user expects to see positive and/or negative button in the dialog. The Activity -if needed- should only be informed about the result (positive, negative input data) of the dialog. Any other input validation should be handled inside the DialogFragment
You could use inheritance with interfaces. Because on interfaces multiple inheritance is possible like this:
public interface A(){
void doA();
}
public interface B(){
void doB();
}
public interface BundleAB extends A, B {
void justAnotherMethod();
}
With this you can bundle your interfaces and use it like this:
public class MyClass implements BundleAB {
#Override
public void doA(){}
#Override
public void doB(){}
#Override
public void justAnotherMethod(){}
}
I have created a DialogFragment with a custom AlertDialog that I need to show on several points of my application. This dialog asks for the user to input some data.
I would like to find a way to make the activity where the dialog is called upon to wait for the users input and then perform a variable action when the user presses the ok button (or nothing if he presses cancel).
AFAIK there's no "modal dialog" in Android so what would be the proper way to achieve this (pretty usual) kind of behavior?
To allow a Fragment to communicate up to its Activity, you can define an interface in the Fragment class and implement it within the Activity.
public class MyDialogFragment extends DialogFragment {
OnDialogDismissListener mCallback;
// Container Activity must implement this interface
public interface OnDialogDismissListener {
public void onDialogDismissListener(int position);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnDialogDismissListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnDialogDismissListener");
}
}
...
}
In dialog Ok listener add
mCallback.onDialogDismissListener(position);
In your activity
public static class MainActivity extends Activity
implements MyDialogFragment.OnDialogDismissListener{
...
public void onDialogDismissListener(int position) {
// Do something here to display that article
}
}