package com.tencent.tws.assistant.widget;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import com.tencent.tws.sharelib.R;
public class SidebarHubbleView extends View {
public static String TAG = "SidebarHubbleView";
public final int hubble_in_per_frame = getResources().getInteger(R.integer.hubble_in_per_frame);
public final int hubble_out_per_frame = getResources().getInteger(R.integer.hubble_out_per_frame);
public static int IN_FRAME_COUNT = 10;
public static int OUT_FRAME_COUNT = 8;
private Paint mPaint = new Paint();
private Paint mNonExistPaint = new Paint();
private final int fPaintSize = (int) getResources().getDimension(R.dimen.hubble_text_size);
private LevelListDrawable mHubbleInDrawable;
private LevelListDrawable mHubbleOutDrawable;
private Drawable mHubbleLeft;
private Drawable mHubbleRight;
public final int NORMAL_SHOW = 0;
public final int IN_ANIMA = 1;
public final int OUT_ANIMA = 2;
private int mStatus = NORMAL_SHOW;
private ValueAnimator mAnimator;
private String mText = null;
private float offsetX = 0;
private float offsetY = 0;
// 0~7
private final int ANIMA_IN_END_LEVEL = 7;
// 3~7
private final int ANIMA_OUT_BEGIN_LEVEL = 3;
public final int PAINT_FLAGS = Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG;
private final int offsetX_NORMAL = (int) getResources().getDimension(R.dimen.hubble_offsetx_in_10);
private final int fSideBarHubbleViewHigh = (int) getResources().getDimension(R.dimen.sidbar_hubble_h);
private final int fHubbleViewChassisWith = (int) getResources().getDimension(R.dimen.sidbar_hubble_chassis_w);
private final int fHubbleViewLeftWith = (int) getResources().getDimension(R.dimen.sidbar_hubble_left_w);
private final int fHubbleViewRightWith = (int) getResources().getDimension(R.dimen.sidbar_hubble_right_w);
private final int fHubbleViewZoomX = (int) getResources().getDimension(R.dimen.sidbar_hubble_zoom_x);
private final int fHubbleViewHigh = (int) getResources().getDimension(R.dimen.hubble_high);
//save the pos x-zoom
private final int[] offsetX_IN = { (int) getResources().getDimension(R.dimen.hubble_offsetx_in_1), (int) getResources().getDimension(R.dimen.hubble_offsetx_in_2),
(int) getResources().getDimension(R.dimen.hubble_offsetx_in_3), (int) getResources().getDimension(R.dimen.hubble_offsetx_in_4),
(int) getResources().getDimension(R.dimen.hubble_offsetx_in_5), (int) getResources().getDimension(R.dimen.hubble_offsetx_in_6),
(int) getResources().getDimension(R.dimen.hubble_offsetx_in_7), (int) getResources().getDimension(R.dimen.hubble_offsetx_in_8),
(int) getResources().getDimension(R.dimen.hubble_offsetx_in_9), offsetX_NORMAL, };
private final float[] scaling_IN = { 0.606f, 0.606f, 0.67f, 0.777f, 0.85f, 0.896f, 0.956f, 0.956f, 0.978f, 1.00f, };
private final int[] offsetX_OUT = { (int) getResources().getDimension(R.dimen.hubble_offsetx_out_1), (int) getResources().getDimension(R.dimen.hubble_offsetx_out_2),
(int) getResources().getDimension(R.dimen.hubble_offsetx_out_3), (int) getResources().getDimension(R.dimen.hubble_offsetx_out_4),
(int) getResources().getDimension(R.dimen.hubble_offsetx_out_5), (int) getResources().getDimension(R.dimen.hubble_offsetx_out_6),
(int) getResources().getDimension(R.dimen.hubble_offsetx_out_7), (int) getResources().getDimension(R.dimen.hubble_offsetx_out_8), };
private final float[] scaling_OUT = { 1.00f, 0.97f, 0.94f, 0.94f, 0.792f, 0.777f, 0.777f, 0.777f, };
private boolean mIndexIsExsit = true;
private int mNormalTextColor = Color.WHITE;// 0x4c000000;
private int mNonExistTextColor = Color.WHITE;// 0x19000000;
private int mNormalBgColor = 0xFF000000;
private int mNonExistBgColor = 0xFFe5e5e5;
private int animateCount = 0;
private int mLevel = -1;
private Rect[] mHubble_R_IN;// = new Rect[10];
private Rect[] mHubble_R_OUT;
private Rect[] mHubble_L_IN;
private Rect[] mHubble_L_OUT;
public SidebarHubbleView(Context context) {
this(context, null);
}
public SidebarHubbleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SidebarHubbleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public int getHubbleInPerFrame(){
return hubble_in_per_frame;
}
public int getHubbleOutPerFrame(){
return hubble_out_per_frame;
}
private void init() {
mHubbleInDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.hubble_in_frame_levellist);
mHubbleOutDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.hubble_out_frame_levellist);
mHubbleLeft = getResources().getDrawable(R.drawable.sidbar_hubble_part_left);
mHubbleRight = getResources().getDrawable(R.drawable.sidbar_hubble_part_right);
setBackgroundColor(Color.TRANSPARENT);
mPaint.setTextSize(fPaintSize);
mPaint.setColor(mNormalTextColor);
mNonExistPaint.setTextSize(fPaintSize);
mNonExistPaint.setColor(mNonExistTextColor);
mHubbleInDrawable.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
mHubbleOutDrawable.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
mHubbleLeft.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
mHubbleRight.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
//cal all pos-rect
// IN
mHubble_L_IN = new Rect[scaling_IN.length];
float scal = 0.0f;
for (int index = 0; index < mHubble_L_IN.length; index++) {
scal = scaling_IN[index];
mHubble_L_IN[index] = new Rect();
mHubble_L_IN[index].left = (int) (offsetX_IN[index] - fHubbleViewZoomX * scal);
mHubble_L_IN[index].right = (int) (mHubble_L_IN[index].left + fHubbleViewLeftWith * scal);
mHubble_L_IN[index].top = (int) (fSideBarHubbleViewHigh - fHubbleViewHigh * scal) / 2;
mHubble_L_IN[index].bottom = (int) (mHubble_L_IN[index].top + fHubbleViewHigh * scal);
}
mHubble_R_IN = new Rect[scaling_IN.length];
for (int index = 0; index < mHubble_R_IN.length; index++) {
scal = scaling_IN[index];
mHubble_R_IN[index] = new Rect();
mHubble_R_IN[index].left = mHubble_L_IN[index].right;
mHubble_R_IN[index].right = (int) (mHubble_R_IN[index].left + fHubbleViewRightWith * scal);
mHubble_R_IN[index].top = mHubble_L_IN[index].top;
mHubble_R_IN[index].bottom = mHubble_L_IN[index].bottom;
}
// OUT
mHubble_L_OUT = new Rect[scaling_OUT.length];
for (int index = 0; index < mHubble_L_OUT.length; index++) {
scal = scaling_OUT[index];
mHubble_L_OUT[index] = new Rect();
mHubble_L_OUT[index].left = (int) (offsetX_OUT[index] - fHubbleViewZoomX * scal);
mHubble_L_OUT[index].right = (int) (mHubble_L_OUT[index].left + fHubbleViewLeftWith * scal);
mHubble_L_OUT[index].top = (int) (fSideBarHubbleViewHigh - fHubbleViewHigh * scal) / 2;
mHubble_L_OUT[index].bottom = (int) (mHubble_L_OUT[index].top + fHubbleViewHigh * scal);
}
mHubble_R_OUT = new Rect[scaling_OUT.length];
for (int index = 0; index < mHubble_R_OUT.length; index++) {
scal = scaling_OUT[index];
mHubble_R_OUT[index] = new Rect();
mHubble_R_OUT[index].left = mHubble_L_OUT[index].right;
mHubble_R_OUT[index].right = (int) (mHubble_R_OUT[index].left + fHubbleViewRightWith * scal);
mHubble_R_OUT[index].top = mHubble_L_OUT[index].top;
mHubble_R_OUT[index].bottom = mHubble_L_OUT[index].bottom;
}
}
public void setNormalTextColor(int color) {
if (mNormalTextColor != color) {
mNormalTextColor = color;
mPaint.setColor(mNormalTextColor);
}
}
public void setNonExistTextColor(int color) {
if (mNonExistTextColor != color) {
mNonExistTextColor = color;
mNonExistPaint.setColor(mNonExistTextColor);
}
}
public void setNormalBgColor(int color) {
if (mNormalBgColor != color) {
mNormalBgColor = color;
if (mIndexIsExsit) {
setNormalBgColor();
}
}
}
public void setNonExistBgColor(int color) {
if (mNonExistBgColor != color) {
mNonExistBgColor = color;
if (!mIndexIsExsit) {
setNonExistBgColor();
}
}
}
public void setNormalBgColor() {
if (mNormalBgColor != mNonExistBgColor) {
mHubbleInDrawable.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
mHubbleOutDrawable.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
mHubbleLeft.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
mHubbleRight.setColorFilter(mNormalBgColor, PorterDuff.Mode.SRC_IN);
}
}
public void setNonExistBgColor() {
if (mNonExistBgColor != mNormalBgColor) {
mHubbleInDrawable.setColorFilter(mNonExistBgColor, PorterDuff.Mode.SRC_IN);
mHubbleOutDrawable.setColorFilter(mNonExistBgColor, PorterDuff.Mode.SRC_IN);
mHubbleLeft.setColorFilter(mNonExistBgColor, PorterDuff.Mode.SRC_IN);
mHubbleRight.setColorFilter(mNonExistBgColor, PorterDuff.Mode.SRC_IN);
}
}
public void showHubbleWithAnimation() {
if (mAnimator != null) {
mAnimator.cancel();
mAnimator = null;
}
mLevel = -1;
animateCount = 0;
mAnimator = ValueAnimator.ofInt(0, IN_FRAME_COUNT - 1);
long duratime = (long)IN_FRAME_COUNT * hubble_in_per_frame;
mAnimator.setDuration(duratime);
//mAnimator.setEvaluator(new QuadEaseOut(duratime));
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
++animateCount;
int iValue = animator.getAnimatedValue() == null ? 0 : (Integer) animator.getAnimatedValue();
if (iValue < 0 || IN_FRAME_COUNT <= iValue)
return;
if (mLevel == iValue)
return;
mLevel = iValue;
// set ChassisDrawable level
if (mLevel <= ANIMA_IN_END_LEVEL)
mHubbleInDrawable.setLevel(mLevel);
invalidate();
}
});
mAnimator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
mStatus = IN_ANIMA;
animateCount = 0;
}
@Override
public void onAnimationRepeat(Animator arg0) {
}
@Override
public void onAnimationEnd(Animator arg0) {
mStatus = NORMAL_SHOW;
}
@Override
public void onAnimationCancel(Animator arg0) {
}
});
mStatus = IN_ANIMA;
mAnimator.start();
}
public void hidHubbleWithAnimation() {
if (mAnimator != null) {
mAnimator.cancel();
mAnimator = null;
}
mLevel = -1;
animateCount = 0;
mAnimator = ValueAnimator.ofInt(0, OUT_FRAME_COUNT - 1);
long duratime = (long)OUT_FRAME_COUNT * hubble_out_per_frame;
mAnimator.setDuration(duratime);
//mAnimator.setEvaluator(new QuadEaseOut(duratime));
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
++animateCount;
final int iValue = animator.getAnimatedValue() == null ? 0 : (Integer) animator.getAnimatedValue();
if (iValue < 0 || OUT_FRAME_COUNT <= iValue || mLevel == iValue)
return;
mLevel = iValue;
// ChassisDrawable
if (ANIMA_OUT_BEGIN_LEVEL <= mLevel)
mHubbleOutDrawable.setLevel(mLevel - ANIMA_OUT_BEGIN_LEVEL);
invalidate();
}
});
mAnimator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
mStatus = OUT_ANIMA;
animateCount = 0;
}
@Override
public void onAnimationRepeat(Animator arg0) {
}
@Override
public void onAnimationEnd(Animator arg0) {
// mStatus = NORMAL_SHOW;
}
@Override
public void onAnimationCancel(Animator arg0) {
}
});
mStatus = OUT_ANIMA;
mAnimator.start();
}
public boolean stopOut() {
if (OUT_ANIMA == mStatus && mAnimator.isRunning()) {
mAnimator.cancel();
mStatus = NORMAL_SHOW;
mHubbleInDrawable.setLevel(IN_FRAME_COUNT - 1);
invalidate();
return true;
}
return false;
}
public void setText(String text) {
if (TextUtils.equals(mText, text))
return;
mText = text;
invalidate();
}
public float theRestOfInAnim() {
float rest = 0.0f;
if (mStatus == IN_ANIMA) {
rest = 1.0f - ((float) mLevel) / (IN_FRAME_COUNT - 1);
}
return rest;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
Rect bounds = new Rect(getWidth() - fHubbleViewChassisWith, 0, getWidth(), getHeight());
if (mFontMetricsInt == null)
mFontMetricsInt = mPaint.getFontMetricsInt();
if (mStatus == OUT_ANIMA) {
//draw Chassis
if (ANIMA_OUT_BEGIN_LEVEL <= mLevel && needDrawChassis()) {
mHubbleOutDrawable.setBounds(bounds);
mHubbleOutDrawable.getLevel();
mHubbleOutDrawable.draw(canvas);
}
mHubbleLeft.setBounds(mHubble_L_OUT[mLevel]);
mHubbleLeft.draw(canvas);
if (mLevel < ANIMA_OUT_BEGIN_LEVEL) {
mHubbleRight.setBounds(mHubble_R_OUT[mLevel]);
mHubbleRight.draw(canvas);
}
offsetX = offsetX_OUT[mLevel] - fHubbleViewZoomX + (fHubbleViewLeftWith - mPaint.measureText(mText)) / 2;
offsetY = (getHeight() + Math.abs(mFontMetricsInt.ascent + mFontMetricsInt.descent)) / 2;
} else {
if (NORMAL_SHOW == mStatus && mHubble_R_IN.length - 1 != mLevel) {
mLevel = mHubble_R_IN.length - 1;
mHubbleInDrawable.setLevel(mLevel);
}
if (mLevel <= ANIMA_IN_END_LEVEL && needDrawChassis()) {
mHubbleInDrawable.setBounds(bounds);
mHubbleInDrawable.draw(canvas);
}
mHubbleRight.setBounds(mHubble_R_IN[mLevel]);
mHubbleRight.draw(canvas);
mHubbleLeft.setBounds(mHubble_L_IN[mLevel]);
mHubbleLeft.draw(canvas);
offsetX = offsetX_IN[mLevel] - fHubbleViewZoomX + (fHubbleViewLeftWith - mPaint.measureText(mText)) / 2;
offsetY = (getHeight() + Math.abs(mFontMetricsInt.ascent + mFontMetricsInt.descent)) / 2;
}
if (mText != null && 0 < offsetX && 0 < offsetY) {
if (mIndexIsExsit)
canvas.drawText(mText, offsetX, offsetY, mPaint);
else
canvas.drawText(mText, offsetX, offsetY, mNonExistPaint);
}
canvas.restore();
}
private FontMetricsInt mFontMetricsInt = null;
public void setIndexIsExsit(boolean exist) {
if (mIndexIsExsit != exist) {
if (exist) {
setNormalBgColor();
mPaint.setColor(mNormalTextColor);
} else {
setNonExistBgColor();
mPaint.setColor(mNonExistTextColor);
}
}
mIndexIsExsit = exist;
}
private boolean needDrawChassis() {
if ((mStatus == OUT_ANIMA && ANIMA_OUT_BEGIN_LEVEL <= mLevel) || (mStatus == IN_ANIMA && mLevel <= ANIMA_IN_END_LEVEL)) {
return true;
}
return true;
}
}