闲着,尝试实现了新版微信视频播放按钮,使用的是自定义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 = ;
/**默认最大的进度*/
private static final int DEFAULT_MAX_PROGRESS=;
/**描边宽度*/
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,);
} 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, , 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))/-mStrokeWidth;
//计算进度圆的半径,减去两倍描边宽度,作为进度圆和外圆环之间的间隙
mInnerRiadius =mOutRadius-*mStrokeWidth;
//确定进度圆的范围
mProgressOval = new RectF(mWidth / - mInnerRiadius, mHeight /
- mInnerRiadius, mWidth / + mInnerRiadius, mHeight
/ + mInnerRiadius); int triangleHeight = mOutRadius/;
//用三个点来确定三角形的位置,这里以外圆环直径的1/3作为三角形的水平方向的高度,
//水平方向向右做了 1/2高度的偏移,让三角形中心与圆的中心重叠(从视觉上来说是中心了,从科学的角度来讲这里应该不是中心,博主数学基础不扎实。。)
mTriangle = new Path();
mTriangle.moveTo(w/-triangleHeight/,w/-triangleHeight);
mTriangle.lineTo(w/+triangleHeight+triangleHeight/,h/);
mTriangle.lineTo(w/-triangleHeight/,w/+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/,mHeight/,mOutRadius,mStrokePaint);
if (mCurrentState==ProgressState.RUNNING) {//运行状态,绘制进度圆
canvas.drawArc(mProgressOval,-,(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 * / 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中定义我们的自定义控件。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}"
android:background="@android:color/black" > <com.lwd.playbutton.PlayButton
android:id="@+id/buffer_button"
android:layout_width="50dp"
android:layout_height="50dp"
/> </RelativeLayout>

然后我们在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 = ;
private int mProgress = ;
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();
}
}
};
mDownloadThread.start();
}
isStop=false;
} @Override
public void onPause(int percent) {//暂停
isStop=true;
} @Override
public void onCompletely() {
Toast.makeText(MainActivity.this, "完成", ).show();
} @Override
public void onCompletedClick() {//缓冲完成之后点击播放
Toast.makeText(MainActivity.this, "播放", ).show();
} };
}
}

Android 自定义View,仿微信视频播放按钮的更多相关文章

  1. Android自定义View——仿滴滴出行十大司机评选活动说明

    滴滴出行原版图 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 仿图 ? ? ? ? ? ? 1.分 ...

  2. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  3. Android自定义View(LimitScrollerView-仿天猫广告栏上下滚动效果)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53303872 本文出自:[openXu的博客] 1分析 2定义组合控件布局 3继承最外层控件 ...

  4. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  5. Android 自定义 View 圆形进度条总结

    Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...

  6. 简单说说Android自定义view学习推荐的方式

    这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧.  以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...

  7. Android自定义View之ProgressBar出场记

    关于自定义View,我们前面已经有三篇文章在介绍了,如果筒子们还没阅读,建议先看一下,分别是android自定义View之钟表诞生记.android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检 ...

  8. android自定义View之NotePad出鞘记

    现在我们的手机上基本都会有一个记事本,用起来倒也还算方便,记事本这种东东,如果我想要自己实现,该怎么做呢?今天我们就通过自定义View的方式来自定义一个记事本.OK,废话不多说,先来看看效果图. 整个 ...

  9. android 自定义view 前的基础知识

    本篇文章是自己自学自定义view前的准备,具体参考资料来自 Android LayoutInflater原理分析,带你一步步深入了解View(一) Android视图绘制流程完全解析,带你一步步深入了 ...

随机推荐

  1. 软件工程随堂小作业——随机四则运算(C++)

    一.设计思路: 1.程序的主体部分是循环输出,次数即题目数目由用户输入: 2.三个整型变量+rand函数来实现随机数四则运算,一个变量代表加减乘除,另外两个用作运算数: 3.用户体验:题目分三列,排列 ...

  2. mui开发

    http://blog.csdn.net/sunhuaqiang1/article/details/46848005

  3. 老周的ABP框架系列教程 -》 一、框架理论初步学习

    老周的ABP框架系列教程 -- 一.框架理论初步学习   1. ABP框架的来源与作用简介 1.1  简介 1.1.1       ABP框架全称为"ASP.NET Boilerplate ...

  4. 如何在Win10下设置图片的浏览方式为windows照片查看器

    小编前些天刚装好了win10,一阵心奋啊,今天刚打开一个图片,却发现图片的默认打开方式是window应用商店的app, 这让我觉得特别不舒服,没有之前windows自带的照片查看器好用,后来我本想进入 ...

  5. 【Binary Tree Inorder Traversal】cpp

    题目: Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary ...

  6. HTML 表格生成

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 离线+线段树

    题目链接: http://codeforces.com/contest/703/problem/D D. Mishka and Interesting sum time limit per test ...

  8. C++中定义比较函数的三种方法

    原文地址:http://fusharblog.com/3-ways-to-define-comparison-functions-in-cpp/ C++编程优与Pascal的原因之一是C++中存在ST ...

  9. Rich Text Editor for MVC

    在网站开发中难免会用到富文本编辑器,本文将介绍一款富文本编辑器(在线HTML编辑器) Rich Text Editor ,简要说明一下其在MVC中的使用. 具体使用情况和下载地址请参考:http:// ...

  10. 2014ACM/ICPC亚洲区鞍山站 清华命题

    A http://acm.hdu.edu.cn/showproblem.php?pid=5070 先跳过. B http://acm.hdu.edu.cn/showproblem.php?pid=50 ...