How to cancel stacked toast from showing after changing fragment? - java

I want to remove stacked Android Toasts after the user goes to another Fragment. I have Fragments that are stacked and in every Fragment, I have two buttons which triggers different Toast message. When operations of a Fragment is done and the user navigates to another Fragment or press back button Toasts are kept showing. This mainly happens when the user clicks buttons too fast and force Toasts to stack.
Or when I instantiate global Toast objects and call cancel() than both of toasts stop from showing in that lifecycle of a fragment no matter how many times the user tap button.
toast1 = new Toast(getContext());
toast2 = new Toast(getContext());
showFirstToast(toast1).show();
showSecondToast(toast2).show();
private Toast showFirstToast(Toast toast){
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_layout_correct, (ViewGroup)
getActivity().findViewById(R.id.toast_layout));
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
return toast;
}

Do not use global Toast object instead you should use multiple instances of Toast. So, you can cancel it one by one.
toast1 = new Toast(getContext());
toast2 = new Toast(getContext());
showFirstToast(toast).show();
showSecondToast(toast).show();
toast1.cancel()

to avoid stacked toasts I reuse a single toast
Toast toast;
protected void showToast(final String text) {
if (toast == null)
toast = Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT);
else
toast.setText(text); // smoother transition than cancel + new toast
toast.show();
}
#Override
public void onPause() {
if(toast != null)
toast.cancel();
super.onPause();
}

Related

Closing a dialog window when a user selects an item from the list in android

I found a custom BlurDialog on github for android. It opens up a new dialog window with options and blurs the background of the rest of the screen. I have it working perfectly, but I am running into an issue where if I select an item in the options list, it will launch the correct activity, but then when I hit the back button I get back to the previous activity and the dialog window is still open. The only way to close it is by clicking outside the dialog window.
I am trying to find out how to close the dialog window before launching the new activity, so that when the user goes back to that screen the dialog window isn't open anymore. I am still new to android, so I am sure I am missing something extremely simple, I just can't figure it out. Here is the "onCreateDialog" method in my fragment that creates the blurred dialog window...
#Override
#NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_profile_dialog, null);
TextView text = (TextView) view.findViewById(R.id.follow_or_unfollow);
if(isSelf) {
text.setText("Edit Profile");
} else {
text.setText((isFollowing) ? "UnFollow" : "Follow");
}
RelativeLayout followButton = (RelativeLayout) view.findViewById(R.id.follow_layout);
RelativeLayout chatButton = (RelativeLayout) view.findViewById(R.id.chat_layout);
followButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//NEED TO CLOSE DIALOG WINDOW HERE
if(isSelf) {
//activate ProfileEditActivity
getActivity().startActivity(new Intent(getActivity(), EditProfileActivity.class));
} else {
Map<String, Object> updates = new HashMap<>();
if(isFollowing) {
//unfollow
updates.put("/following/" + user.getUid() + "/users/" + userID, null);
updates.put("/followers/" + userID + "/users/" + user.getUid(), null);
} else {
updates.put("/following/" + user.getUid() + "/users/" + userID, true);
updates.put("/followers/" + userID + "/users/" + user.getUid(), true);
//follow
}
database.getReference().updateChildren(updates);
getFragmentManager().beginTransaction().remove(ProfileDialogFragment.this).commit();
}
}
});
chatButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "Implement the start activity for chat", Toast.LENGTH_SHORT).show();
}
});
builder.setView(view);
return builder.create();
}
I have tried looking through the sample apps on the github page here Blurred Dialog Github
But it only shows how to activate the dialog, not how to actually close it when a user selects an item in the dialog. Everything else is working perfectly, if I click an item it launches the correct activity, and if I click outside the dialog the dialog closes. I just need to close it programmatically after a user clicks an item in the dialog. Thank you.
Instead of final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) create dialog using final AlertDialog builder = new AlertDialog.Builder(getActivity()).create() and show the dilaog after stting view like dialog.show().
Whenver user clicks something on the screen you can close the dialog using the dialog object like dialog.dismiss() i.e inside your follow button click
followButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss()
//YOUR CODE SHOULD COME HERE
}
});
According to the developer site https://developer.android.com/reference/android/app/DialogFragment.html
"Note that in this case the fragment is not placed on the back stack, it is just added as an indefinitely running fragment. Because dialogs normally are modal, this will still operate as a back stack, since the dialog will capture user input until it is dismissed. When it is dismissed, DialogFragment will take care of removing itself from its fragment manager."
Maybe if you call dismiss() it will work.
Public methods
void dismiss()
Dismiss the fragment and its dialog.

