package com.hupu.games.livegift.animation;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import com.hupu.games.R;
import com.nineoldandroids.animation.Animator;
@SuppressLint("NewApi")
public class AnimationTool {
private LruCache<Integer, Bitmap> lruCache = new LruCache<Integer, Bitmap>(
8192 / 4);
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AnimationTool#" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(
10);
private static ThreadPoolExecutor fixThreadPool;
// = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT,
// 20, TimeUnit.MILLISECONDS, sPoolWorkQueue, sThreadFactory,
// new ThreadPoolExecutor.DiscardPolicy());
// (ThreadPoolExecutor) Executors
// .newFixedThreadPool(THREAD_COUNT, sThreadFactory);
public final static int[] res = { R.drawable.bubble1, R.drawable.bubble2,
R.drawable.bubble3, R.drawable.bubble4, R.drawable.bubble5,
R.drawable.bubble6, R.drawable.bubble7, R.drawable.boom1,
R.drawable.boom2, R.drawable.boom3, R.drawable.boom3_1,
R.drawable.boom4, R.drawable.boom4_1, R.drawable.boom5,
R.drawable.boom5_1, R.drawable.boom6, R.drawable.boom6_1,
R.drawable.boom7, R.drawable.boom8, R.drawable.boom9,
R.drawable.boom10, R.drawable.boom11, R.drawable.boom12, };
private final static int MSG_CHANGE_FRAME = 0;
private final static int MSG_FRAME_COMPLETED = 3;
private final static int MSG_START_HALF_TEXT_ANIMATION = 1;
private final static int MSG_START_END_TEXT_ANIMATION = 2;
private static int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private int THREAD_COUNT;
/** 图片每帧时间 */
private static final int IMG_FRAME_DURATION = 41;
private static final int TEXT_SHOW_FRAME_INDEX = 5;
/** 文字等待多少ms开始动画 */
private static final int TEXT_SHOW_WAIT_TIME = 400;
/** 文字动画中间停顿多少ms */
private static final int TEXT_SHOW_END_TIME = 200;
/** 文字动画前半段总共显示的时间 */
private static final int TEXT_SHOW_HALF_DURATION = 700;
/** 文字动画后半段总共显示的时间 */
private static final int TEXT_SHOW_END_DURATION = 500;
/** 数字动画总共显示的时间 */
private static final int NUMBER_SHOW_DURATION = 700;
/** 默认显示的文字 */
private static final String DEFAULT_TEXT = "哈";
protected static final String TAG = AnimationTool.class.getSimpleName();
/** 要显示的文字 */
private String animationText = DEFAULT_TEXT;
/** 同时显示的动画最大数 */
private int maxAnimationNum = CPU_COUNT*3+3;
private FrameLayout frameLayout;
/** 屏幕宽度 */
private int w;
/** 屏幕高度 */
private int h;
/** 所显示动画activity */
private Activity activity;
private boolean isDestroyed = false;
private int textLayoutId;
private ViewGroup numTextViewGroup;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_CHANGE_FRAME:
ImageView iv = (ImageView) msg.obj;
if (iv != null) {
Bitmap bitmap = msg.getData().getParcelable("bitmap");
if (bitmap != null)
iv.setImageBitmap(bitmap);
}
break;
case MSG_FRAME_COMPLETED:
iv = (ImageView) msg.obj;
iv.setImageResource(0);
if(frameLayout!=null){
synchronized (frameLayout) {
frameLayout.removeView(iv);
}
}
break;
case MSG_START_HALF_TEXT_ANIMATION:
startTextViewHalfAnimation((ViewGroup) msg.obj);
break;
case MSG_START_END_TEXT_ANIMATION:
startTextViewEndAnimation((ViewGroup) msg.obj);
break;
default:
break;
}
};
};
/**
*
* @param activity
* @param textLayoutId
* 承载数字textview的framelayout布局
*/
public AnimationTool(Activity activity, int textLayoutId) {
initAnimationTool(activity, textLayoutId);
}
public void initAnimationTool(Activity activity, int textLayoutId) {
this.activity = activity;
Log.i(TAG, "cpu count=" + CPU_COUNT);
THREAD_COUNT = maxAnimationNum;
isDestroyed = false;
Display mDisplay = activity.getWindowManager().getDefaultDisplay();
DisplayMetrics realDisplay = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mDisplay.getRealMetrics(realDisplay);
} else {
mDisplay.getMetrics(realDisplay);
}
w = realDisplay.widthPixels;
h = realDisplay.heightPixels;
frameLayout = new FrameLayout(activity);
activity.addContentView(frameLayout, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
if (fixThreadPool == null || fixThreadPool.isShutdown()) {
fixThreadPool = new ThreadPoolExecutor(THREAD_COUNT,
THREAD_COUNT * 2, 1, TimeUnit.MILLISECONDS, sPoolWorkQueue,
sThreadFactory, new ThreadPoolExecutor.DiscardPolicy());
// (ThreadPoolExecutor)
// Executors.newCachedThreadPool(sThreadFactory);
//
// Executors.newFixedThreadPool(
// THREAD_COUNT, sThreadFactory);
}
// numTextViewGroup = (ViewGroup) activity.findViewById(textLayoutId);
}
/**
* 显示动画
*
* @param num显示数字的值
*
*/
public void showAnimation(String animationText, int color) {
// HupuLog.e("showAnimation", animationText);
Log.i(TAG, "showAnimation animationText=" + animationText);
if (frameLayout != null) {
synchronized (frameLayout) {
if (frameLayout.getChildCount() < maxAnimationNum) {
ViewGroup viewGroup = addViews(animationText, color);
if (viewGroup != null) {
// ImageView iv = (ImageView) viewGroup.getChildAt(0);
// TextView tv = (TextView) viewGroup.getChildAt(1);
startFrameAnimation(viewGroup);
// startClockTask(viewGroup);
}
}
// startNumberTextAnimation(num);
}
}
}
// public void showAnimation(String animText) {
// setAnimationText(animText);
// showAnimation(animText);
//
// }
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
@SuppressLint("NewApi")
private Bitmap loadBitmapFromRes(final Context context, final int resId) {
Bitmap bitmap = null;
bitmap = lruCache.get(resId);
if (bitmap != null) {
return bitmap;
}
InputStream stream = null;
try {
BitmapFactory.Options o = null;
o = new BitmapFactory.Options();
o.inPurgeable = true;
o.inInputShareable = true;
o.inPreferredConfig = Bitmap.Config.ARGB_8888;
o.inSampleSize = 2;
stream = activity.getResources().openRawResource(resId);
bitmap = BitmapFactory.decodeStream(stream, null, o);
// Log.i(TAG,String.format("Loaded bitmap (%dx%d).",
// bitmap.getWidth(),
// bitmap.getHeight()));
if (bitmap != null)
lruCache.put(resId, bitmap);
return bitmap;
} catch (final Exception e) {
return null;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.w(TAG, "Failed to close FileInputStream", e);
}
}
}
}
/**
* 启动帧动画
*
* @param iv
* @param position
*/
public void startFrameAnimation(final ViewGroup viewGroup) {
if (handler != null) {
final ImageView iv = (ImageView) viewGroup.getChildAt(0);
if (iv != null) {
fixThreadPool.execute(new Runnable() {
long start;
long end;
@Override
public void run() {
// HupuLog.e("AnimationTool",
// "startFrameAnimation run");
// TODO Auto-generated method stub
int position = 0;
while (!isDestroyed && position <= res.length - 1) {
iv.setDrawingCacheEnabled(false);
start = System.currentTimeMillis();
Bitmap bitmap = loadBitmapFromRes(activity,
res[position]);
// Log.i(TAG, "图片获取时间:"
// + (System.currentTimeMillis() - start));
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
if (handler != null) {
Message msg = handler
.obtainMessage(MSG_CHANGE_FRAME);
msg.obj = iv;
msg.setData(bundle);
msg.sendToTarget();
if (position == TEXT_SHOW_FRAME_INDEX) {
msg = handler
.obtainMessage(MSG_START_HALF_TEXT_ANIMATION);
msg.obj = viewGroup;
msg.sendToTarget();
}
} else {
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
bundle.clear();
}
try {
Thread.currentThread()
.sleep(IMG_FRAME_DURATION);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
} finally {
// System.gc();
position++;
}
}
if (handler != null) {
iv.setDrawingCacheEnabled(false);
Message msg = handler
.obtainMessage(MSG_FRAME_COMPLETED);
msg.obj = iv;
msg.sendToTarget();
}
}
});
}
}
// handler.postDelayed(new Runnable() {
// @Override
// public void run() {
// // TODO Auto-generated method stub
// if (position <= res.length - 1) {
// iv.setImageResource(res[position]);
// startFrameAnimation(iv, position + 1);
// }
// }
// }, IMG_FRAME_DURATION);
// }
}
/**
* 添加动画布局
*
* @param activity
* @return
*/
public ViewGroup addViews(String animationText, int textColor) {
if (frameLayout != null) {
synchronized (frameLayout) {
// HupuLog.e("AnimationTool", "addViews");
FrameLayout flAnimation = new FrameLayout(activity);
// 图片
ImageView iv = new ImageView(activity);
iv.setScaleType(ScaleType.FIT_XY);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
// lp.gravity = Gravity.CENTER_HORIZONTAL
// | Gravity.CENTER_VERTICAL;
// iv.setLayoutParams(lp);
TextView tv = new TextView(activity);
LayoutParams tvLp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
int size = 0;
if (isChinese(animationText)) {
if (animationText.length() == 3)
size = 3;
else {
size = 2;
}
int textSize = w / 2;
tvLp.topMargin = (341 - textSize / 2) * h / 1037;
if (animationText.length() == 3) {
textSize = w / 3;
tvLp.topMargin = (int) ((341 - textSize / 2.0) * h / 1037);
} else if (animationText.length() == 4) {
textSize = w / 4;
tvLp.topMargin = (int) ((341 - textSize) * h / 1037);
}
Log.i(TAG, "defaultMagin=" + tvLp.topMargin);
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
} else {
size = 4;
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, w / 4);
if (animationText.length() <= 4)
tvLp.topMargin = 180;
else
tvLp.topMargin = 130;
}
if (animationText.length() >= size) {
int type = animationText.length() / size;
int type2 = animationText.length() % size;
StringBuffer temp = new StringBuffer();
for (int i = 0; i <= type - 1; i++) {
temp.append(animationText.substring(i * size, i * size
+ size));
if (i != type - 1 || type2 > 0)
temp.append("\n");
}
if (type2 > 0) {
temp.append(animationText.substring(
animationText.length() - type2,
animationText.length()));
}
animationText = temp.toString();
}
tv.setText(animationText);
tv.setTextColor(activity.getResources().getColor(textColor));
tv.setVisibility(View.INVISIBLE);
tv.setGravity(Gravity.CENTER);
// 添加View
flAnimation.addView(iv, lp);
flAnimation.addView(tv, tvLp);
frameLayout.addView(flAnimation, LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
return flAnimation;
}
}
return null;
}
/**
* 等待。。时间后显示文字动画
*
* @param viewGroup
*/
public void startClockTask(final ViewGroup viewGroup) {
// handler.postDelayed(new Runnable() {
//
// @Override
// public void run() {
// // TODO Auto-generated method stub
// startTextViewHalfAnimation(viewGroup);
// }
// }, TEXT_SHOW_WAIT_TIME);
fixThreadPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
boolean isBreak = false;
try {
Thread.currentThread().sleep(TEXT_SHOW_WAIT_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
isBreak = true;
}
if (!isBreak) {
Message msg = handler
.obtainMessage(MSG_START_HALF_TEXT_ANIMATION);
msg.obj = viewGroup;
msg.sendToTarget();
}
}
});
}
/**
* 显示文字前半段动画
*
* @param viewGroup
*/
public void startTextViewHalfAnimation(final ViewGroup viewGroup) {
final TextView tv = (TextView) viewGroup.getChildAt(1);
HalfScalAnimator halfScalAnimator = new HalfScalAnimator();
halfScalAnimator.setDuration(TEXT_SHOW_HALF_DURATION);
halfScalAnimator.addAnimatorListener(new SimpleAnimationListener() {
@Override
public void onAnimationStart(Animator arg0) {
// TODO Auto-generated method stub
super.onAnimationStart(arg0);
tv.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator arg0) {
// TODO Auto-generated method stub
super.onAnimationEnd(arg0);
if (handler != null) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
startTextViewEndAnimation(viewGroup);
}
}, TEXT_SHOW_END_TIME);
}
}
});
halfScalAnimator.animate(tv);
}
/**
* 显示结尾动画并移除动画布局
*
* @param viewGroup
*/
public void startTextViewEndAnimation(final ViewGroup viewGroup) {
final TextView tv = (TextView) viewGroup.getChildAt(1);
final ImageView iv = (ImageView) viewGroup.getChildAt(0);
EndScalAnimator endScalAnimator = new EndScalAnimator();
endScalAnimator.setDuration(TEXT_SHOW_END_DURATION);
endScalAnimator.addAnimatorListener(new SimpleAnimationListener() {
@Override
public void onAnimationEnd(Animator arg0) {
// TODO Auto-generated method stub
super.onAnimationEnd(arg0);
if (frameLayout != null) {
synchronized (frameLayout) {
// iv.getDrawable().setCallback(null);
viewGroup.removeAllViews();
frameLayout.removeView(viewGroup);
}
}
}
});
endScalAnimator.animate(tv);
}
/**
* 显示数字动画
*
* @param num
* 显示的数字的值
*/
public void startNumberTextAnimation(int num) {
final TextView tv = new TextView(activity);
tv.setText(num + "");
tv.setTextSize(60);
LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.RIGHT;
tv.setLayoutParams(layoutParams);
tv.setGravity(Gravity.RIGHT);
if (numTextViewGroup != null) {
synchronized (numTextViewGroup) {
numTextViewGroup.addView(tv);
NumAnimator numAnimator = new NumAnimator();
numAnimator.setDuration(NUMBER_SHOW_DURATION);
numAnimator.addAnimatorListener(new SimpleAnimationListener() {
@Override
public void onAnimationEnd(Animator arg0) {
// TODO Auto-generated method stub
super.onAnimationEnd(arg0);
synchronized (numTextViewGroup) {
numTextViewGroup.removeView(tv);
}
}
});
numAnimator.animate(tv);
}
}
}
/**
* 设置显示的文字
*
* @param text
*/
public void setAnimationText(String text) {
this.animationText = text;
}
/**
* 设置同时显示动画的最大数量
*
* @param maxNum
*/
public void setMaxAnimationNum(int maxNum) {
this.maxAnimationNum = maxNum;
}
public void destroy() {
isDestroyed = true;
if (fixThreadPool != null) {
fixThreadPool.shutdown();
}
fixThreadPool = null;
frameLayout = null;
numTextViewGroup = null;
activity = null;
handler = null;
}
/**
* 描述:是否是中文.
*
* @param str
* 指定的字符串
* @return 是否是中文:是为true,否则false
*/
public static Boolean isChinese(String str) {
Boolean isChinese = true;
String chinese = "[\u0391-\uFFE5]";
if (str != null && !str.equals("")) {
// 获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1
for (int i = 0; i < str.length(); i++) {
// 获取一个字符
String temp = str.substring(i, i + 1);
// 判断是否为中文字符
if (temp.matches(chinese)) {
} else {
isChinese = false;
}
}
}
return isChinese;
}
}