/**
* Copyright 2014 John Persano
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.github.johnpersano.supertoasts;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.*;
import java.util.Iterator;
import java.util.LinkedList;
/**
* Manages the life of a SuperActivityToast. Initial code derived from the Crouton library.
*/
class ManagerSuperActivityToast extends Handler {
@SuppressWarnings("UnusedDeclaration")
private static final String TAG = "ManagerSuperActivityToast";
/* Potential messages for the handler to send **/
private static final class Messages {
/* Hexadecimal numbers that represent acronyms for the operation. **/
private static final int DISPLAY = 0x44534154;
private static final int REMOVE = 0x52534154;
}
private static ManagerSuperActivityToast mManagerSuperActivityToast;
private final LinkedList<SuperActivityToast> mList;
/* Private method to create a new list if the manager is being initialized */
private ManagerSuperActivityToast() {
mList = new LinkedList<SuperActivityToast>();
}
/**
* Singleton method to ensure all SuperActivityToasts are passed through the same manager.
*/
protected static synchronized ManagerSuperActivityToast getInstance() {
if (mManagerSuperActivityToast != null) {
return mManagerSuperActivityToast;
} else {
mManagerSuperActivityToast = new ManagerSuperActivityToast();
return mManagerSuperActivityToast;
}
}
/**
* Add a SuperActivityToast to the list. Will show immediately if no other SuperActivityToasts
* are in the list.
*/
void add(SuperActivityToast superActivityToast) {
mList.add(superActivityToast);
this.showNextSuperToast();
}
/**
* Shows the next SuperActivityToast in the list. Called by add() and when the dismiss animation
* of a previously showing SuperActivityToast ends.
*/
private void showNextSuperToast() {
final SuperActivityToast superActivityToast = mList.peek();
if (mList.isEmpty() || superActivityToast.getActivity() == null) {
return;
}
if (!superActivityToast.isShowing()) {
final Message message = obtainMessage(Messages.DISPLAY);
message.obj = superActivityToast;
sendMessage(message);
}
}
@Override
public void handleMessage(Message message) {
final SuperActivityToast superActivityToast = (SuperActivityToast)
message.obj;
switch (message.what) {
case Messages.DISPLAY:
displaySuperToast(superActivityToast);
break;
case Messages.REMOVE:
removeSuperToast(superActivityToast);
break;
default: {
super.handleMessage(message);
break;
}
}
}
/**
* Displays a SuperActivityToast.
*/
private void displaySuperToast(SuperActivityToast superActivityToast) {
/* If this SuperActivityToast is somehow already showing do nothing */
if(superActivityToast.isShowing()) {
return;
}
final ViewGroup viewGroup = superActivityToast.getViewGroup();
final View toastView = superActivityToast.getView();
if(viewGroup != null) {
try {
viewGroup.addView(toastView);
if(!superActivityToast.getShowImmediate()) {
toastView.startAnimation(getShowAnimation(superActivityToast));
}
} catch(IllegalStateException e) {
this.cancelAllSuperActivityToastsForActivity(superActivityToast.getActivity());
}
}
/* Dismiss the SuperActivityToast at the set duration time unless indeterminate */
if(!superActivityToast.isIndeterminate()) {
Message message = obtainMessage(Messages.REMOVE);
message.obj = superActivityToast;
sendMessageDelayed(message, superActivityToast.getDuration() +
getShowAnimation(superActivityToast).getDuration());
}
}
/**
* Hide and remove the SuperActivityToast
*/
void removeSuperToast(final SuperActivityToast superActivityToast) {
/* If SuperActivityToast has been dismissed before it shows, do not attempt to show it */
if(!superActivityToast.isShowing()) {
mList.remove(superActivityToast);
return;
}
/* If being called somewhere else get rid of delayed remove message */
removeMessages(Messages.REMOVE, superActivityToast);
final ViewGroup viewGroup = superActivityToast.getViewGroup();
final View toastView = superActivityToast.getView();
if (viewGroup != null) {
Animation animation = getDismissAnimation(superActivityToast);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
/* Do nothing */
}
@Override
public void onAnimationEnd(Animation animation) {
if(superActivityToast.getOnDismissWrapper() != null){
superActivityToast.getOnDismissWrapper().onDismiss(superActivityToast.getView());
}
/* Show the SuperActivityToast next in the list if any exist */
ManagerSuperActivityToast.this.showNextSuperToast();
}
@Override
public void onAnimationRepeat(Animation animation) {
/* Do nothing */
}
});
toastView.startAnimation(animation);
viewGroup.removeView(toastView);
mList.poll();
}
}
/**
* Removes all SuperActivityToasts and clears the list
*/
void cancelAllSuperActivityToasts() {
removeMessages(Messages.DISPLAY);
removeMessages(Messages.REMOVE);
for (SuperActivityToast superActivityToast : mList) {
if (superActivityToast.isShowing()) {
superActivityToast.getViewGroup().removeView(
superActivityToast.getView());
superActivityToast.getViewGroup().invalidate();
}
}
mList.clear();
}
/**
* Removes all SuperActivityToasts and clears the list for a specific activity
*/
void cancelAllSuperActivityToastsForActivity(Activity activity) {
Iterator<SuperActivityToast> superActivityToastIterator = mList
.iterator();
while (superActivityToastIterator.hasNext()) {
SuperActivityToast superActivityToast = superActivityToastIterator
.next();
if ((superActivityToast.getActivity()) != null
&& superActivityToast.getActivity().equals(activity)) {
if (superActivityToast.isShowing()) {
superActivityToast.getViewGroup().removeView(
superActivityToast.getView());
}
removeMessages(Messages.DISPLAY, superActivityToast);
removeMessages(Messages.REMOVE, superActivityToast);
superActivityToastIterator.remove();
}
}
}
/**
* Used in SuperActivityToast saveState().
*/
LinkedList<SuperActivityToast> getList(){
return mList;
}
/**
* Returns an animation based on the {@link com.github.johnpersano.supertoasts.SuperToast.Animations} enums
*/
private Animation getShowAnimation(SuperActivityToast superActivityToast) {
if (superActivityToast.getAnimations() == SuperToast.Animations.FLYIN) {
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.75f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setDuration(250);
return animationSet;
} else if (superActivityToast.getAnimations() == SuperToast.Animations.SCALE) {
ScaleAnimation scaleAnimation = new ScaleAnimation(0.9f, 1.0f, 0.9f, 1.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setDuration(250);
return animationSet;
} else if (superActivityToast.getAnimations() == SuperToast.Animations.POPUP) {
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.1f, Animation.RELATIVE_TO_SELF, 0.0f);
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setDuration(250);
return animationSet;
} else {
Animation animation= new AlphaAnimation(0f, 1f);
animation.setDuration(500);
animation.setInterpolator(new DecelerateInterpolator());
return animation;
}
}
/**
* Returns an animation based on the {@link com.github.johnpersano.supertoasts.SuperToast.Animations} enums
*/
private Animation getDismissAnimation(SuperActivityToast superActivityToast) {
if (superActivityToast.getAnimations() == SuperToast.Animations.FLYIN) {
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, .75f,
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setInterpolator(new AccelerateInterpolator());
animationSet.setDuration(250);
return animationSet;
} else if (superActivityToast.getAnimations() == SuperToast.Animations.SCALE) {
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.9f, 1.0f, 0.9f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setDuration(250);
return animationSet;
} else if (superActivityToast.getAnimations() == SuperToast.Animations.POPUP) {
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.1f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setDuration(250);
return animationSet;
} else {
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f);
alphaAnimation.setDuration(500);
alphaAnimation.setInterpolator(new AccelerateInterpolator());
return alphaAnimation;
}
}
}