I have a dialog with some UI elements in there. This dialog is created and shown at some point later on via show(). I can create the dialog with the default constructor Dialog(Context). But my content view is only set on onCreate which is called after show() function. This causes NPE when I try to modify UI elements like this:
public void showNumber(String number)
{
labelNumber.setText(number);
show();
}
But if call change the above function as below, it works most of the time. (Sometimes it fails if the phone gets slower because setContentView wouldn't be called by the time it executed setText)
public void showNumber(String number)
{
show();
labelNumber.setText(number);
}
How do you create the dialog and set content view without showing it at all. If I call setContentView() manually, it will be re-called when i call show() for the first time.
All you need to do is call create(); on the dialog when you construct it.
When you call show it will create the dialog only if create(); hasn't been called and then call onStart(); on the dialog. Finally it will attach the dialog to the window.
Something like:
Dialog myDialog = new Dialog(context) {
protected void onCreate() {
super.onCreate();
doYourThing
}
};
myDialog.create();
I'm assuming you're doing logic in onCreate, because, in Dialog it's just an empty method for subclasses to override.
onCreate:
http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/app/Dialog.java#37
show:
http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/app/Dialog.java#254
Pre API level 21 (if you can't use an AlertDialog.Builder) you should be able to use onRestoreInstanceState to do what you want to do, like this (this is a hack):
Bundle myBundle = new Bundle();
myBundle.putBoolean("android:dialogShowing", false);
myBundle.putBundle("android:dialogHierarchy", new Bundle());
myDialog.onRestoreInstanceState(myBundle);
Info:
http://androidxref.com/4.4_r1/xref/frameworks/base/core/java/android/app/Dialog.java#411
Related
In my Andriod app, I've got a Dialog extended from AppCompatDialogFragment. I show it immediatelly in my App's main Activity's onCreate:
#Override
protected void onCreate(Bundle savedState)
{
super.onCreate(savedState);
// ....
if( savedState==null )
{
MyDialog diag = new MyDialog();
diag.show(getSupportFragmentManager(), null);
}
}
later on I want to dismiss this dialog - so I need to find it. I cannot simply remember a reference to it in my Activity, as when I e.g. rotate the phone the Dialog gets recreated and my reference would be invalid.
How do I get a reference to MyDialog later on in my code?
The second parameter to show() is the tag.
This tag is what allows you to use findFragmentByTag() later to retrieve that Fragment.
Therefore, just use any other value than null
diag.show(getSupportFragmentManager(), "dialog");
And then you can retrieve the fragment:
MyDialog diag = (MyDialog) getSupportFragmentManager().findFragmentByTag("dialog");
I am checking internet connection in my main activity.If connection is lost,I want to show reconnecting message in fragment.Example:If I run following code in main activity my app is crashing.
ConversationFragment conv1 = new ConversationFragment();
conv1.showReconnecting();
And this is the showReconnecting method in fragment:
public void showReconnecting() {
final RelativeLayout rel=(RelativeLayout)rootView.findViewById(R.id.reconnecting);
rel.setVisibility(View.VISIBLE);
}
I know why my app is crashing because rootView is setting in onCreateView and when I call this method from activity rootView is returning null.
What can I do for resolve this problem ?
Try this (Assuming reconnecting view is in fragment and your fragment is visible on screen),
public void showReconnecting() {
if (conv1 != null && conv1.getView()!=null) {
final RelativeLayout rel=(RelativeLayout)conv1.getView().findViewById(R.id.reconnecting);
rel.setVisibility(View.VISIBLE);
}
}
If conv1 is not available then please make it class variable.
According to what you want to do, a simple ProgressDialog will do the job. You can lauch it from your ChatFragment, like this:
First, declare it on your Fragment:
private ProgressDialog connectiongProgressDialog;
Then, when you want to show it, use:
connectiongProgressDialog = ProgressDialog.show(getActivity(), "My title", "Reconnecting");
When you want to dismiss it, use:
if (connectiongProgressDialog != null){
connectiongProgressDialog .dismiss();
}
It will display a simple dialog with the message you want.
Well, just looking at this and your explanation, I would think you can't call methods relating to a view (such as a fragment) without creating said fragment. An option, if the fragment is only used for showing the reconnecting, would be just to put some code in the activity and use a Toast.makeText(....).show();
which notifies the user that you are attempting to reconnect. So instead of conv1.showReconnecting(); maybe rather put, Toast.makeText(context,"Reconnecting", Toast.LONG).show(); and then do the necessary background work in an AsyncTask.
I hope this helps.
I want to launch a dialog with a custom layout, which I've implemented via a DialogFragment. (I basically just changed onCreateView() and added button handlers). The dialog lets the user quickly change an important setting.
This dialog will be launched from several different activities. The different activities don't have much in common, except that they need to refresh after the user makes a change to the setting. They don't need to get any information from the dialog; they merely need to know when it's closed (dismissed).
What I've Tried
I tried having the activity refresh in onResume(), but launching and dismissing a dialog never seems to call this method. (So I'm not sure why it even exists, but that's probably a topic for another question.)
Next, I tried adding a DialogInterface.OnDismissListener to the dialog:
public static void showMyDialog(OnDismissListener listener, Activity activity)
{
DialogFragment fragment = new MyDialogFragment();
fragment.show(activity.getFragmentManager(), "date");
activity.getFragmentManager().executePendingTransactions();//A
fragment.getDialog().setOnDismissListener(listener);//B
}
When I originally left out the line A, I got a NullPointerException on line B because the dialog is null at that point. Following the advice of this SO answer, I put in the call to executePendingTransaction(). This causes an IllegalStateException on line B, with the message "OnDismissListener is already taken by DialogFragment and cannot be replaced." I also tried putting setOnDismissListener() before the call to show(), but that always caused a NullPointerException.
I then read this other SO answer, which says the original asker was "calling getDialog() too early in the DialogFragment's life cycle." So I tried adding a constructor to my DialogFragment:
public MyDialogFragment(SomeCallback illTakeAnythingICanGet)
{
//I'll store the callback here and call it later
}
Unfortunately, adding a constructor made Android Lint freak out with a fatal warning, and when I looked it up, I found a comment in this question that seems to say this approach will make it impossible to deal with the user rotating the screen while the dialog is open.
The Question
How can an activity figure out when a DialogFragment has closed (been dismissed) in a way that won't break my app if the user rotates the screen? Should I be using something else besides a DialogFragment?
This is just a longer explanation of harism's comment in case anyone else has the same problem I did.
You can accomplish what I wanted by creating an interface like this:
public interface MyDialogCloseListener
{
public void handleDialogClose(DialogInterface dialog);//or whatever args you want
}
Have the activity that launches your dialog (DialogFragment) implement this interface. Then give that DialogFragment the following method:
public void onDismiss(DialogInterface dialog)
{
Activity activity = getActivity();
if(activity instanceof MyDialogCloseListener)
((MyDialogCloseListener)activity).handleDialogClose(dialog);
}
More explanatory code for someone to do the same.
Create the interface as:
package com.example.dialoglistener;
import android.content.DialogInterface;
public interface MyDialogCloseListener {
public void handleDialogClose(DialogInterface dialog);
}
Implement the interface in activity as:
MyDialogCloseListener closeListener = new MyDialogCloseListener() {
#Override
public void handleDialogClose(DialogInterface dialog) {
//do here whatever you want to do on Dialog dismiss
}
};
Write a DismissListener in DialogFragement as
public void DismissListener(MyDialogCloseListener closeListener) {
this.closeListener = closeListener;
}
call DismissListener from your activity as:
dialogFragementObject.DismissListener(closeListener);
and finally write onDismiss method
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if(closeListener != null) {
closeListener.handleDialogClose(null);
}
}
Tyler's example was the only example I could find that actually worked. The only thing that needs changed for the example to work is the call to the DismissListner method in the DialogFragment class. He has it as:
dialogFragementObject.DismissListner(closeListener);
This just needs to be a cast to whatever your class name of that DialogFragment is. For example:
((MyDialogFragment)dialogFragementObject).DismissListner(closeListener);
Im writing an Android application in which a user selection triggers a custom Dialog, from which a selection may trigger a second Dialog.
When showing the initial Dialog from the Activity class, I'm setting an onDismissListener on it to pull out user selections which works fine other in cases where the 2nd Dialog is not triggered. The issue that I'm having is that I can't figure out how to have the first one Dialog remain open until the 2nd one is dismissed, so that the information from both is sent back to the Activity class.
Hopefully some code will make this a little more clear:
MainActivity class where I am launching the initial CustomDialog:
customDialog = new CustomDialog(this);
customDialog.show();
customDialog.setOnDismissListener(new OnDismissListener(){
public void onDismiss(DialogInterface di){
slection = customDialog.getselection();
updateUI(); //updates a listview with the results
}
});
Within the CustumDialog class where I am launching the SecondDialog on top of it:
if(specify){
SecondDialog secondDialog = new SecondDialog(context);
secondDialog.show();
secondDialog.setOnDismissListener( new OnDissmissListener(){
public void onDismiss(DialogInterface di){
// this is where I want to call the CustomDialog's dismiss() method
// so that they both close at the same time and the data from here
// can be sent back to the MainActiivty through the CustomDialog's
// onDismissListener
}
});
}
dismiss();
So, to reiterate: I'm trying to prevent the CustomDialog's dismiss() method to be called until the SecondDialog is also dismissed. Is there a way that I can call it from the SecondDialog's OnDismissListener?
You should create customDialog as an instance level variable. You then it will be accessible with onDismiss(...) of second dialog. There you can call customDialog.dismiss();
// Instance level variable
private Dialog customDialog = null;
Instanciate your customDialog, then create second dialog from within your customDialog. Your Second dialog's code would look like this.
if(specify){
SecondDialog secondDialog = new SecondDialog(context);
secondDialog.show();
secondDialog.setOnDismissListener( new OnDissmissListener(){
public void onDismiss(DialogInterface di){
// customDialog is accessible as it is declared as instance level variable
MyClassName.this.customDialog.dismiss();
}
});
}
dismiss();
I prefer to save the data in 1st dialog before going to send one and when dismiss the 2nd dialog, open the 1st dialog again with saved data .. i used this way in my developing and its effective ..
In my activity I need a ProgressDialog with a horizontal progress bar to visualise the progress of a background task. To make the activity care for the dialog e.g. in case of screen rotation, I would like to use a managed dialog created in onCreateDialog. The problem is that I need to update the progress bar of the dialog after it has been created and therefor I need a reference to the managed progress dialog: Does anyone know how to retrieve a reference to a dialog created by onCreateDialog?
At the moment I am storing a reference to the dialog created in onCreateDialog, but that my fail with a InvalidArgumentException in the onFinished() method after the screen has been rotated (and the activity has been recreated):
public final class MyActivity extends Activity {
private static final int DIALOG_PROGRESS = 0;
private ProgressDialog progressDialog = null;
// [...]
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_PROGRESS:
progressDialog = createProgressDialog();
return progressDialog;
default:
return super.onCreateDialog(id);
}
}
// [...]
public void updateProgress(int progress) {
progressDialog.setProgress(0);
}
public void onFinished() {
progressDialog.dismiss();
}
// [...]
}
I would have expected something like a getDialog(int) method in the Activity class to get a reference to a managed dialog, but this doesn't seem to exist. Any ideas?
I answer myself:
There really is no getDialog(int) method available in the Activity class.
Storing the reference like shown above works correctly -- the bug was something else...
The problem was, that the parallel thread, that called the onFinished() method called this method on the already destroyed activity, thus the accessed ProgressDialog instance is still existing but no longer a valid dialog. Instead another activity with another ProgressDialog has already been created by Android.
So all I needed to do was to make the background thread call the onFinished() method of the new activity and everything works fine. To switch the reference I override the onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() methods of the Activity class.
The good thing of the shown example: Android really cares about recreating the new dialog after the screen orientation changed. So constructing the ProgressDialog that way is definitely easier than using ProgressDialog.show() where I would need to handle the dialog recreation on my own (the two methods described above would be a good place to do this.