Android自定義SeekBar實現(xiàn)視頻播放進(jìn)度條
本文實例為大家分享了Android實現(xiàn)視頻播放進(jìn)度條的具體代碼,供大家參考,具體內(nèi)容如下
首先來看一下效果圖,如下所示:
其中進(jìn)度條如下:
接下來說一說我的思路,上面的進(jìn)度拖動條有自定義的Thumb,在Thumb正上方有一個PopupWindow窗口,窗口里面顯示當(dāng)前的播放時間。在SeekBar右邊有一個文本框顯示當(dāng)前播放時間/總時間。
step1、先來看一看PopupWindow的布局文件,seek_popu.xml,效果如下圖所示:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/seek_dialog_bg" > <!-- 展現(xiàn)當(dāng)前播放進(jìn)度時間的文本框--> <TextView android:id="@+id/dialogSeekTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:layout_marginTop="12dip" android:text="@string/unknow_seek_time" android:textColor="@color/black" android:textSize="12sp" /> </RelativeLayout>
step2、自定義一個SeekBar
import com.canplay.video.R; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.PopupWindow; import android.widget.SeekBar; import android.widget.TextView; /** * 自定義進(jìn)度拖動條控件 */ public class MySeekBar extends SeekBar { /** * 定義一個展現(xiàn)時間的PopupWindow */ private PopupWindow mPopupWindow; private View mView; /** * 顯示時間的TextView */ private TextView dialogSeekTime; /** * 用來表示該組件在整個屏幕內(nèi)的絕對坐標(biāo),其中 mPosition[0] 代表X坐標(biāo),mPosition[1] 代表Y坐標(biāo)。 */ private int[] mPosition; /** * SeekBar上的Thumb的寬度,即那個托動的小黃點的寬度 */ private final int mThumbWidth = 25; public MySeekBar(Context context) { this(context, null); } public MySeekBar(Context context, AttributeSet attrs) { super(context, attrs); mView = LayoutInflater.from(context).inflate(R.layout.seek_popu, null); dialogSeekTime = (TextView) mView.findViewById(R.id.dialogSeekTime); mPopupWindow = new PopupWindow(mView, mView.getWidth(), mView.getHeight(), true); mPosition = new int[2]; } /** * 獲取控件的寬度 * * @param v * @return 控件的寬度 */ private int getViewWidth(View v) { int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); v.measure(w, h); return v.getMeasuredWidth(); } /** * 獲取控件的高度 * * @param v * @return 控件的高度 */ private int getViewHeight(View v) { int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); v.measure(w, h); return v.getMeasuredHeight(); } /** * 隱藏進(jìn)度拖動條的PopupWindow */ public void hideSeekDialog() { if (mPopupWindow != null && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); } } /** * 顯示進(jìn)度拖動條的PopupWindow * * @param str * 時間值 */ public void showSeekDialog(String str) { dialogSeekTime.setText(str); int progress = this.getProgress(); // 計算每個進(jìn)度值所占的寬度 int thumb_x = (int) (progress * (1.0f * (this.getWidth() - 22) / this.getMax())); //22是兩邊的空白部分寬度 // 更新后的PopupWindow的Y坐標(biāo) int middle = this.getHeight() / 2 + 120; if (mPopupWindow != null) { try { /* * 獲取在整個屏幕內(nèi)的絕對坐標(biāo),注意這個值是要從屏幕頂端算起,也就是包括了通知欄的高度。 * 其中 mPosition[0] 代表X坐標(biāo),mPosition[1]代表Y坐標(biāo)。 */ this.getLocationOnScreen(mPosition); // 相對某個控件的位置(正左下方),在X、Y方向各有偏移 mPopupWindow.showAsDropDown(this, (int) mPosition[0], mPosition[1]); /* * 更新后的PopupWindow的X坐標(biāo) * 首先要把當(dāng)前坐標(biāo)值減去PopWindow的寬度的一半,再加上Thumb的寬度一半。 * 這樣才能使PopWindow的中心點和Thumb的中心點的X坐標(biāo)相等 */ int x = thumb_x + mPosition[0] - getViewWidth(mView) / 2 + mThumbWidth / 2; // 更新popup窗口的位置 mPopupWindow.update(x, middle, getViewWidth(mView), getViewHeight(mView)); } catch (Exception e) { } } } }
step3、將自定義的拖動條加入到布局文件中,下面是部分代碼
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/black" > ...... <!-- 進(jìn)度拖動條 --> <RelativeLayout android:id="@+id/seek_bar_container" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@id/control_btn_container" android:background="@drawable/seek_bg" > <com.canplay.video.view.MySeekBar android:id="@+id/seek_progress" android:layout_width="600dip" android:layout_height="wrap_content" android:layout_centerInParent="true" /> <TextView android:id="@+id/currentTime" style="@style/seekTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@id/seek_progress" android:paddingLeft="20dip" android:text="@string/unknow_time" /> </RelativeLayout> ............... </RelativeLayout>
step4、在主文件中對拖動條進(jìn)行托動監(jiān)聽
mSeekBar = (MySeekBar) findViewById(R.id.seek_progress); mSeekBar.setOnSeekBarChangeListener(mSeekBarListener); /** * 進(jìn)度拖動條監(jiān)聽器 */ private OnSeekBarChangeListener mSeekBarListener = new OnSeekBarChangeListener() { // 通知進(jìn)度已經(jīng)被修改 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (isTouchSeeked) { mSeekBar.showSeekDialog(makeTimeString(progress));//動態(tài)展示當(dāng)前播放時間 } else { mSeekBar.hideSeekDialog(); } } // 通知用戶已經(jīng)開始一個觸摸拖動手勢 public void onStartTrackingTouch(SeekBar seekBar) { showControlView(3600000); isTouchSeeked = true; } // 通知用戶觸摸手勢已經(jīng)結(jié)束 public void onStopTrackingTouch(SeekBar seekBar) { Message msg = Message.obtain(); msg.what = PROGRESS_SEEKTO; msg.arg1 = seekBar.getProgress(); mHandler.removeMessages(PROGRESS_SEEKTO); mHandler.sendMessageAtTime(msg, 1000);// 1秒之后開始發(fā)送更新進(jìn)度的消息 isTouchSeeked = false; showControlView(sDefaultTimeout); } };
其中將進(jìn)度值轉(zhuǎn)換為時間的方法makeTimeString(int secs)如下所示:
/** * 格式化的Builder */ private StringBuilder sFormatBuilder = new StringBuilder(); /** * 格式化的Formatter */ private Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault()); /** * 格式化的相關(guān)屬性 */ private final Object[] sTimeArgs = new Object[3]; /** * 轉(zhuǎn)換進(jìn)度值為時間 * * @param secs * @return */ private String makeTimeString(int secs) { /** * %[argument_index$][flags][width]conversion 可選的 * argument_index 是一個十進(jìn)制整數(shù),用于表明參數(shù)在參數(shù)列表中的位置。第一個參數(shù)由 "1$" * 引用,第二個參數(shù)由 "2$" 引用,依此類推。 可選 flags * 是修改輸出格式的字符集。有效標(biāo)志集取決于轉(zhuǎn)換類型。 可選 width * 是一個非負(fù)十進(jìn)制整數(shù),表明要向輸出中寫入的最少字符數(shù)。 可選 precision * 是一個非負(fù)十進(jìn)制整數(shù),通常用來限制字符數(shù)。特定行為取決于轉(zhuǎn)換類型。 所需 conversion * 是一個表明應(yīng)該如何格式化參數(shù)的字符。給定參數(shù)的有效轉(zhuǎn)換集取決于參數(shù)的數(shù)據(jù)類型。 */ String durationformat = getString(R.string.durationformat);// <xliff:g // id="format">%1$02d:%2$02d:%3$02d</xliff:g> sFormatBuilder.setLength(0); secs = secs / 1000; Object[] timeArgs = sTimeArgs; timeArgs[0] = secs / 3600; // 秒 timeArgs[1] = (secs % 3600) / 60; // 分 timeArgs[2] = (secs % 3600 % 60) % 60; // 時 return sFormatter.format(durationformat, timeArgs).toString().trim(); }
當(dāng)然,這里只是簡單的介紹了下自定義進(jìn)度條,而該進(jìn)度條的樣式都沒有展現(xiàn)出來,樣式讀者可以自己定義。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android使用VideoView播放本地視頻和網(wǎng)絡(luò)視頻的方法
- Android提高之MediaPlayer播放網(wǎng)絡(luò)視頻的實現(xiàn)方法
- Android使用VideoView出現(xiàn)無法播放此視頻問題的解決方法
- 詳解Android App中使用VideoView來實現(xiàn)視頻播放的方法
- Android播放assets文件里視頻文件相關(guān)問題分析
- Android如何讓W(xué)ebView中的HTML5頁面實現(xiàn)視頻全屏播放
- 一個html5播放視頻的video控件只支持android的默認(rèn)格式mp4和3gp
- android webvie指定視頻播放器播放網(wǎng)站視頻
- android視頻播放簡單實現(xiàn)示例(VideoView&MediaPlayer)
- Android實現(xiàn)音樂視頻播放
相關(guān)文章
Android自定義ViewPagerIndicator實現(xiàn)炫酷導(dǎo)航欄指示器(ViewPager+Fragment)
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewPagerIndicator實現(xiàn)炫酷導(dǎo)航欄指示器,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02Android在項目中接入騰訊TBS瀏覽器WebView的教程與注意的地方
今天小編就為大家分享一篇關(guān)于Android在項目中接入騰訊TBS瀏覽器WebView的教程與注意的地方,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10Android FlowLayout流式布局實現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了Android FlowLayout流式布局的實現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-09-09Android實現(xiàn)倒計時結(jié)束后跳轉(zhuǎn)頁面功能
最近在工作中遇到一個需求,需要在倒計時一段時間后進(jìn)行跳轉(zhuǎn)頁面,通過查找相關(guān)資料發(fā)現(xiàn)其中涉及的知識還不少,所以分享出來,下面這篇文章主要給大家介紹了關(guān)于Android實現(xiàn)倒計時結(jié)束后跳轉(zhuǎn)頁面功能的相關(guān)資料,需要的朋友可以參考下。2017-11-11Android四大組件:Activity/Service/Broadcast/ContentProvider作用示例
Android是一種基于Linux,自由及開放源代碼的操作系統(tǒng),Android分為四個層,從高層到底層分別是應(yīng)用程序?qū)?、?yīng)用程序框架層、系統(tǒng)運行庫層和Linux內(nèi)核層,Android有四大基本組件:Activity、Service服務(wù)、BroadcastReceiver廣播接收器、Content Provider內(nèi)容提供者2023-11-11