Refactored Android AlertDialogBuilder code to another class, style of the dialog breaks

I created two fairly long functions which create an AlertDialogBuilder which builds an AlertDialog which is populated and launched. The alert dialogs produced are fairly large for dialogs, so a lot of views need to be populated within the dialog. For the sake of cleanliness, testability, SRP etc. I decided to move these functions into a new class.
Originally the functions were placed directly in the Activity class, and the alert dialogs launched fine. I've now moved both to an AlertDialogLauncher class, which takes an Activity parameter when launched, most of the original code is the same, I've got the alert dialog working, but the colours of the text and background colours of some of my views are off.
So the dialog is launching fine, just with incorrect colours, so I imagine it is loading an incorrect style or something similar?
Code...
Original version (shortened)
private void addNormalRow(final ScannedWiFiNetwork network) {
TableRow row = (TableRow) View.inflate(this, R.layout.regular_network_table_row, null);
// loads of code
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
launchNewNetworkDialog(network);
}
});
}
private void launchPreferredNetworkDialog(final ScannedWiFiNetwork network) {
final AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("Connect to "+network.getSsid()+"?")
.setView(getLayoutInflater().inflate(R.layout.preferred_network_dialog,null))
.setCancelable(false)
.show();
final EditText passwordInput = (EditText) dialog.findViewById(R.id.edit_text_password);
TextView passwordText = (TextView) dialog.findViewById(R.id.dialog_password);
//loads of code
}
Essentially, the launch dialog function is called and creates a new AlertDialog by passing the AlertDialog.Builder a reference to this (the Java class for my activity).
Refactored Activity/Interface class
private void addNormalRow(final ScannedWiFiNetwork network) {
TableRow row = (TableRow) View.inflate(this, R.layout.regular_network_table_row, null);
//loads of code
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Activity activity = (Activity) v.getContext();
dialogs.launchNewNetworkDialog(network, activity);
}
});
}
New AlertDialogLauncher class
public void launchPreferredNetworkDialog(final ScannedWiFiNetwork network, final Activity activity) {
Context con = activity.getApplicationContext();
LayoutInflater layoutInflater = LayoutInflater.from(con);
final AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle("Connect to "+network.getSsid()+"?")
.setView((layoutInflater.inflate(R.layout.preferred_network_dialog,null)))
.setCancelable(false)
.show();
As you can see, in this new class an Activity must be passed in to be used to create the layout inflater and context objects used later on to populate the views. All this works fine, however as mentioned earlier, the text colours change and the background of the buttons.
I'm loading the same xml layout file, so I'd assume it is loading an incorrect or default style somehow when I provide it with a default activity object (retrieved from calling getContext on the button view added to the dialog).
I've tried replacing 'activity' with NetworkListActivity.this (my activity name), that compiles but gives me the same ruined style outcome.
Thanks in advance for any help. Hope the question is clear!
Figured out my problem.. I never applied a style to my dialog xml layout file, some of the text views which I did not assign explicit text colors two are defaulting to the style of the dialog, I found this out when experimenting with changing the style which can be done by adding R.style.STYLE_NAME to the AlertDialogBuilder constructor (after the 'activity' parameter).
So yeah, I just didn't apply a style and need to be careful with views I haven't applied a style to!

stopping toast android in other actvity

my problem is this:
I make a toast "welcome" in the Activity Main for the first time that you open the home, and it's ok,but when another page to return to the home via the back button, how can I make the toast "welcome" does not appear anymore?
the code of main activity is:
public class MyActivity extends Activity {
/**
* Called when the activity is first created.
*/
MyActivity actvi1;
int cont=0;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnabout=(Button)findViewById(R.id.about);
//click
btnabout.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// definisco l'intenzione di aprire l'Activity "aboutme.java"
Intent aboutmejava= new Intent(MyActivity.this,aboutme.class);
startActivity(aboutmejava);
}
}
);
//toast
Toast toast = Toast.makeText(getApplicationContext(),
"Welcome", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_HORIZONTAL, 20, 0);
toast.show();
code of aboutme.java
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.aboutme);
Button btnback=(Button)findViewById(R.id.scritta);
btnback.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Intent main = new Intent(aboutme.this,MyActivity.class);
startActivity(main);
If you want it to only show the very first time the application runs, put a boolean flag in SharedPreferences and check here. There are tons of examples but here is one
If you want it to show *every time the Activity is first run when the app starts, simply replace your onClick() code with onBackPressed(). This way it won't start a new instance of your MyActivity and since the Toast code is in onCreate() and not onResume(), it won't run when you go back by clicking the back button.
SharedPreferences
This works.
SharedPreferences sp = getPreferences(Context.MODE_PRIVATE);
int show = sp.getInt("firstlaunch", 0);
if(show == 0) {
Toast.makeText(getApplicationContext(), "WELCOME", Toast.LENGTH_LONG).show();
sp.edit().putInt("firstlaunch", 1).apply();
}
Place it in your home activities onCreate method.'
A shared preference is a "setting" of sort. It's a xml file that is loaded which contains all of your settings. When we first run "sp.getInt" you can see that i have a 0 after the "key - fistlaunch". The 0 is specifying what to give our Int SHOW if it can't find any shared preference with that key. Next if the int show is equal to 0 we run our Toast and then change the shared preference value to 1 so next time you run it doesn't show...
boolean b = false;
if(!b) {
Toast toast = Toast.makeText(getApplicationContext(),
"Welcome", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_HORIZONTAL, 20, 0);
toast.show();
b = true
}
kind of like that?
Are you another instance of MainActivity?
In order to return to your Main activity you should send an Intent with the flag FLAG_ACTIVITY_CLEAR_TOP (or set android:launchMode="singleTop" in launchMode in AndroidManifest.xml)
Intent main = new Intent(aboutme.this,MyActivity.class);
main.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(main);
By doing so, your main activity will be restored, instead of creating a new instance of MainActivity

