Android自定义SeekBar实现视频播放进度条

首先来看一下效果图,如下所示:

其中进度条如下:

接下来说一说我的思路,上面的进度拖动条有自定义的Thumb,在Thumb正上方有一个PopupWindow窗口,窗口里面显示当前的播放时间。在SeekBar右边有一个文本框显示当前播放时间/总时间。

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" >
 <!-- 展现当前播放进度时间的文本框-->
 <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; 

/**
 * 自定义进度拖动条控件
 */
public class MySeekBar extends SeekBar {
 /**
  * 定义一个展现时间的PopupWindow
  */
 private PopupWindow mPopupWindow; 

 private View mView;
 /**
  * 显示时间的TextView
  */
 private TextView dialogSeekTime;
 /**
  * 用来表示该组件在整个屏幕内的绝对坐标,其中 mPosition[0] 代表X坐标,mPosition[1] 代表Y坐标。
  */
 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();
 } 

 /**
  * 隐藏进度拖动条的PopupWindow
  */
 public void hideSeekDialog() {
  if (mPopupWindow != null && mPopupWindow.isShowing()) {
   mPopupWindow.dismiss();
  }
 } 

 /**
  * 显示进度拖动条的PopupWindow
  *
  * @param str
  *     时间值
  */
 public void showSeekDialog(String str) {
  dialogSeekTime.setText(str);
  int progress = this.getProgress();
  // 计算每个进度值所占的宽度
  int thumb_x = (int) (progress * (1.0f * (this.getWidth() - 22) / this.getMax())); //22是两边的空白部分宽度
  // 更新后的PopupWindow的Y坐标
  int middle = this.getHeight() / 2 + 120;
  if (mPopupWindow != null) {
   try {
    /*
     * 获取在整个屏幕内的绝对坐标,注意这个值是要从屏幕顶端算起,也就是包括了通知栏的高度。
     * 其中 mPosition[0] 代表X坐标,mPosition[1]代表Y坐标。
     */
    this.getLocationOnScreen(mPosition);
    // 相对某个控件的位置(正左下方),在X、Y方向各有偏移
    mPopupWindow.showAsDropDown(this, (int) mPosition[0], mPosition[1]);
    /*
     * 更新后的PopupWindow的X坐标
     * 首先要把当前坐标值减去PopWindow的宽度的一半,再加上Thumb的宽度一半。
     * 这样才能使PopWindow的中心点和Thumb的中心点的X坐标相等
     */
    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" >
......
<!-- 进度拖动条 -->
  <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、在主文件中对拖动条进行托动监听

mSeekBar = (MySeekBar) findViewById(R.id.seek_progress);
mSeekBar.setOnSeekBarChangeListener(mSeekBarListener);
/**
  * 进度拖动条监听器
  */
 private OnSeekBarChangeListener mSeekBarListener = new OnSeekBarChangeListener() {
  // 通知进度已经被修改
  public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
   if (isTouchSeeked) {
    mSeekBar.showSeekDialog(makeTimeString(progress));//动态展示当前播放时间
   } else {
    mSeekBar.hideSeekDialog();
   }
  } 

  // 通知用户已经开始一个触摸拖动手势
  public void onStartTrackingTouch(SeekBar seekBar) {
   showControlView(3600000);
   isTouchSeeked = true;
  } 

  // 通知用户触摸手势已经结束
  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秒之后开始发送更新进度的消息
   isTouchSeeked = false;
   showControlView(sDefaultTimeout);
  }
 };

其中将进度值转换为时间的方法makeTimeString(int secs)如下所示:

/**
  * 格式化的Builder
  */
 private StringBuilder sFormatBuilder = new StringBuilder();
 /**
  * 格式化的Formatter
  */
 private Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
 /**
  * 格式化的相关属性
  */
 private final Object[] sTimeArgs = new Object[3]; 

 /**
  * 转换进度值为时间
  *
  * @param secs
  * @return
  */
 private String makeTimeString(int secs) {
  /**
   * %[argument_index$][flags][width]conversion 可选的
   * argument_index 是一个十进制整数,用于表明参数在参数列表中的位置。第一个参数由 "1$"
   * 引用,第二个参数由 "2$" 引用,依此类推。 可选 flags
   * 是修改输出格式的字符集。有效标志集取决于转换类型。 可选 width
   * 是一个非负十进制整数,表明要向输出中写入的最少字符数。 可选 precision
   * 是一个非负十进制整数,通常用来限制字符数。特定行为取决于转换类型。 所需 conversion
   * 是一个表明应该如何格式化参数的字符。给定参数的有效转换集取决于参数的数据类型。
   */
  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();
 }

当然,这里只是简单的介绍了下自定义进度条,而该进度条的样式都没有展现出来,样式读者可以自己定义。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义垂直拖动seekbar进度条

    Android自带的SeekBar是水平的,要垂直的,必须自己写一个类,继承SeekBar. 一个简单的垂直SeekBar的例子: (但是它其实是存在一些问题的.不过要是满足基本需要还是可以凑合的) package com.example.helloverticalseekbar; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import and

  • Android 可拖动的seekbar自定义进度值

    最近接了个项目其中有需要要实现此功能:seekbar需要显示最左和最右值,进度要跟随进度块移动.下面通过此图给大家展示下效果,可能比文字描述要更清晰. 其实实现起来很简单,主要是思路.自定义控件的话也不难,之前我的博客也有专门介绍,这里就不再多说. 实现方案 这里是通过继承seekbar来自定义控件,这样的方式最快.主要难点在于进度的显示,其实我很的是最笨的方法,就是用了一个popwindow显示在进度条的上方,然后在移动滑块的时候实时的改变它显示的横坐标.看进度显示的核心代码: private

  • Android控件之SeekBar的用法总结

    1 SeekBar简介 SeekBar是进度条.我们使用进度条时,可以使用系统默认的进度条:也可以自定义进度条的图片和滑块图片等. 2 SeekBar示例 创建一个activity,包含2个SeekBar. 第1个SeekBar是系统默认的SeekBar. 第2个SeekBar是自定义SeekBar,使用自定义的背景图和滑块图片. 应用层代码 package com.skywang.control; import android.os.Bundle; import android.app.Act

  • Android 七种进度条的样式

    当一个应用在后台执行时,前台界面就不会有什么信息,这时用户根本不知道程序是否在执行.执行进度如何.应用程序是否遇到错误终止等,这时需要使用进度条来提示用户后台程序执行的进度.Android系统提供了两大类进度条样式,长形进度条(progress-BarStyleHorizontal) 和圆形进度条(progressBarStyleLarge).进度条用处很多,比如,应用程序装载资源和网络连接时,可以提示用户稍等,这一类进度条只是代表应用程序中某一部分的执行情况,而整个应用程序执行情况呢,则可以通

  • android自定义进度条渐变色View的实例代码

    最近在公司,项目不是很忙了,偶尔看见一个兄台在CSDN求助,帮忙要一个自定义的渐变色进度条,我当时看了一下进度条,感觉挺漂亮的,就尝试的去自定义view实现了一个,废话不说,先上图吧! 这个自定义的view,完全脱离了android自带的ProgressView,并且没使用一张图片,这样就能更好的降低程序代码上的耦合性! 下面我贴出代码  ,大概讲解一下实现思路吧! 复制代码 代码如下: package com.spring.progressview; import android.conten

  • Android中实现Webview顶部带进度条的方法

    写这篇文章,做份备忘,简单滴展示一个带进度条的Webview示例,进度条位于Webview上面. 示例图如下: 主Activity代码: 复制代码 代码如下: package com.droidyue.demo.webviewprogressbar; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.vi

  • android之SeekBar控件用法详解

    MainActivity.java package com.example.mars_2400_seekbar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.Activity; import android.os.Bundle; import a

  • Android 动态改变SeekBar进度条颜色与滑块颜色的实例代码

    遇到个动态改变SeekBar进度条颜色与滑块颜色的需求,有的是根据不同进度改变成不同颜色. 对于这个怎么做呢?大家都知道设置下progressDrawable与thumb即可,但是这样设置好就是确定的了,要动态更改需要在代码里实现. 用shape进度条与滑块 SeekBar设置 代码里动态设置setProgressDrawable与setThumb 画图形,大家都比较熟悉,background是背景图,secondaryProgress第二进度条,progress进度条: <layer-list

  • Android下修改SeekBar样式的解决办法

    SeekBar配置文件:Xml代码 复制代码 代码如下: <SeekBar              android:id="@+id/player_seekbar"             android:layout_width="245px"             android:layout_height="25px"             android:progressDrawable="@drawable/see

  • Android自定义竖直方向SeekBar多色进度条

    写在前面 因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下: 具体实现 本来想定义水平的,然后旋转一下,后来发现还不如直接定义竖直方向来的直接,就直接在竖直方向画了下. 首先讲一下思路,就是通过继承View,然后通过onDraw()方法进行绘制.具体绘制的时候,需要处理一些小细节. 比如,我们需要画一个圆形的滑动块,那么我们的背景色带就不能把整个宽度占满,要不然,小圆块只能和色带一样宽了,效果不是很好看,所以在绘制的时候应该把背

随机推荐