您的位置:首页 > 移动开发 > Android开发

android视频缓冲进度条SeekBar有断断续续的间断效果

2015-09-02 11:52 639 查看
最近要弄个播放器,但是SeekBar没有断断续续的效果都是连续的进度。查了点资料自己重写一个,主要原理是利用Region不断的求并集 实现断断续续的效果:



1.继承SeekBar自定义类中重写onDraw(Canvas canvas)方法 绘制进度条

protected synchronized void onDraw(Canvas canvas) {
if(progressBarWidth!=0&&progressBarWidth!=getWidth()){
changeSizeScale=(float)getWidth()/(float)progressBarWidth;
}
progressBarWidth = getWidth();
progressBarHeight = getHeight();
int pTop=(progressBarHeight-seekBarBgHeight)/2;
int pBottom=(progressBarHeight-seekBarBgHeight)/2+seekBarBgHeight;
Drawable thumb=getThumb();
//绘制进度条背景
Rect bgRect = new Rect(0,pTop,progressBarWidth,pBottom);
canvas.drawRect(bgRect, bgPaint);
//绘制缓冲进度
drawCachProgress(canvas,progressBarWidth,pTop,pBottom);

//绘制播放进度
Rect progressRect = new Rect(0,pTop,thumb.getBounds().left,pBottom);
canvas.drawRect(progressRect, progressPaint);
//绘制控制点
canvas.drawBitmap(controlPointBitmap,thumb.getBounds().left,progressBarHeight/2-controlPointBitmap.getWidth()/2,null);
}


2.绘制缓冲进度条,(播放进度、背景、控制点都是比较简单的方法实现不多说)。缓冲进度条就是要根据 getSecondaryProgress 进度 不断更新currentRect 的位置,(currentRect 标识上一次进度-----到----当前进度 的距离) 每一次更新这段距离
都与全局变量cachRegion求并集(就是把每段更新的距离都保存到cachRegion中)在一次性的画出cachRegion中的内容。这样可以保证无论怎么拖动进度条更新都是正确的会有断断续的效果
int secondProg=getSecondaryProgress();
float scale=(float)secondProg/(float)getMax();

if((secondProg-lastCachProg)>=0&&(secondProg-lastCachProg)<=2000){//小于2s的都视为没有拖动
if(currentRect==null){
currentRect= new Rect(0,pTop,(int)(scale*progressBarWidth),pBottom);
}
currentRect.right=(int)(scale*progressBarWidth);
}else{//手指拖动了 重新定位
if(currentRect!=null){
currentRect.left=(int)(scale*progressBarWidth);//定位到新的位置
currentRect.right=(int)(scale*progressBarWidth)+1;
}
}
lastCachProg=secondProg;
if(currentRect!=null){
getCachRegion(pTop,pBottom).op(currentRect, Op.UNION);//求并集
}
drawRegion(canvas,getCachRegion(pTop,pBottom),cachPaint);//绘制并集
这里我们播放器更新缓冲进度都是缓冲时间所以才有上边的 //小于2s的都视为没有拖动

----------------------------全部代码------------------------------------

package com.stream.media.seekbar;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.RegionIterator;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.SeekBar;
import com.zte.rtmpplayerdemo.R;