how to keep my popup window on orientation change?

I have a popup window in my activity.
Whenever I change the screen orientation to landscape, the popup disappears.
Why is that, and how can I keep the popup visible?
try below code:-
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
Log.i("orientation", "Orientation changed to: Landscape");
else
Log.i("orientation", "Orientation changed to: Portrait");
}
see below link for more info:-
How to keep Popup window opened when orientation changes at run time in Android?
When orientation changes the activity will restart.. So normally the popup window calls again.. In any case if it gone try to call it within onCreate.
Or check the orientation change and take necessary recalls.
if(getResources().getConfiguration().orientation == getResources()
.getConfiguration().ORIENTATION_LANDSCAPE){
// put some flag
}else if(getResources().getConfiguration().orientation != getResources()
.getConfiguration().ORIENTATION_PORTRAIT) {
// change the flag
}
If you put your code fragments may I can help you
You need to use managed Dialogs. Rather than
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.rule_edit_choose_action));
builder.setAdapter(new ArrayAdapter(this, R.array.dummyValues), null);
builder.show();
you should use something like
myActivity.showDialog(0);
and then implement onCreateDialog() in your Activity. Your activity will then manage the dialog and re-show it when you re-orientate and it's closed. If you need to change your dialog every time it is shown, implement onPrepareDialog() also - the Activity will give you access to the Dialog just before it is shown so you can update it (with a custom message, for instance).
There's lots of info here:
http://developer.android.com/guide/topics/ui/dialogs.html
As #Ciril said, your issue is that your Activity is restarted when you re-orientate. You could always fix your activity orientation to portrait or landscape if that is suitable for your app. That would prevent it from restarting.
most likely you use AlertDialog for your popups, something along the lines of:
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.popup_title);
builder.setMessage(R.string.popup_message);
builder.setPositiveButton(R.string.yes, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// do something
}
});
builder.show();
this is bad, because your Activity has no idea there's a popup dialog, and when you change screen orientation, the Activity is restarted with the new parameters, and your popup is gone.
to avoid this you'd better use ShowDialog() to display your popups. to make it work, you need to override onCreateDialog() :
// Called to create a dialog to be shown.
#Override
protected Dialog onCreateDialog(int id, Bundle bundle) {
switch (id) {
case NEW_DIALOG :
return new AlertDialog.Builder(this)
.setTitle(R.string.popup_title)
.setMessage(R.string.popup_message)
.setPositiveButton(android.R.string.ok, null)
.create();
default:
return null;
}
}
then you'd better override onPrepareDialog() (this is not required, actually):
// If a dialog has already been created, this is called
// to reset the dialog before showing it a 2nd time. Optional.
#Override
protected void onPrepareDialog(int id, Dialog dialog, final Bundle bundle) {
AlertDialog dlg = (AlertDialog) dialog;
switch (id) {
case NEW_DIALOG :
dlg.SetTitle("popup title");
// and maybe something else
}
}
after all preparations you may call ShowDialog(NEW_DIALOG) and you Activity will remember it has a popup laid over on the top, and will recreate it after the orientation change.

