闲着,尝试实现了新版微信视频播放按钮,使用的是自定义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. 向Array中添加堆排序

    堆排序思路 堆排序是一种树形选择排序方法(注意下标是从1开始的,也就是R[1...n]). 1) 初始堆: 将原始数组调整成大根堆的方法——筛选算法:比较R[2i].R[2i+1]和R[i],将最大者 ...

  2. 6、android 普通日志输出到SD卡

    这是本人见过写博文最负责的一个人: http://www.crifan.com/android_try_use_android_logging_log4j_to_output_log_to_sd_ca ...

  3. 使用sqlserver日期函数获取当前日期

    使用sqlserver日期函数中的getdate()可以获取当现的日期,下面就将为您介绍这种使用sqlserver日期函数获取当前日期的方法,供您参考,希望对您学习sqlserver日期函数有所启迪. ...

  4. Javascript中常用事件的命名

    OnClick :单击事件 OnChange:改变事件 OnSelect:选中事件 OnFocus:获得焦点事件 OnBlur:失去焦点事件 Onload:载入文件 OnUnload:卸载文件 anc ...

  5. Geo-Fence

    转自:http://blog.jobbole.com/86633/ 地理围栏(Geo-fencing)是LBS的一种应用,就是用一个虚拟的栅栏围出一个虚拟地理边界,当手机进入.离开某个特定地理区域,或 ...

  6. hdu 1043 Eight 经典八数码问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...

  7. 【BZOJ】【3894】文理分科

    网络流/最小割 rausen大爷太神辣-作为一个蒟蒻还是搬运题解吧…… 很明显的一道网络流题.. 首先把所有值的加起来,再减掉网络流最小割值就好了,问题就是如何建图.这貌似也是考了好多次了的... 把 ...

  8. Segment Tree with Lazy 分类: ACM TYPE 2014-08-29 11:28 134人阅读 评论(0) 收藏

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; stru ...

  9. Windows+Apache+MySQL+PHP(WAMP)环境搭建

    运行操作系统:Windows Server 2008 R2 Apache版本:Apache 2.2 MySQL版本:MySQL 5.5 PHP版本:PHP 5.6.14(当前最新版) 更新日期:201 ...

  10. linux centos yum 安装 rar

    linux yum安装rar时,可能会出现无资源的错误,只需把配置好资源即可,具体操作如下: 1.# vi /etc/yum.repos.d/dag.repo 2.将以下内容写入文件中 [dag] n ...