标签:
//绘制进度条的X,Y坐标 private int marginXY = 0; //进度条背景,进度条,分隔线的paint private Paint progressbarBackgroundPaint, progressbarPaint, separtatedPaint; //视频总数 private int videoSum = 6; //画笔的宽度 private int strokeWidth = 20; //进度条线程实例 private CustomProgressRunnable customProgressRunnable; //进度条绘制标记位 private boolean startDrawProgress = false; //进度条的背景颜色 private int background; //分隔线的颜色 private int separtatedLineBackground; //进度条的颜色 private int progressbarBackground; //分隔线的宽度 private int separtatedLineWidth; //线程池 private ExecutorService executorService;
public CustomProgress(Context context , AttributeSet attrs, int defStyleAttr) {
super (context, attrs , defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomProgress) ;
videoSum = typedArray.getInt(R.styleable.CustomProgress_CP_Video_Sum, 3);
background = typedArray.getColor(R.styleable.CustomProgress_CP_Background, Color.parseColor("#F1F1F1" ));//F1F1F1
separtatedLineBackground = typedArray.getColor(R.styleable.CustomProgress_CP_Separated_Line_Background, Color.parseColor("#D6D6D6" ));
progressbarBackground = typedArray.getColor(R.styleable.CustomProgress_CP_Progressbar_Background, Color.parseColor("#5BD290" ));//5BD290
separtatedLineWidth = typedArray.getDimensionPixelSize(R.styleable.CustomProgress_CP_Separated_Line_Width, 5);
typedArray.recycle() ;
//
progressbarBackgroundPaint = new Paint() ;
progressbarBackgroundPaint .setAntiAlias(true) ;
progressbarBackgroundPaint .setStrokeCap(Paint.Cap.ROUND) ;
progressbarBackgroundPaint .setStrokeWidth(strokeWidth) ;
progressbarBackgroundPaint .setColor(background) ;
//
progressbarPaint = new Paint() ;
progressbarPaint .setAntiAlias(true) ;
progressbarPaint .setStrokeWidth(strokeWidth) ;
progressbarPaint .setStrokeCap(Paint.Cap.ROUND) ;
progressbarPaint .setColor(progressbarBackground) ;
separtatedPaint = new Paint() ;
separtatedPaint .setAntiAlias(true) ;
separtatedPaint .setStrokeWidth(strokeWidth) ;
separtatedPaint .setColor(separtatedLineBackground) ;
executorService = Executors.newCachedThreadPool();
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = MeasureSpec.getSize(widthMeasureSpec);
int finalWidth = size + getPaddingLeft() + getPaddingRight();
int finalHeight = strokeWidth + getPaddingBottom() + getPaddingTop();
setMeasuredDimension(finalWidth , finalHeight);
}
//开始绘制进度条的X,Y坐标 marginXY = strokeWidth / 2; //绘制背景进度 canvas.drawLine(marginXY, marginXY, getWidth() - marginXY, marginXY, progressbarBackgroundPaint);也许很多人不理解marginXY是什么意思呢?为了方便解释,请大家再看看下面的图。
//开始绘制进度条
if (startDrawProgress) {
//绘制当前进度
canvas.drawLine(marginXY, marginXY, getProgress(), marginXY, progressbarPaint);
}
//分隔线的X坐标(注意,这一步必须放在“开始绘制进度条”之后,否则绘制的进度条会把分隔线覆盖。)
int separtatedLineX = 0;
for (int i = 0; i < videoSum - 1; i++) {
//计算分隔线的X坐标
separtatedLineX += (getWidth() - 2 * marginXY) / videoSum;
//绘制分隔线
// canvas.drawLine(marginXY + separtatedLineX - (separtatedLineWidth / 2), marginXY, marginXY + separtatedLineX + (separtatedLineWidth/2), marginXY, separtatedPaint);
// canvas.drawLine(separtatedLineX , marginXY, separtatedLineX + separtatedLineWidth , marginXY, separtatedPaint);
canvas.drawLine(marginXY + separtatedLineX - (separtatedLineWidth / 2), marginXY, marginXY + separtatedLineX + (separtatedLineWidth / 2), marginXY, separtatedPaint);
}
}
private Handler handler; private Thread thread; private VideoView videoView; //视频进度条的长度 private int perVideoLength; //当前正在播放视频的下标(下标从0开始) private int currentVideoIndex; //线程正在运行标记位 private boolean running = false; //线程正在等待标记位 private boolean waiting = false;
public CustomProgressRunnable(Handler handler, VideoView videoView, int currentVideoIndex) {
this.handler = handler;
this.currentVideoIndex = currentVideoIndex;
this.perVideoLength = (getWidth() - 2 * marginXY) / videoSum;
this.videoView = videoView;
thread = new Thread(this);
//设置进度条的最大进度值
setMax((currentVideoIndex + 1) * perVideoLength + marginXY);
}
下图中绿色线@Override
public void run() {
//当前视频开始的位置
int currentVideoStartPosition = (currentVideoIndex * perVideoLength);
while (currentVideoStartPosition < getMax()) {
synchronized (this) {
if (!running) {
break;
}
if (waiting) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
execute(currentVideoStartPosition);
}
}
public void execute(int currentVideoStartPosition) {
if (running && !waiting) {
int videoDuration = videoView.getDuration();
if (videoDuration != -1) {
//获取比例
float proportion = (float) videoView.getCurrentPosition() / (float) videoDuration;
//计算移动进度
int currentVideoPosition = (int) (proportion * perVideoLength);
//计算当前最新进度
int newestVideoPosition = currentVideoPosition + currentVideoStartPosition + marginXY;
// CommonTool.showLog("测试:" + newestVideoPosition + " " + videoView.getCurrentPosition() + " " + videoView.getDuration() + " " + proportion + " " + perVideoLength);
handler.sendMessage(Message.obtain(handler, newestVideoPosition));
}
}
}
class TestHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int temp = msg.what;
//每设置一次setProgress的值就会调用onDraw方法
setProgress(temp);
}
}
//开始线程
public void start() {
running = true;
executorService.execute(thread);
}
//挂起线程
public void suspend() {
if (waiting) {
return;
}
synchronized (this) {
this.waiting = true;
}
}
//恢复线程
public void resume() {
if (!waiting) {
return;
}
synchronized (this) {
this.waiting = false;
this.notifyAll();
}
}
//停止线程
public void stop() {
if (!running) {
return;
}
synchronized (this) {
running = false;
}
}
/**
* 开始进度条
*
* @param videoView
* @param currentVideoIndex
*/
public void startProgress(VideoView videoView, int currentVideoIndex) {
if (currentVideoIndex > videoSum) {
Log.e("-------------------->", "当前视频下标不能大于视频总数");
return;
}
customProgressBarRunnable = new CustomProgressBarRunnable(new TestHandler(), videoView, currentVideoIndex);
//开启一个线程更新进度条
customProgressBarRunnable.start();
startDrawProgress = true;
}
public void hangUpThread() {
if (customProgressBarRunnable == null) {
return;
}
customProgressBarRunnable.suspend();
Log.e("-------------------->", "挂起线程!");
}
public void recoverThread() {
if (customProgressBarRunnable == null) {
return;
}
customProgressBarRunnable.resume();
Log.e("-------------------->", "恢复线程!");
}
public void stopThread() {
if (customProgressBarRunnable == null) {
return;
}
customProgressBarRunnable.stop();
Log.e("-------------------->", "停止线程!");
}
/**
* 关闭线程池
*/
public void closeThreadPool() {
executorService.shutdown();
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F2F2F2"
android:orientation="vertical">
<TextView
android:id="@+id/txt_bar_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:background="#33C774"
android:gravity="center_horizontal|center_vertical"
android:text="视频"
android:textColor="#ffffff"
android:textSize="16dp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="作者:Edward"
android:textSize="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Android自定义控件---继承ProgressBar功能扩展\n"
android:textSize="14dp" />
<TextView
android:id="@+id/txt_video_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="2/15"
android:textSize="14dp" />
<per.edward.ui.CustomProgressBar
android:id="@+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/image_prev_video"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginRight="30dp"
android:layout_toLeftOf="@+id/image_play_stop"
android:onClick="onClick"
android:src="@mipmap/video_left" />
<ImageView
android:id="@+id/image_play_stop"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:onClick="onClick"
android:src="@mipmap/video_play" />
<ImageView
android:id="@+id/image_netx_video"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:layout_toRightOf="@+id/image_play_stop"
android:onClick="onClick"
android:src="@mipmap/video_right" />
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
<per.edward.ui.CustomProgressBar
android:id="@+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
/**
* 播放视频页面
* Created by Edward on 2016/4/15.
*/
public class MainActivity extends Activity {
//视频视图实例
private VideoView videoView;
//视频路径列表
private ArrayList<String> videoUriList;
//咋们写的自定义控件
private CustomProgressBar progressBar;
//播放视频按钮
private ImageView imagePlayStop;
//用来显示当前视频下标以及视频的总数
private TextView txtVideoNumber;
//当前视频的下标
private int currentVideoIndex = 0;
//是否开启视频线程标记位
private boolean isOpenVideoThread = false;
//获取内部类实例
private CustomProgressBar.CustomProgressBarRunnable customProgressBarRunnable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoView = (VideoView) findViewById(R.id.video_view);
videoUriList = new ArrayList<>();
progressBar = (CustomProgressBar) findViewById(R.id.progressbar);
imagePlayStop = (ImageView) findViewById(R.id.image_play_stop);
txtVideoNumber = (TextView) findViewById(R.id.txt_video_number);
initData();
setCallBackListener();
}
public void initData() {
int[] videosId = {R.raw.bbb, R.raw.aaa, R.raw.ccc};
//获取raw文件夹内视频
for (int i = 0; i < videosId.length; i++) {
videoUriList.add("android.resource://" + getPackageName() + "/" + videosId[i]);
}
//设置视频段数
progressBar.setVideoSum(videoUriList.size());
txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size());
}
/**
* 设置回调监听事件
*/
public void setCallBackListener() {
//视频播放完毕之后回调此方法,关闭线程
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//将绘制进度条的线程暂停
progressBar.stopThread();
//将视频下标移动下一个
++currentVideoIndex;
//如果没有视频
if (currentVideoIndex > videoUriList.size() - 1) {
Toast.makeText(MainActivity.this, "没有视频了", Toast.LENGTH_LONG).show();
//更换播放视频按钮的图标
imagePlayStop.setImageResource(R.mipmap.video_play);
//将当前视频的下标设为0
currentVideoIndex = 0;
//将开启线程的标记位设置false
isOpenVideoThread = false;
} else {
//每当一个视频播放结束之后,再播放下一个视频。
openVideoThread(currentVideoIndex);
txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size());
}
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(MainActivity.this, "视频播放错误!", Toast.LENGTH_LONG).show();
return false;
}
});
}
public void onClick(View v) {
switch (v.getId()) {
//播放或暂停视频
case R.id.image_play_stop:
imagePlayStop();
break;
//下一个视频
case R.id.image_netx_video:
++currentVideoIndex;
if (currentVideoIndex > videoUriList.size() - 1) {
Toast.makeText(MainActivity.this, "没有视频了", Toast.LENGTH_LONG).show();
currentVideoIndex = videoUriList.size() - 1;
} else {
isOpenVideoThread = false;
progressBar.stopThread();
imagePlayStop.setImageResource(R.mipmap.video_stop);
txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size());
openVideoThread(currentVideoIndex);
}
break;
//上一个视频
case R.id.image_prev_video:
--currentVideoIndex;
if (currentVideoIndex < 0) {
Toast.makeText(MainActivity.this, "没有视频了", Toast.LENGTH_LONG).show();
++currentVideoIndex;
} else {
isOpenVideoThread = false;
progressBar.stopThread();
imagePlayStop.setImageResource(R.mipmap.video_stop);
txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size());
openVideoThread(currentVideoIndex);
}
break;
}
}
/**
* 视频播放与暂停
*/
public void imagePlayStop() {
txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size());
//如果没有开启视频(线程),那么就打开
if (!isOpenVideoThread) {
imagePlayStop.setImageResource(R.mipmap.video_stop);
openVideoThread(currentVideoIndex);
} else {
customProgressBarRunnable = progressBar.getCustomProgressBarRunnable();
//当前视频线程打开了之后,如果线程处于运行状态,那么就挂起,否则恢复线程。
if (!customProgressBarRunnable.isWaiting()) {
//挂起进度条的线程
progressBar.hangUpThread();
//暂停视频播放
videoView.pause();
imagePlayStop.setImageResource(R.mipmap.video_play);
} else {
//恢复进度条的线程
progressBar.recoverThread();
//开始视频播放
videoView.start();
imagePlayStop.setImageResource(R.mipmap.video_stop);
}
}
}
/**
* 开启视频线程
*
* @param currentVideoIndex
*/
public void openVideoThread(int currentVideoIndex) {
//把线程标记位设为已开启
isOpenVideoThread = true;
//设置uri
videoView.setVideoURI(Uri.parse(videoUriList.get(currentVideoIndex)));
//开始视频播放
videoView.start();
//开启进度条绘制
progressBar.startProgress(videoView, currentVideoIndex);
}
@Override
protected void onPause() {
CustomProgressBar.CustomProgressBarRunnable customProgressBarRunnable = progressBar.getCustomProgressBarRunnable();
//当APP进入“不可见”状态的时候(例如返回桌面,锁屏,跳转到另一个Activity等情况),将视频暂停
if (customProgressBarRunnable != null && !customProgressBarRunnable.isWaiting())
imagePlayStop();
super.onPause();
}
/**
* 在该页面被销毁之前,关闭线程池,停止线程
*/
@Override
protected void onDestroy() {
progressBar.closeThreadPool();
progressBar.stopThread();
super.onDestroy();
}
}
Android自定义控件---继承ProgressBar功能扩展
标签:
原文地址:http://blog.csdn.net/u012814441/article/details/51350871