Android popup style activity which sits on top of any other apps

What I want to create is a popup style application.
I have a service in the background - something arrives on the queue and i want an activity to start to inform the user - very very similar to the functionality of SMSPopup app.
So I have the code where something arrives on the queue and it calls my activity.
However for some reason the activity always shows on top of the originally started activity instead of just appearing on the main desktop of the android device.
As an example:
I have the main activity which is shown when the application is run
I have the service which checks queue
I have a popup activity.
When i start the main activity it starts the service - I can now close this.
I then have something on the queue and it creates the popup activity which launches the main activity with the popup on top of it :S How do I stop this and have it behave as i want...
The popup class is :
public class SMSPopup extends Activity implements OnClickListener{
public static String msg;
#Override
public void onCreate(Bundle bundle){
super.onCreate(bundle);
// Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
this.setContentView(R.layout.popup);
TextView tv = (TextView)findViewById(R.id.txtLbl);
Intent intent = getIntent();
if (intent != null){
Bundle bb = intent.getExtras();
if (bb != null){
msg = bb.getString("com.andy.tabletsms.message");
}
}
if(msg == null){
msg = "LOLOLOL";
}
tv.setText(msg);
Button b = (Button)findViewById(R.id.closeBtn);
b.setOnClickListener(this);
}
#Override
public void onClick(View v) {
this.finish();
}
}
and I call the activity from a broadcast receiver which checks the queue every 30 seconds or so :
if(main.msgs.size()>0){
Intent testActivityIntent = new Intent(context.getApplicationContext(), com.andy.tabletsms.work.SMSPopup.class);
testActivityIntent.putExtra("com.andy.tabletsms.message", main.msgs.get(0));
testActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(testActivityIntent);
}
The layout is here : http://pastebin.com/F25u6wdM
This is against the design practice suggested by Android. See http://developer.android.com/guide/topics/ui/notifiers/notifications.html
A background Service should never launch an Activity on its own in order to receive user interaction.
You could show the message in a Toast and/or notification. From the notification, you could start a new intent.

Categories

Resources