赞
踩
记录一次自定义控件的实现原理
动画效果分解为一个随机位置归位动效和一个渐变的动效
1.根据文案在onSizechange方法里生成一个随机位置的集合和一个最终位置的集合 用于记录每个字符的位置
2.监听valueanimation动态计算随机位置当前应该到达的位置然后重绘界面
3.监听动效结束开始初始化一个渐变的动效 使用LinearGradient和Matrix实现渐变效果 渐变效果实现参考文末链接
关键代码如下
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- initTranslateAnimation(w, h);
- }
-
- private void initTranslateAnimation(int w, int h) {
- int startX;
- int centerY;
- float contenWith = mPaint.measureText(contentStr);
- Rect rect = new Rect();
- mPaint.getTextBounds(contentStr, 0, contentStr.length(), rect);
- startX = (int) ((w - contenWith) / 2);
- centerY = (h + rect.height()) / 2;
- queitList.clear();
- randowList.clear();
- for (int i = 0; i < contentStr.length(); i++) {
- char c = contentStr.charAt(i);
- float singleW = mPaint.measureText(String.valueOf(c));
- //记录每个字符的开始坐标 (文字绘制的左下角坐标)
- queitList.add(new PointF(startX, centerY));
- // 生成随机位置坐标
- randowList.add(new PointF((float) Math.random() * (w - singleW) + singleW, (float) Math.random() * (h - rect.height()) + rect.height()));
- startX += (singleW + 3);
- }
-
- animator = ValueAnimator.ofFloat(0, 1);
- animator.setDuration(2000);
- TimeInterpolator intercept = new DecelerateInterpolator(0.05f);
- animator.setInterpolator(intercept);
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- // 计算当前文字的坐标并重绘
- float value = (float) animation.getAnimatedValue();
- for (int i = 0; i < randowList.size(); i++) {
- PointF pointF = randowList.get(i);
- PointF pointF1 = queitList.get(i);
-
- pointF.x = pointF.x + (pointF1.x - pointF.x) * value;
- pointF.y = pointF.y + (pointF1.y - pointF.y) * value;
- }
- postInvalidate();
- }
- });
- // 检听归位动画结束开始渐变动画
- animator.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- isTranslateEnd = false;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
-
- isTranslateEnd = true;
-
- initLightAnimation();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
-
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
- });
-
- animator.start();
- }
-
- private void initLightAnimation() {
- float strW = mPaint.measureText(contentStr);
- PointF pointF = queitList.get(0);
- // 从文案内容前面开始渐变 注意TileMode.CLAMP 时为了文字颜色不会突变 开始和结束的颜色和textColor保持一致
- final Shader shader = new LinearGradient(pointF.x-strW, 0, pointF.x, 0, new int[]{Color.BLACK,Color.RED,Color.WHITE,Color.BLACK}, null,Shader.TileMode.CLAMP);
- final Matrix matrix = new Matrix();
- shader.setLocalMatrix(matrix);
- mPaint.setShader(shader);
- //
- ValueAnimator animator = ValueAnimator.ofFloat(0, getWidth()*2);
- animator.setDuration(1000);
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- //计算Matrix translate距离
- float value = (float) animation.getAnimatedValue();
- matrix.setTranslate(value, 0);
- shader.setLocalMatrix(matrix);
- postInvalidate();
- }
- });
- animator.start();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.drawRect(0, 0, getWidth(), getHeight(), mPaints);
- for (int i = 0; i < contentStr.length(); i++) {
- PointF pointF = isTranslateEnd ? queitList.get(i) : randowList.get(i);
- canvas.drawText(String.valueOf(contentStr.charAt(i)), pointF.x, pointF.y, mPaint);
- }
- }
-
- //开始动效方法
- public void start() {
- if (animator.isRunning()) {
- animator.cancel();
- }
- initTranslateAnimation(getWidth(), getHeight());
- }
参考文献
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。