博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 自定义View,仿微信视频播放按钮
阅读量:6036 次
发布时间:2019-06-20

本文共 9199 字,大约阅读时间需要 30 分钟。

闲着,尝试实现了新版微信视频播放按钮,使用的是自定义View,先来个简单的效果图。。。真的很简单哈。

由于暂时用不到,加上时间原因,加上实在是没意思,加上……,本控件就没有实现自定义属性,有兴趣的朋友可以自己去添加一下,方法都给你们准备好了。- =

其实这个控件主要步骤

1、画外环的圆

2、画进度的圆或者画三角形播放按钮

其余剩下的都是围绕以上两步准备或者收尾的。

接下来贴主要我们的自定义控件代码,注释很全,我就不过多解释了,请各位看官自己分析,有疑问可以在评论区一起讨论。

package com.lwd.playbutton;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import android.view.View.OnClickListener;/** * 仿微信视频播放按钮 * @author Vitor Lee */public class PlayButton extends View implements OnClickListener {    /**默认最大角度*/    private static final int DEFAULT_MAX_ANGLE = 360;    /**默认最大的进度*/    private static final int DEFAULT_MAX_PROGRESS=100;    /**描边宽度*/    private int mStrokeWidth;    /**外圆环半径*/    private int mOutRadius;    /**内圆半径*/    private int mInnerRiadius;    /**控件的宽度*/    private int mWidth;    /**控件的高度*/    private int mHeight;    /**描边的画笔*/    private Paint mStrokePaint;    /**实心画笔*/    private Paint mFillPaint;    /**进度圆的*/    private RectF mProgressOval;    /**最大进度*/    private int mMax=DEFAULT_MAX_PROGRESS;    /**当前进度*/    private int mProgress;    /**三角形的路径*/    private Path mTriangle;    private ProgressState mCurrentState=ProgressState.PRE_START;        public PlayButton(Context context) {        this(context,null);    }        public PlayButton(Context context, AttributeSet attrs) {        this(context, attrs,0);    }        public PlayButton(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initParams();        initAttribute(context, attrs, defStyle);    }    private void initParams() {        mStrokeWidth = (int) TypedValue.applyDimension(                TypedValue.COMPLEX_UNIT_SP, 1, getResources()                        .getDisplayMetrics());                //初始化描边的笔        mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mStrokePaint.setColor(Color.WHITE);        mStrokePaint.setStyle(Paint.Style.STROKE);        mStrokePaint.setStrokeWidth(mStrokeWidth);                //初始化画实心的笔        mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mFillPaint.setColor(Color.WHITE);        mFillPaint.setStyle(Paint.Style.FILL);                setOnClickListener(this);    }    private void initAttribute(Context context, AttributeSet attrs, int defStyle) {        //TODO 增加自定义属性,解析应用自定义属性    }        @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mWidth = w;        mHeight = h;                //计算外环的半径 得到控件宽高的最小值作为圆的半径,还要减去掉描边的宽度        mOutRadius = (Math.min(w, h))/2-mStrokeWidth;        //计算进度圆的半径,减去两倍描边宽度,作为进度圆和外圆环之间的间隙        mInnerRiadius =mOutRadius-2*mStrokeWidth;        //确定进度圆的范围        mProgressOval = new RectF(mWidth / 2 - mInnerRiadius, mHeight / 2                - mInnerRiadius, mWidth / 2 + mInnerRiadius, mHeight                / 2 + mInnerRiadius);                int triangleHeight = mOutRadius/3;        //用三个点来确定三角形的位置,这里以外圆环直径的1/3作为三角形的水平方向的高度,        //水平方向向右做了 1/2高度的偏移,让三角形中心与圆的中心重叠(从视觉上来说是中心了,从科学的角度来讲这里应该不是中心,博主数学基础不扎实。。)        mTriangle = new Path();        mTriangle.moveTo(w/2-triangleHeight/2,w/2-triangleHeight);        mTriangle.lineTo(w/2+triangleHeight+triangleHeight/2,h/2);        mTriangle.lineTo(w/2-triangleHeight/2,w/2+triangleHeight);        mTriangle.close();        //等边三角形//        mRantange = new Path();//        float halfOfRantangeHeight = (float) (Math.sqrt(1f/27*Math.pow(mOutRadius*2,2)));//        Log.e("xxx","mOutRadius/3="+mOutRadius/3+" ,halfOfRantangeHeight="+halfOfRantangeHeight);//        mRantange.moveTo(w/2-mOutRadius/6,h/2-halfOfRantangeHeight);//        mRantange.lineTo(w/2+mOutRadius/3+mOutRadius/6,h/2);//        mRantange.lineTo(w/2-mOutRadius/6,h/2+halfOfRantangeHeight);//        mRantange.close();            }        @Override    protected void onDraw(Canvas canvas) {        //绘制外圆环        canvas.drawCircle(mWidth/2,mHeight/2,mOutRadius,mStrokePaint);        if (mCurrentState==ProgressState.RUNNING) {
//运行状态,绘制进度圆 canvas.drawArc(mProgressOval,-90,(mProgress*1f/mMax*DEFAULT_MAX_ANGLE),true,mFillPaint); }else{
//非运行状态画三角形 canvas.drawPath(mTriangle,mStrokePaint); } } @Override public void onClick(View v) { switch (mCurrentState) { case PRE_START: if (listener != null) { listener.onStart(); } mCurrentState = ProgressState.RUNNING; break; case RUNNING: if (listener != null) { listener.onPause(mProgress * 100 / mMax); } mCurrentState = ProgressState.PAUSE; invalidate(); break; case PAUSE: if (listener != null) { listener.onStart(); } mCurrentState = ProgressState.RUNNING; invalidate(); break; case COMPLETELY: if (listener!=null) { listener.onCompletedClick(); } break; } } private OnProgressClickListener listener; /** * 设置最大值 * @param max 最大值 */ public void setMax(int max){ mMax=max; } /** * 设置当前进度 * @param progress 当前进度 */ public void setProgress(int progress){ mProgress=progress; if (mCurrentState!=ProgressState.RUNNING) { mCurrentState=ProgressState.RUNNING; } if (mProgress>=mMax) { mCurrentState=ProgressState.COMPLETELY; if (listener!=null) {
//进度圆完成回调 listener.onCompletely(); } } invalidate(); } /** * 设置监听事件 * @param l 监听器 */ public void setOnProgressClickListener(OnProgressClickListener l) { this.listener = l; } /** * 这里提供了四个回调方法,比较多,可能只用到其中几个, * 所以采用了抽象类来实现,除了必要的开始操作以外, * 其他的操作用户需要哪个方法自己复写就行了。 */ public static abstract class OnProgressClickListener { /** 开始 */ public abstract void onStart(); /** 暂停 */ public void onPause(int percent){}; /** 结束 */ public void onCompletely(){}; /** 完成后点击 */ public void onCompletedClick(){}; } /**控件状态*/ public enum ProgressState{ /**开始之前*/ PRE_START, /**运行*/ RUNNING, /**暂停*/ PAUSE, /**完成*/ COMPLETELY; } }

接下来我们说说怎么使用,现在xml中定义我们的自定义控件。

然后我们在Activity中模拟一下缓冲视频,并且播放的操作。

package com.lwd.playbutton;    import com.lwd.bufferbutton.R;import com.lwd.playbutton.PlayButton.OnProgressClickListener;import android.app.Activity;import android.os.Bundle;import android.os.SystemClock;import android.widget.Toast;/** * 模拟视频缓冲的activity * @author Vitor Lee */public class MainActivity extends Activity {    private static final int DEFAULT_MAX_VALUE = 100;    private int mProgress = 0;    private PlayButton mProgressView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mProgressView = (PlayButton) findViewById(R.id.buffer_button);        mProgressView.setOnProgressClickListener(getProgressClickListener());        mProgressView.setMax(DEFAULT_MAX_VALUE);    }    private OnProgressClickListener getProgressClickListener() {        return new OnProgressClickListener() {                        private Thread mDownloadThread;            private boolean isStop;                        @Override            public void onStart() {
//模拟下载 if (mDownloadThread==null) { mDownloadThread = new Thread() { @Override public void run() { while (true) { if (!isStop) { runOnUiThread(new Runnable() { @Override public void run() { mProgressView.setProgress(mProgress); mProgress++; } }); if (mProgress==DEFAULT_MAX_VALUE) { break; } } SystemClock.sleep(100); } } }; mDownloadThread.start(); } isStop=false; } @Override public void onPause(int percent) {
//暂停 isStop=true; } @Override public void onCompletely() { Toast.makeText(MainActivity.this, "完成", 1).show(); } @Override public void onCompletedClick() {
//缓冲完成之后点击播放 Toast.makeText(MainActivity.this, "播放", 1).show(); } }; }}

 

你可能感兴趣的文章
C++中struct和class的区别 [转]
查看>>
C++ ofstream和ifstream详细用法
查看>>
【G-BLASTN 1.0正式发布】
查看>>
Mysql 连接查询 Mysql支持的连接查询有哪些
查看>>
wireshark tcp 协议分析 z
查看>>
Need a code of lazy load for div--reference
查看>>
HTable和HTablePool使用注意事项
查看>>
如何使用JW Player来播放Flash并隐藏控制按钮和自定义播放完成后执行的JS
查看>>
04 http协议模拟登陆发帖
查看>>
Codeforces Round #298 (Div. 2) B. Covered Path 物理题/暴力枚举
查看>>
百度地图定位地址为空
查看>>
云计算设计模式(五)——计算资源整合模式
查看>>
关于classpath
查看>>
[数据库事务与锁]详解一: 彻底理解数据库事务
查看>>
Debug和Release区别
查看>>
Android 手机卫士--打包生成apk维护到服务器
查看>>
Python下载
查看>>
通过微软认证所需费用
查看>>
JAVA实现拼图游戏
查看>>
Azure运维系列 6:使用自定义映像创建虚拟机
查看>>