手機(jī)qq里面發(fā)送小視頻有個(gè)功能是,分段錄制視頻魄懂,就是錄制的時(shí)候沿侈,可以停下來(lái)闯第,然后再接著錄。這個(gè)功能目前被我們的項(xiàng)目使用到了缀拭,于是咳短,我就自定義了一個(gè)SeekBar填帽,給錄制視頻,編輯視頻咙好,播放視頻使用篡腌。
進(jìn)度條主要包括兩個(gè)部分:進(jìn)度條和可以拖動(dòng)的圖片
和qq的進(jìn)度條有點(diǎn)不同的是,我的進(jìn)度條勾效,到達(dá)100%的時(shí)候嘹悼,是沒(méi)有填充滿的,看下圖
我預(yù)留了一個(gè)圖片的位置給剪切的那個(gè)圖片层宫。
當(dāng)我滑動(dòng)或者點(diǎn)擊圖片的時(shí)候杨伙,我們就要去編輯這幾段視頻了(圖片中有5段視頻),比如說(shuō)我點(diǎn)擊了一次剪切圖片萌腿,就會(huì)變成下圖:
圖片中有白色的分割線限匣,我們叫斷點(diǎn),每個(gè)斷點(diǎn)就表示毁菱,之前在這個(gè)位置錄視頻的時(shí)候暫停過(guò)米死。大致功能就是這樣啦。上代碼吧
public class SeekVideoBar extends SeekBar implements GestureDetector.OnGestureListener { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
private Bitmap controlPointBitmap;
Paint progressPaint;//繪制進(jìn)度的筆
Paint bgPaint;//繪制進(jìn)度條背景顏色的筆
Paint cachPaint;//繪制二級(jí)緩存的筆
Paint pointPaint;//繪制斷點(diǎn)的筆
int progressBarWidth = 0;
int progressBarHeight = 0;//整個(gè)view的高度贮庞,一般情況是thumb的高度
int progressHeight = 12;//進(jìn)度條的高度
private int state = 1;
public static final int STATE_MAKING = 0;
public static final int STATE_EDITING = 1;
public static final int STATE_PLAYING = 2;
private GestureDetector detector;
public SeekVideoBar(Context context) {super(context);init(context);}
public SeekVideoBar(Context context, AttributeSet attrs) {super(context, attrs);init(context);}
public SeekVideoBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blank);
progressPaint = new Paint();
bgPaint = new Paint();
cachPaint = new Paint();
pointPaint = new Paint();
progressPaint.setColor(Color.parseColor("#ff1786EF"));
bgPaint.setColor(Color.parseColor("#90ffffff"));
cachPaint.setColor(Color.parseColor("#ffff0000"));
pointPaint.setColor(Color.parseColor("#ff000000"));
this.setOnSeekBarChangeListener(listener);
detector = new GestureDetector(context, this);}
@SuppressLint("DrawAllocation")@Override
protected synchronized void onDraw(Canvas canvas) {
progressBarWidth = getWidth();
progressBarHeight = getHeight();
int pTop = (progressBarHeight - progressHeight) / 2;
int pBottom = (progressBarHeight - progressHeight) / 2 + progressHeight;progressBarWidth = progressBarWidth - controlPointBitmap.getWidth();
Rect bgRect = new Rect(0, pTop, progressBarWidth + controlPointBitmap.getWidth(), pBottom);
canvas.drawRect(bgRect, bgPaint);//繪制背景峦筒,灰色部分
int sec = progressBarWidth * getSecondaryProgress() / 100;
Rect secProgressRect = new Rect(0, pTop, sec, pBottom);
canvas.drawRect(secProgressRect, cachPaint);//繪制二級(jí)緩存,紅色部分
int imgLeft = progressBarWidth * currentProgress / 100;
Rect progressRect = new Rect(0, pTop, imgLeft, pBottom);
canvas.drawRect(progressRect, progressPaint);//繪制進(jìn)度窗慎,藍(lán)色部分
drawPoints(canvas, pTop, pBottom);//繪制斷點(diǎn)
canvas.drawBitmap(controlPointBitmap, imgLeft, progressBarHeight / 2 - controlPointBitmap.getHeight() / 2, null);//繪制拖動(dòng)圖片
}
private Listpoints;
/* * 錄制視頻的是勘天,可以分段錄制,中間暫停的地方捉邢,會(huì)有一個(gè)Point斷點(diǎn) */
public void setPoints(Listpoints) {this.points = points;}
private void drawPoints(Canvas canvas, int pTop, int pBottom) {
if (points == null) {return;}
List tempPoints = new ArrayList();
tempPoints.addAll(points);
if (tempPoints.size() > 2) {
tempPoints.remove(0);//不繪制斷點(diǎn)0
}
for (int progress : tempPoints) {
int point = progressBarWidth * progress / 100;
Rect bgRect = new Rect(point, pTop, point + 2, pBottom);
canvas.drawRect(bgRect, bgPaint);
}
invalidate();
}
public void setState(int state) {
this.state = state;
if (state == STATE_EDITING) {//
if (currentProgress < mSecondProgress) {
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.video_cut_red);
} else {
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.video_cut);
}
bgPaint.setColor(Color.parseColor("#90ffffff"));
cachPaint.setColor(Color.parseColor("#ffff0000"));
} else if (state == STATE_MAKING) {//
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blank);
setSecondaryProgress(0);
} else {//
bgPaint.setColor(Color.parseColor("#ff000000"));
cachPaint.setColor(Color.parseColor("#90ffffff"));
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blank);
}
invalidate();
}
private boolean isScroll = false;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (state == STATE_EDITING) {//不是編輯階段觸碰無(wú)效
if (event.getAction() == MotionEvent.ACTION_UP && isScroll) {
//如果手指抬起來(lái)的時(shí)候脯丝,是滑動(dòng)結(jié)束,就把事件給原生的seekbar處理
return super.onTouchEvent(event);
} else {
//剩下的情況伏伐,都把事件傳遞給手勢(shì)
return detector.onTouchEvent(event);
}
} else {
return false;
}
}
private int BITMAP_STATE = 0;//0,表示normal宠进;1表示cut
private int currentProgress;//當(dāng)前的進(jìn)度
private int mSecondProgress;//制作視頻的時(shí)候的最大進(jìn)度
private OnSeekBarChangeListener listener = new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
currentProgress = progress;
if (state == STATE_MAKING) {// 視頻制作過(guò)程中
mSecondProgress = progress;
setSecondaryProgress(mSecondProgress);
return;
} else if (state == STATE_PLAYING) {// 視頻播放過(guò)程中
return;
} else {// 編輯階段
if (progress >= mSecondProgress) {
setProgress(mSecondProgress);//在編輯階段,如果當(dāng)前的進(jìn)度藐翎,超過(guò)了我們的最大進(jìn)度材蹬,就一直固定在最大進(jìn)度
if(BITMAP_STATE == 0){//不需要每次都重新加載
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.video_cut);
BITMAP_STATE = 1;
}
}else{
if(BITMAP_STATE == 1){//不需要每次都重新加載
controlPointBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.video_cut_red);
BITMAP_STATE = 0;
}
}
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//不是編輯狀態(tài)無(wú)法繼續(xù)
if (state != STATE_EDITING) {
return;
}
int index = 0;
int min = 100;
//點(diǎn)擊或者滑動(dòng)結(jié)束后,找到最近的斷點(diǎn)吝镣,然后跳轉(zhuǎn)過(guò)去
for (int i = 0; i < points.size(); i++) {
int progress = points.get(i);
int distance = Math.abs(progress - currentProgress);
if (min > distance) {
min = distance;
index = i;
}
}
cutBack(index);
}
};
private OnCutListener cutListener;
public void setOnCutListener(OnCutListener cutListener) {
this.cutListener = cutListener;
}
public interface OnCutListener {
public static final int KEEP_ALL = -1;
void onCut(int index);
}
@Override
public boolean onDown(MotionEvent arg0) {
isScroll = false;
return true;
}
@Override
public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
float arg3) {
return false;
}
@Override
public void onLongPress(MotionEvent arg0) {
}
@Override
public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
isScroll = true;
return super.onTouchEvent(arg1);
}
@Override
public void onShowPress(MotionEvent arg0) {
}
@Override
public boolean onSingleTapUp(MotionEvent ev) {
//點(diǎn)擊事件
int downX = (int) ev.getX();
int downY = (int) ev.getY();
int left = progressBarWidth * currentProgress / 100;
Rect r = new Rect(left, progressBarHeight / 2 - controlPointBitmap.getHeight() / 2, left + controlPointBitmap.getWidth(), progressBarHeight / 2 + controlPointBitmap.getHeight() / 2);
//如果點(diǎn)擊的范圍就是圖片的范圍堤器,就跳轉(zhuǎn)到前一個(gè)斷點(diǎn)
if (r.contains(downX, downY)) {
//找到當(dāng)前斷點(diǎn)的index
int index = 0;
for (int i = 0; i < points.size(); i++) {
if(points.get(i) == currentProgress){
index = i;
}
}
//找到前一個(gè)斷點(diǎn)
if(index == 0){
index = 0;
}else{
index = index - 1;
}
cutBack(index);
return true;
}
return super.onTouchEvent(ev);
}
private void cutBack(int index){
int progress = points.get(index );
setProgress(progress);
if (cutListener != null) {
if (index > points.size() - 2) {
cutListener.onCut(OnCutListener.KEEP_ALL);
} else {
cutListener.onCut(index);
}
}
}
}
在activity中這么使用
簡(jiǎn)書(shū)怎么貼代碼的。末贾。闸溃。好難看啊。。辉川。里面注釋還蠻多的表蝙,就不解釋啦
或者去下載資源吧,csdn不用積分的乓旗。府蛇。。
http://download.csdn.net/detail/xiaodousa/9613484
---------------------------------分割線----------------------------------
在寫這個(gè)自定義的seekbar我也遇到了問(wèn)題屿愚,還望大神教我
seekbar里面的可以拖動(dòng)的圖片汇跨,的位置
getThumb().getBounds().left//表示那個(gè)圖片的左邊的坐標(biāo),可是每次都存在偏差妆距;導(dǎo)致如果我繪制剪切的這個(gè)圖片的時(shí)候扰法,如果用這個(gè)left,就會(huì)不對(duì)毅厚;最后我改了方案塞颁,用了另外一個(gè)方式才實(shí)現(xiàn)的{getThumb()網(wǎng)上有重寫了一個(gè)getSeekBarThumb()方法的,同時(shí)需要重寫一下setThumb()}
canvas.drawBitmap(controlPointBitmap, imgLeft, progressBarHeight / 2 - controlPointBitmap.getHeight() / 2, null);//繪制拖動(dòng)圖片
如果我把上面的imgLeft換成getSeekBarThumb().getBounds().left就會(huì)出現(xiàn)偏差吸耿,不知道是什么原因
以上