public class SeekBarExt extends SeekBar{
private Bitmap controlPointBitmap;//控制点图片
int seekBarBgHeight=12;//进度条背景宽度
Paint progressPaint;//进度条画笔
Paint bgPaint;//背景画笔
Paint cachPaint;//缓冲进度条画笔
int progressBarWidth=0;
int progressBarHeight=0;
private int lastCachProg=0;//secondProgress的上一次位置
private Region cachRegion;//缓冲进度条已缓冲区域
private Rect currentRect;//当前缓冲进度更新的一段距离
private float changeSizeScale;//全屏切换缩放比例

public SeekBarExt(Context context) {
super(context);
init(context);
}

public SeekBarExt(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

public SeekBarExt(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}

private void init(Context context){
controlPointBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.btn_control_points);
progressPaint=new Paint();
progressPaint.setColor(getResources().getColor(R.color.seekbar_progresscolor));
bgPaint=new Paint();
bgPaint.setColor(getResources().getColor(R.color.seekbar_bg));
cachPaint=new Paint();
cachPaint.setColor(getResources().getColor(R.color.seekbar_cachcolor));
}

@SuppressLint("DrawAllocation")
@Override
protected synchronized void onDraw(Canvas canvas) {
if(progressBarWidth!=0&&progressBarWidth!=getWidth()){//进度条大小是否改变
changeSizeScale=(float)getWidth()/(float)progressBarWidth;
}
progressBarWidth = getWidth();
progressBarHeight = getHeight();
int pTop=(progressBarHeight-seekBarBgHeight)/2;
int pBottom=(progressBarHeight-seekBarBgHeight)/2+seekBarBgHeight;
Drawable thumb=getThumb();
//绘制进度条背景
Rect bgRect = new Rect(0,pTop,progressBarWidth,pBottom);
canvas.drawRect(bgRect, bgPaint);
//绘制缓冲进度
drawCachProgress(canvas,progressBarWidth,pTop,pBottom);

//绘制播放进度
Rect progressRect = new Rect(0,pTop,thumb.getBounds().left,pBottom);
canvas.drawRect(progressRect, progressPaint);
//绘制控制点
canvas.drawBitmap(controlPointBitmap,thumb.getBounds().left,progressBarHeight/2-controlPointBitmap.getWidth()/2,null);
}
//计算绘制缓冲进度
private void drawCachProgress(Canvas canvas,int progressBarWidth,int pTop,int pBottom){
if(changeSizeScale!=0){//进度条尺寸变化了重新计算一遍已缓冲进度
Region region=getCachRegion(pTop,pBottom);
cachRegion=new Region(0, pTop,1, pBottom);
RegionIterator iter = new RegionIterator(region);
Rect r = new Rect();
while (iter.next(r)) {
r.set((int)(r.left*changeSizeScale), r.top,(int)(r.right*changeSizeScale), r.bottom);
cachRegion.op(r, Op.UNION);//求并集
}
changeSizeScale=0;
}

int secondProg=getSecondaryProgress();
float scale=(float)secondProg/(float)getMax();

if((secondProg-lastCachProg)>=0&&(secondProg-lastCachProg)<=2000){//小于2s的都视为没有拖动
if(currentRect==null){
currentRect= new Rect(0,pTop,(int)(scale*progressBarWidth),pBottom);
}
currentRect.right=(int)(scale*progressBarWidth);
}else{//手指拖动了 重新定位
if(currentRect!=null){
currentRect.left=(int)(scale*progressBarWidth);//定位到新的位置
currentRect.right=(int)(scale*progressBarWidth)+1;
}
}
lastCachProg=secondProg;
if(currentRect!=null){
getCachRegion(pTop,pBottom).op(currentRect, Op.UNION);//求并集
}
drawRegion(canvas,getCachRegion(pTop,pBottom),cachPaint);//绘制并集
}

//绘制并集
private void drawRegion(Canvas canvas,Region rgn,Paint paint)
{
RegionIterator iter = new RegionIterator(rgn);
Rect r = new Rect();
while (iter.next(r)) {
canvas.drawRect(r, paint);
}
}
//懒加载
private Region getCachRegion(int pTop,int pBottom) {
if(cachRegion==null){
cachRegion=new Region(0, pTop,1, pBottom);
}
return cachRegion;
}

}


使用:

<com.stream.media.seekbar.SeekBarExt
android:id="@+id/mediaPlayer_seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:layout_gravity="center_vertical"
android:max="100"
android:progress="0"
>
</com.stream.media.seekbar.SeekBarExt>


seekbar.setMax(videoConutTime); //我们的播放器进度都是毫秒值

seekbar.setProgress(videoPlayTime);//我们的播放器进度都是毫秒值

seekbar.setSecondaryProgress(iSeconds);//我们的播放器进度都是毫秒值

主要原理是利用Region不断的求并集 实现断断续续的效果,Region还有好多用法不断学习中。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: