Android自定义View贝塞尔曲线最佳实现
来源:互联网 发布:linux mount命令nfs 编辑:程序博客网 时间:2024/04/28 13:12
先看一下效果图
主要是通过贝塞尔曲线去控制绳子的绘制,就直接上代码了
package yuekong.com.progressview;import android.animation.Animator;import android.animation.AnimatorSet;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.util.TypedValue;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.animation.DecelerateInterpolator;/** * Created by Zhongqi.Shao on 2017/1/17. */public class ProgressView extends SurfaceView implements SurfaceHolder.Callback { private final int STATE_DOWN = 1; private final int STATE_UP = 2; private Context mContext; private Path mPath; //中间绳子的Paint private Paint mPaint; private Paint mCirclePaint; //向下运动 private ValueAnimator mDownAnimator; //向上运动 private ValueAnimator mUpAnimator; //从上至下 自由落体运动 private ValueAnimator mFreeAnimator; private AnimatorSet mAnimationSet; private boolean isAnimationShowing = false; //中间绳子的高度 private float mLineHeigth; //中间绳子的宽度 private float mLineWidth; //向下运动的距离 private float mDownDistance = 0f; //向上运动的距离 private float mUpDistance = 0f; //自由落体运动的距离 private float mFreeDistance = 0f; private int mState = STATE_DOWN; private boolean mIsBounced = false; public ProgressView(Context context) { this(context, null); mContext = context; } public ProgressView(Context context, AttributeSet attrs) { this(context, attrs, 0); mContext = context; } public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; init(); } private void init() { mLineHeigth = dp2px(3); mLineWidth = dp2px(100); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mLineHeigth); //圆形线帽 mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setColor(getContext().getResources().getColor(R.color.auto_yellow)); mCirclePaint = new Paint(); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(mContext.getResources().getColor(R.color.black)); mCirclePaint.setStyle(Paint.Style.FILL); mPath = new Path(); SurfaceHolder holder = getHolder(); holder.addCallback(this); initAnimator(); } private void initAnimator() { mDownAnimator = ValueAnimator.ofFloat(0, 1); mDownAnimator.setDuration(500); mDownAnimator.setInterpolator(new DecelerateInterpolator()); mDownAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mDownDistance = (float) valueAnimator.getAnimatedValue() * 50; postInvalidate(); } }); mDownAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { mState = STATE_DOWN; } @Override public void onAnimationEnd(Animator animator) { } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); mUpAnimator = ValueAnimator.ofFloat(0, 1); mUpAnimator.setDuration(900); mUpAnimator.setInterpolator(new DecelerateInterpolator()); mUpAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mUpDistance = (float) valueAnimator.getAnimatedValue() * 50; if (mUpDistance >= 50) { //进入自由落体 mIsBounced = true; if (!mFreeAnimator.isRunning()) { mFreeAnimator.start(); } } postInvalidate(); } }); mUpAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { mState = STATE_UP; } @Override public void onAnimationEnd(Animator animator) { } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); mFreeAnimator = ValueAnimator.ofFloat(0, 6.8f); mFreeAnimator.setDuration(900); mFreeAnimator.setInterpolator(new DecelerateInterpolator()); mFreeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float t = (float) valueAnimator.getAnimatedValue(); mFreeDistance = 34 * t - 5 * t * t; postInvalidate(); } }); mFreeAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { mIsBounced = true; } @Override public void onAnimationEnd(Animator animator) { isAnimationShowing = false; //执行第二次动画 startAllAnimator(); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); mAnimationSet = new AnimatorSet(); mAnimationSet.play(mDownAnimator).before(mUpAnimator); mAnimationSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { isAnimationShowing = true; } @Override public void onAnimationEnd(Animator animator) { } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); } public void startAllAnimator() { if (isAnimationShowing) { return; } if (mAnimationSet.isRunning()) { mAnimationSet.end(); mAnimationSet.cancel(); } mIsBounced = false; mAnimationSet.start(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /* * 中间绳子分成左右两个二阶贝塞尔曲线绘制 * */ mPath.reset(); mPath.moveTo(getWidth() / 2 - mLineWidth / 2, getHeight() / 2); if (mState == STATE_DOWN) { //向下运动 //左边的贝塞尔 mPath.quadTo((float) (getWidth() / 2 - mLineWidth / 2 + mLineWidth * 0.375), getHeight() / 2 + mDownDistance, getWidth() / 2, getHeight() / 2 + mDownDistance); //右边的贝塞尔 mPath.quadTo((float) (getWidth() / 2 + mLineWidth / 2 - mLineWidth * 0.375), getHeight() / 2 + mDownDistance, getWidth() / 2 + mLineWidth / 2, getHeight() / 2); canvas.drawPath(mPath, mPaint); //绘制小球 canvas.drawCircle(getWidth() / 2, getHeight() / 2 + mDownDistance - 10, 10, mCirclePaint); } else if (mState == STATE_UP) { //向上运动 //左边的贝塞尔 mPath.quadTo((float) (getWidth() / 2 - mLineWidth / 2 + mLineWidth * 0.375), getHeight() / 2 + (50 - mUpDistance), getWidth() / 2, getHeight() / 2 + (50 - mUpDistance)); //右边的贝塞尔 mPath.quadTo((float) (getWidth() / 2 + mLineWidth / 2 - mLineWidth * 0.375), getHeight() / 2 + (50 - mUpDistance), getWidth() / 2 + mLineWidth / 2, getHeight() / 2); canvas.drawPath(mPath, mPaint); //第三种状态 最大运动长度设置为50 半径为10 if (!mIsBounced) { //正常向上运动 canvas.drawCircle(getWidth() / 2, getHeight() / 2 + (50 - mUpDistance) - 10, 10, mCirclePaint); } else { //自由落体状态 canvas.drawCircle(getWidth() / 2, getHeight() / 2 - mFreeDistance - 10, 10, mCirclePaint); } } //绘制两边固定的小圆 //两边小球的颜色 canvas.drawCircle(getWidth() / 2 - mLineWidth / 2, getHeight() / 2, 10, mCirclePaint); canvas.drawCircle(getWidth() / 2 + mLineWidth / 2, getHeight() / 2, 10, mCirclePaint); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { //锁住画布 Canvas canvas = surfaceHolder.lockCanvas(); //开始绘制 draw(canvas); surfaceHolder.unlockCanvasAndPost(canvas); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { } private int dp2px(int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); } private int sp2px(int sp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()); }}
0 0
- Android自定义View贝塞尔曲线最佳实现
- Android 自定义view实现贝塞尔曲线
- Android自定义View,贝塞尔曲线
- Android自定义View-- 贝塞尔曲线
- Android自定义View阻尼动画&贝塞尔曲线的实现
- Android自定义View---Canvas绘制贝塞尔曲线
- Android自定义View进阶 - 贝塞尔曲线
- Android自定义View之贝塞尔曲线
- Android自定义View画曲线
- android自定义View贝赛尔曲线
- Android自定义View--用贝塞尔曲线实现一加多云天气
- Android自定义View——使用贝塞尔曲线实现流量进度条
- Android自定义View——贝塞尔曲线实现水波纹效果
- Android自定义View——贝塞尔曲线实现水波纹进度球
- 自定义View之贝塞尔曲线
- 自定义view进阶-贝塞尔曲线实现水波动画、粘性控件
- android自定义View创建一个Path绘制多边形,贝塞尔曲线,
- Android自定义view进阶-- 神奇的贝塞尔曲线
- hdu 1711 Number Sequence(KMP)
- 一张图教你如何使用debugview
- eclipse "clean up"出错,
- Spring与Quartz的整合实现定时任务调度
- 排序算法之选择法排序(Java)
- Android自定义View贝塞尔曲线最佳实现
- tp5 重定向缺少index.php报错(No input file specified)
- redis windows平台下的简单实现实例
- tensorflow 源代码学习之图(graph_def 和 graph)
- hibernate使用存储过程初识
- Android当前任务管理器不显示应用进程
- @Override is not allowed when implement interface method
- 【深度学习:CNN】Batch Normalization解析(2)-- caffe中batch_norm层代码详细注解
- 微信小程序开发