Android动画 播放暂停
目录
Android 开始暂停动画.png
效果
国际惯例,先放效果
动画开始暂停.gif
前言
之前写了java线程的暂停和继续,Android下载暂停,圆形下载进度条,相信大家看了上面的动画效果就知道我这一个系列是要做什么了,哈哈,没错就是一个简单的网络下载暂停,只是通过一部分一部分的分析,今天把动画给搞定了,过段时间就是可以成功的把这些整合起来,估计效果就是我们手机应用商城中的软件下载的效果,可以暂停,也是圆形进度条;拥有开始和暂停的动画;想想就非常不错;666666666
正文
自己设置View PlayPauseView
上面的动画就是两个矩形,变成三角形,我们只用设置左边矩形的四个点的坐标,那么右边的坐标,可以通过自己定义的两个矩形之间的宽度,算出相应的坐标,
Path方法就是用画笔画出相应的动画效果,path.moveTo(),就是从起点画到后面的点,path.lineTo()画直线,通过两个点确定一个直线,即可以成功的画出动画,path.close()这可不是关闭方法,而是把线段封闭掉,什么意思呢?我们花了四个点,但是只连接了三个线,那么就会把开始的点和最后的点连接起来,这样就形成了矩形。
public class PlayPauseView extends View { private int mWidth; //View宽度 private int mHeight; //View高度 private Paint mPaint; private Path mLeftPath; //暂停时左侧竖条Path private Path mRightPath; //暂停时右侧竖条Path private float mGapWidth; //两个暂停竖条中间的空隙,默认为两侧竖条的宽度 private float mProgress; //动画Progress private Rect mRect; private boolean isPlaying; private float mRectWidth; //圆内矩形宽度 private float mRectHeight; //圆内矩形高度 private float mRectLT; //矩形左侧上侧坐标 private float mRadius; //圆的半径 private int mBgColor = Color.WHITE; private int mBtnColor = Color.BLACK; private int mDirection = Direction.POSITIVE.value; private float mPadding; private int mAnimDuration = 200;//动画时间 public PlayPauseView(Context context) { super(context); } public PlayPauseView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context, attrs); } public PlayPauseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { mPaint = new Paint(); mPaint.setAntiAlias(true); mLeftPath = new Path(); mRightPath = new Path(); mRect = new Rect(); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PlayPauseView); mBgColor = ta.getColor(R.styleable.PlayPauseView_bg_color, Color.WHITE); mBtnColor = ta.getColor(R.styleable.PlayPauseView_btn_color, Color.BLACK); mGapWidth = ta.getDimensionPixelSize(R.styleable.PlayPauseView_gap_width, dp2px(context, 0)); mPadding = ta.getDimensionPixelSize(R.styleable.PlayPauseView_space_padding, dp2px(context, 0)); mDirection = ta.getInt(R.styleable.PlayPauseView_anim_direction, Direction.POSITIVE.value); mAnimDuration = ta.getInt(R.styleable.PlayPauseView_anim_duration, 200); ta.recycle(); setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = MeasureSpec.getSize(widthMeasureSpec); mHeight = MeasureSpec.getSize(heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { mWidth = Math.min(mWidth, mHeight); } else { mWidth = dp2px(getContext(), 50); } if (heightMode == MeasureSpec.EXACTLY) { mHeight = Math.min(mWidth, mHeight); } else { mHeight = dp2px(getContext(), 50); } mWidth = mHeight = Math.min(mWidth, mHeight); setMeasuredDimension(mWidth, mHeight); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = mHeight = w; initValue(); } private void initValue() { mRadius = mWidth / 2; mPadding = getSpacePadding() == 0 ? mRadius / 3f : getSpacePadding(); if (getSpacePadding() > mRadius / Math.sqrt(2) || mPadding < 0) { mPadding = mRadius / 3f; //默认值 } float space = (float) (mRadius / Math.sqrt(2) - mPadding); //矩形宽高的一半 mRectLT = mRadius - space; float rectRB = mRadius + space; mRectWidth = 2 * space; mRectHeight = 2 * space; mGapWidth = getGapWidth() != 0 ? getGapWidth() : mRectWidth / 3; mProgress = isPlaying ? 0 : 1; mAnimDuration = getAnimDuration() < 0 ? 200 : getAnimDuration(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mLeftPath.rewind(); mRightPath.rewind(); mPaint.setColor(mBgColor); canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius, mPaint); float distance = mGapWidth * (1 - mProgress); //暂停时左右两边矩形距离 float barWidth = mRectWidth / 2 - distance / 2; //一个矩形的宽度 float leftLeftTop = barWidth * mProgress; //左边矩形左上角 float rightLeftTop = barWidth + distance; //右边矩形左上角 float rightRightTop = 2 * barWidth + distance; //右边矩形右上角 float rightRightBottom = rightRightTop - barWidth * mProgress; //右边矩形右下角 mPaint.setColor(mBtnColor); mPaint.setStyle(Paint.Style.FILL); if (mDirection == Direction.NEGATIVE.value) { mLeftPath.moveTo(mRectLT, mRectLT); mLeftPath.lineTo(leftLeftTop + mRectLT, mRectHeight + mRectLT); mLeftPath.lineTo(barWidth + mRectLT, mRectHeight + mRectLT); mLeftPath.lineTo(barWidth + mRectLT, mRectLT); mLeftPath.close(); mRightPath.moveTo(rightLeftTop + mRectLT, mRectLT); mRightPath.lineTo(rightLeftTop + mRectLT, mRectHeight + mRectLT); mRightPath.lineTo(rightRightBottom + mRectLT, mRectHeight + mRectLT); mRightPath.lineTo(rightRightTop + mRectLT, mRectLT); mRightPath.close(); } else { mLeftPath.moveTo(leftLeftTop + mRectLT, mRectLT); mLeftPath.lineTo(mRectLT, mRectHeight + mRectLT); mLeftPath.lineTo(barWidth + mRectLT, mRectHeight + mRectLT); mLeftPath.lineTo(barWidth + mRectLT, mRectLT); mLeftPath.close(); mRightPath.moveTo(rightLeftTop + mRectLT, mRectLT); mRightPath.lineTo(rightLeftTop + mRectLT, mRectHeight + mRectLT); mRightPath.lineTo(rightLeftTop + mRectLT + barWidth, mRectHeight + mRectLT); mRightPath.lineTo(rightRightBottom + mRectLT, mRectLT); mRightPath.close(); } canvas.save(); canvas.translate(mRectHeight / 8f * mProgress, 0); float progress = isPlaying ? (1 - mProgress) : mProgress; int corner = mDirection == Direction.NEGATIVE.value ? -90 : 90; float rotation = isPlaying ? corner * (1 + progress) : corner * progress; canvas.rotate(rotation, mWidth / 2f, mHeight / 2f); canvas.drawPath(mLeftPath, mPaint); canvas.drawPath(mRightPath, mPaint); canvas.restore(); } public ValueAnimator getPlayPauseAnim() { ValueAnimator valueAnimator = ValueAnimator.ofFloat(isPlaying ? 1 : 0, isPlaying ? 0 : 1); valueAnimator.setDuration(mAnimDuration); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mProgress = (float) animation.getAnimatedValue(); invalidate(); } }); return valueAnimator; } public void play() { if (getPlayPauseAnim() != null) { getPlayPauseAnim().cancel(); } setPlaying(true); getPlayPauseAnim().start(); } public void pause() { if (getPlayPauseAnim() != null) { getPlayPauseAnim().cancel(); } setPlaying(false); getPlayPauseAnim().start(); } private PlayPauseListener mPlayPauseListener; public void setPlayPauseListener(PlayPauseListener playPauseListener) { mPlayPauseListener = playPauseListener; setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (isPlaying()) { pause(); if (null != mPlayPauseListener) { mPlayPauseListener.pause(); } } else { play(); if (null != mPlayPauseListener) { mPlayPauseListener.play(); } } } }); } public interface PlayPauseListener { void play(); void pause(); } public int dp2px(Context context, float dpVal) { float density = context.getResources().getDisplayMetrics().density; return (int) (density * dpVal + 0.5f); } /* ------------下方是参数------------- */ public boolean isPlaying() { return isPlaying; } public void setPlaying(boolean playing) { isPlaying = playing; } public void setGapWidth(float gapWidth) { mGapWidth = gapWidth; } public float getGapWidth() { return mGapWidth; } public int getBgColor() { return mBgColor; } public int getBtnColor() { return mBtnColor; } public int getDirection() { return mDirection; } public void setBgColor(int bgColor) { mBgColor = bgColor; } public void setBtnColor(int btnColor) { mBtnColor = btnColor; } public void setDirection(Direction direction) { mDirection = direction.value; } public float getSpacePadding() { return mPadding; } public void setSpacePadding(float padding) { mPadding = padding; } public int getAnimDuration() { return mAnimDuration; } public void setAnimDuration(int animDuration) { mAnimDuration = animDuration; } public enum Direction { POSITIVE(1),//顺时针 NEGATIVE(2);//逆时针 int value; Direction(int value) { this.value = value; } }} mBgColor = ta.getColor(R.styleable.PlayPauseView_bg_color, Color.WHITE); mBtnColor = ta.getColor(R.styleable.PlayPauseView_btn_color, Color.BLACK); mGapWidth = ta.getDimensionPixelSize(R.styleable.PlayPauseView_gap_width, dp2px(context, 0)); mPadding = ta.getDimensionPixelSize(R.styleable.PlayPauseView_space_padding, dp2px(context, 0)); mDirection = ta.getInt(R.styleable.PlayPauseView_anim_direction, Direction.POSITIVE.value); mAnimDuration = ta.getInt(R.styleable.PlayPauseView_anim_duration, 200);大家可能不太清楚这些是什么,其实这个就是我们在xml中声名的属性,也就是自己设置View的属性;
自己设置xml attrs.xml
<resources> <declare-styleable name="PlayPauseView"> <attr name="bg_color" format="color"/> <attr name="btn_color" format="color"/> <attr name="gap_width" format="dimension|reference"/> <attr name="space_padding" format="dimension|reference"/> <attr name="anim_duration" format="integer"/> <attr name="anim_direction"> <enum name="positive" value="1"/> <enum name="negative" value="2"/> </attr> </declare-styleable></resources>大家看到上面的name,就是我们在自己设置View 中的属性方法;
通过相应的设置,大家即可以看出来了;
界面 activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.freedom.lauzy.playpauseview.MainActivity"> <com.freedom.lauzy.playpauseviewlib.PlayPauseView android:id="@+id/play_pause_view1" android:layout_width="80dp" android:layout_height="80dp" android:layout_gravity="center" android:layout_marginTop="40dp" app:anim_direction="positive" app:anim_duration="300" app:bg_color="#E0E0E0" app:btn_color="#000000"/></LinearLayout>看见上面的app:后下面跟的属性名称了吗?就是我们自己设置View 的那些属性,我们是在自己设置的时候通过get()``set()方法,设置属性的;
主方法 MainActivity()
package com.freedom.lauzy.playpauseview;import android.graphics.Color;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Toast;import com.freedom.lauzy.playpauseviewlib.PlayPauseView;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final PlayPauseView playPauseView1 = (PlayPauseView) findViewById(R.id.play_pause_view1); playPauseView1.setPlayPauseListener(new PlayPauseView.PlayPauseListener() { @Override public void play() { Toast.makeText(MainActivity.this, "Play", Toast.LENGTH_SHORT).show(); } @Override public void pause() { Toast.makeText(MainActivity.this, "Pause", Toast.LENGTH_SHORT).show(); } }); }}这个就还是蛮简单的,设置一下点击事件即可以了,我们自己设置的时候,自己设置了点击事件(可以看看上面的代码)。
总结
自己设置View时,要想一想我们自己设置需要什么功能,他有动画吗,需要什么样的参数,能设置的属性有需要多少,需要动画吗?需要什么要的动画,等等
- 首先就是两个矩形,先考虑假如画出两个矩形,先画出一个圆,配置该视图的宽高,就像画出个圆形,在圆形里面画出矩形,左边矩形的坐标,假如画,两个矩形的宽度设置出来,就知道相应的右边的坐标,这样子两个矩形就出来了
- 其次就是个三角形,也就是三个点的坐标,通过宽度换算成适合的大小,画出就可;
- 最后就是动画,设置动画时间,动画效果
- 最后就是可配置的参数和属性;
感谢
感谢大家!!! 加油!!! 努力!! 日更!!
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Android动画 播放暂停