转载请注明出处:
距离过春节还有1天。继续这一系列的git翻料之旅。
昨天的工具类真的非常棒,这里再推崇一下 传送门: (实际去体验的小伙伴都说好)
今天上一个自己定义的Button:SendButton
效果:
比較建议把代码抠出来由于内容不多,一个类就画完了
地址:
由于内容不多。我们就来分析下
public class SendButton extends View
31行。继承View而不是ViewGroup(也就是不像一个Layout为底板 其中画东西了,纯画)
int flag = 0; Point a, b, c, d, e; Path mOutlinePath, mPlanePath; int mButtonColor, mButtonSide, mBorderStrokeWidth, mPlaneStrokeWidth, mPlaneColor; Paint mBackgroundPaint, mPlanePaint; ValueAnimator mPlaneAnimator; long mDuration; AnimationType mAnimationType;
35-42,定义了一系列变量,动画模式啊,持续时间啊。画笔啊,尺寸什么的
public SendButton(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.SendButton, 0, 0); try { mButtonColor = a.getColor(R.styleable.SendButton_buttonColor, Color.WHITE); mButtonSide = a.getDimensionPixelSize(R.styleable.SendButton_buttonSide, 200); mBorderStrokeWidth = a.getInteger(R.styleable.SendButton_borderStrokeWidth, 5); mPlaneStrokeWidth = a.getInteger(R.styleable.SendButton_planeStrokeWidth, 5); mPlaneColor = a.getColor(R.styleable.SendButton_planeColor, getResources().getColor(R.color.orange)); mAnimationType = AnimationType.values()[a.getInteger(R.styleable .SendButton_animationType, 0)]; mDuration = a.getInteger(R.styleable.SendButton_duration, 3000); } catch (Exception e) { e.printStackTrace(); } finally { a.recycle(); } init(); }
45-74,构造函数,获取标签的一系列内容,然后把前面那些变量填充了一下,然后调用了init()方法。
private void init() { mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPlanePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBackgroundPaint.setStyle(Paint.Style.STROKE); mPlanePaint.setStrokeWidth(mPlaneStrokeWidth); mBackgroundPaint.setStrokeWidth(mBorderStrokeWidth); mBackgroundPaint.setColor(mButtonColor); mOutlinePath = new Path(); mPlanePath = new Path(); mPlaneAnimator = ValueAnimator.ofInt(0, 75); mPlaneAnimator.setDuration(mDuration); mPlaneAnimator.setRepeatMode(ValueAnimator.RESTART); mPlaneAnimator.setRepeatCount(ValueAnimator.INFINITE); switch (mAnimationType) { case LINEAR: mPlaneAnimator.setInterpolator(new LinearInterpolator()); break; case ANTICIPATE: mPlaneAnimator.setInterpolator(new AnticipateInterpolator()); break; case ANTICIPATE_OVERSHOOT: mPlaneAnimator.setInterpolator(new AnticipateOvershootInterpolator()); break; case ACCELERATE: mPlaneAnimator.setInterpolator(new AccelerateInterpolator()); break; case ACCELERATE_DECELERATE: mPlaneAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); break; case BOUNCE: mPlaneAnimator.setInterpolator(new BounceInterpolator()); break; case DECELERATE: mPlaneAnimator.setInterpolator(new DecelerateInterpolator()); break; case FASTOUTLINEARIN: mPlaneAnimator.setInterpolator(new FastOutLinearInInterpolator()); break; case FASTOUTSLOWIN: mPlaneAnimator.setInterpolator(new FastOutSlowInInterpolator()); break; case LINEAROUTSLOWIN: mPlaneAnimator.setInterpolator(new LinearOutSlowInInterpolator()); break; case OVERSHOOT: mPlaneAnimator.setInterpolator(new OvershootInterpolator()); break; } mPlaneAnimator.start(); /** * The coordinates position calculated by percentage of button side. */ a = new Point((mButtonSide * 10) / 100, (mButtonSide * 55) / 100); // Point a : (10% of mButtonSide, 55% of mButtonSide) b = new Point((mButtonSide * 80) / 100, (mButtonSide * 20) / 100); // Point b : (80% of mButtonSide, 20% of mButtonSide) c = new Point((mButtonSide * 45) / 100, (mButtonSide * 90) / 100); // Point c : (45% of mButtonSide, 90% of mButtonSide) d = new Point((mButtonSide * 30) / 100, (mButtonSide * 70) / 100); // Point d : (30% of mButtonSide, 70% of mButtonSide) e = new Point(mButtonSide / 2, mButtonSide / 2); // Point e : (10% of mButtonSide, 55% of mButtonSide) }
76-139,给画笔着色,然后选定插值器模式(就是突然加速啊,缓慢啊。一系列模式这个我之前View的文章里有,传送门:)
再一个就是计算各个坐标点,画圆画三角都用的。(算法这部分不研究了。反正就是依据控件大小操作)
public void setPath() { mPlanePath = new Path(); mPlanePath.moveTo(a.x, a.y); //Set the starting point to A mPlanePath.lineTo(a.x, a.y); mPlanePath.lineTo(b.x, b.y); mPlanePath.lineTo(c.x, c.y); mPlanePath.lineTo(d.x, d.y); mPlanePath.lineTo(e.x, e.y); mPlanePath.lineTo(d.x, d.y); mPlanePath.lineTo(a.x, a.y); }
164-174,画轨迹用的
private void translate() { a.set((mButtonSide * 10) / 100, (mButtonSide * 55) / 100); // Point a : (10% of mButtonSide, // 55% of mButtonSide) b.set((mButtonSide * 80) / 100, (mButtonSide * 20) / 100); // Point b : (80% of mButtonSide, // 20% of mButtonSide) c.set((mButtonSide * 45) / 100, (mButtonSide * 90) / 100); // Point c : (45% of mButtonSide, // 90% of mButtonSide) d.set((mButtonSide * 30) / 100, (mButtonSide * 70) / 100); // Point d : (30% of mButtonSide, // 70% of mButtonSide) e.set(mButtonSide / 2, mButtonSide / 2); // Point e : (10% of mButtonSide, 55% of // mButtonSide) int change = 3 * (int) mPlaneAnimator.getAnimatedValue(); Log.i(LOGTAG, "Animated Value: " + change + ", Flag: " + flag++); a.x += change; a.y -= change; b.x += change; b.y -= change; c.x += change; c.y -= change; d.x += change; d.y -= change; e.x += change; e.y -= change; invalidate(); }
178-209,画三角用的,这个三角有一个内凹的角度问题,计算起来还是有点搞脑子了(算法差,心酸)
private enum AnimationType { LINEAR, ANTICIPATE, ANTICIPATE_OVERSHOOT, ACCELERATE, ACCELERATE_DECELERATE, BOUNCE, DECELERATE, FASTOUTLINEARIN, FASTOUTSLOWIN, LINEAROUTSLOWIN, OVERSHOOT }
211-224,各类插值器做的枚举
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mBackgroundPaint.setAlpha(255); mOutlinePath.addRoundRect(new RectF(0, 0, mButtonSide, mButtonSide), mButtonSide / 3, mButtonSide / 3, Path.Direction.CCW); canvas.drawPath(mOutlinePath, mBackgroundPaint); canvas.clipPath(mOutlinePath); // for different color of Fill and Stroke, // first painted in Fill style and then Stroke style with different color mPlanePaint.setStyle(Paint.Style.FILL); mPlanePaint.setColor(mPlaneColor); mPlanePaint.setAlpha(255 - ((int) mPlaneAnimator.getAnimatedValue() * 25) / 10); translate(); setPath(); canvas.drawPath(mPlanePath, mPlanePaint); mPlanePaint.setStyle(Paint.Style.STROKE); mPlanePaint.setColor(Color.WHITE); mPlanePaint.setAlpha(255 - ((int) mPlaneAnimator.getAnimatedValue() * 25) / 10); canvas.drawPath(mPlanePath, mPlanePaint); }
142-162,详细的绘画实现,这部分来读一读
首先给画笔做了一些圆角的操作。然后画方,画圆。然后用Direction去掉不须要的部分。出现了我们的外圈白线
再之后就是画三角。画三角也是依据位置和动画位置一直在刷UI的。
所以 这控件持续时间多了,可能会有卡顿的现象。。
背景啊,大小啊,三角颜色这些都能够改。可是要在XML里改,作者没有提供一系列set方法。
OK,就到这。明天我休假了。家里有点事可能停更,之后放假在家没事做的时候再补吧,新年快乐。!
!!