模擬QQ多段錄制視頻壮吩,使用到的SeekBar

手機(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)有填充滿的,看下圖


100%

我預(yù)留了一個(gè)圖片的位置給剪切的那個(gè)圖片层宫。

當(dāng)我滑動(dòng)或者點(diǎn)擊圖片的時(shí)候杨伙,我們就要去編輯這幾段視頻了(圖片中有5段視頻),比如說(shuō)我點(diǎn)擊了一次剪切圖片萌腿,就會(huì)變成下圖:

保留剩下的4個(gè)小視頻


保留0個(gè)視頻

圖片中有白色的分割線限匣,我們叫斷點(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)偏差吸耿,不知道是什么原因

以上

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祠锣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子咽安,更是在濱河造成了極大的恐慌伴网,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妆棒,死亡現(xiàn)場(chǎng)離奇詭異澡腾,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)糕珊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門动分,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人红选,你說(shuō)我怎么就攤上這事澜公。” “怎么了喇肋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵坟乾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蝶防,道長(zhǎng)甚侣,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任间学,我火速辦了婚禮殷费,結(jié)果婚禮上印荔,老公的妹妹穿的比我還像新娘。我一直安慰自己宗兼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布氮采。 她就那樣靜靜地躺著殷绍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹊漠。 梳的紋絲不亂的頭發(fā)上主到,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音躯概,去河邊找鬼登钥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛娶靡,可吹牛的內(nèi)容都是我干的牧牢。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姿锭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼塔鳍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起呻此,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤轮纫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后焚鲜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體掌唾,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年忿磅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了糯彬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡葱她,死狀恐怖情连,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情览效,我是刑警寧澤却舀,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站锤灿,受9級(jí)特大地震影響挽拔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜但校,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一螃诅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦术裸、人聲如沸倘是。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搀崭。三九已至,卻和暖如春猾编,著一層夾襖步出監(jiān)牢的瞬間瘤睹,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工答倡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留轰传,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓瘪撇,卻偏偏與公主長(zhǎng)得像获茬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子倔既,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容