android视频缓冲进度条SeekBar有断断续续的间断效果
2015-09-02 11:52
696 查看
最近要弄个播放器,但是SeekBar没有断断续续的效果都是连续的进度。查了点资料自己重写一个,主要原理是利用Region不断的求并集 实现断断续续的效果:
1.继承SeekBar自定义类中重写onDraw(Canvas canvas)方法 绘制进度条
2.绘制缓冲进度条,(播放进度、背景、控制点都是比较简单的方法实现不多说)。缓冲进度条就是要根据 getSecondaryProgress 进度 不断更新currentRect 的位置,(currentRect 标识上一次进度-----到----当前进度 的距离) 每一次更新这段距离
都与全局变量cachRegion求并集(就是把每段更新的距离都保存到cachRegion中)在一次性的画出cachRegion中的内容。这样可以保证无论怎么拖动进度条更新都是正确的会有断断续的效果
----------------------------全部代码------------------------------------
使用:
seekbar.setMax(videoConutTime); //我们的播放器进度都是毫秒值
seekbar.setProgress(videoPlayTime);//我们的播放器进度都是毫秒值
seekbar.setSecondaryProgress(iSeconds);//我们的播放器进度都是毫秒值
主要原理是利用Region不断的求并集 实现断断续续的效果,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还有好多用法不断学习中。。。。。
相关文章推荐
- Android中ListView.getCount()与ListView.getChildCount()区别和OnScrollListener()各个参数的区别
- android sharePreference的使用
- Android四大组建之Service
- Android中的长度单位详解(dp、sp、px、in、pt、mm)
- android性能优化--overdraw优化
- Android 查看內存使用
- Android如何防止apk程序被反编译
- 如何给你的Android 安装文件(APK)瘦身
- 使用 Android NDK 重用现有的 C 代码
- Android 动态布局实现多主题切换
- 使用 Android NDK 重用现有的 C 代码
- Android x86模拟器Intel Atom x86 System Image配置与使用方法
- Android小知识点、小疑问之 ListView中的灵异事件ListView跟Button 不能同时点击
- [轉]Android的内存泄漏和调试
- Android之Activity的启动方式
- Android 官方推荐 : DialogFragment 创建对话框
- android studio 获取SHA1值
- Android中的dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()
- Android系统SVC命令教程
- Android WebView 与JS的数据交互