标签:
//绘制进度条的X,Y坐标 private int marginXY = 0; //进度条背景,进度条,分隔线的paint private Paint progressbarBackgroundPaint, progressbarPaint, separtatedPaint; //视频总数 private int videoSum = 6; //画笔的宽度 private int strokeWidth = 20; //进度条线程实例 private CustomProgressRunnable customProgressRunnable; //进度条绘制标记位 private boolean startDrawProgress = false; //进度条的背景颜色 private int background; //分隔线的颜色 private int separtatedLineBackground; //进度条的颜色 private int progressbarBackground; //分隔线的宽度 private int separtatedLineWidth; //线程池 private ExecutorService executorService;
public CustomProgress(Context context , AttributeSet attrs, int defStyleAttr) { super (context, attrs , defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomProgress) ; videoSum = typedArray.getInt(R.styleable.CustomProgress_CP_Video_Sum, 3); background = typedArray.getColor(R.styleable.CustomProgress_CP_Background, Color.parseColor("#F1F1F1" ));//F1F1F1 separtatedLineBackground = typedArray.getColor(R.styleable.CustomProgress_CP_Separated_Line_Background, Color.parseColor("#D6D6D6" )); progressbarBackground = typedArray.getColor(R.styleable.CustomProgress_CP_Progressbar_Background, Color.parseColor("#5BD290" ));//5BD290 separtatedLineWidth = typedArray.getDimensionPixelSize(R.styleable.CustomProgress_CP_Separated_Line_Width, 5); typedArray.recycle() ; // progressbarBackgroundPaint = new Paint() ; progressbarBackgroundPaint .setAntiAlias(true) ; progressbarBackgroundPaint .setStrokeCap(Paint.Cap.ROUND) ; progressbarBackgroundPaint .setStrokeWidth(strokeWidth) ; progressbarBackgroundPaint .setColor(background) ; // progressbarPaint = new Paint() ; progressbarPaint .setAntiAlias(true) ; progressbarPaint .setStrokeWidth(strokeWidth) ; progressbarPaint .setStrokeCap(Paint.Cap.ROUND) ; progressbarPaint .setColor(progressbarBackground) ; separtatedPaint = new Paint() ; separtatedPaint .setAntiAlias(true) ; separtatedPaint .setStrokeWidth(strokeWidth) ; separtatedPaint .setColor(separtatedLineBackground) ; executorService = Executors.newCachedThreadPool(); }
@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int size = MeasureSpec.getSize(widthMeasureSpec); int finalWidth = size + getPaddingLeft() + getPaddingRight(); int finalHeight = strokeWidth + getPaddingBottom() + getPaddingTop(); setMeasuredDimension(finalWidth , finalHeight); }
//开始绘制进度条的X,Y坐标 marginXY = strokeWidth / 2; //绘制背景进度 canvas.drawLine(marginXY, marginXY, getWidth() - marginXY, marginXY, progressbarBackgroundPaint);也许很多人不理解marginXY是什么意思呢?为了方便解释,请大家再看看下面的图。
//开始绘制进度条 if (startDrawProgress) { //绘制当前进度 canvas.drawLine(marginXY, marginXY, getProgress(), marginXY, progressbarPaint); }
//分隔线的X坐标(注意,这一步必须放在“开始绘制进度条”之后,否则绘制的进度条会把分隔线覆盖。) int separtatedLineX = 0; for (int i = 0; i < videoSum - 1; i++) { //计算分隔线的X坐标 separtatedLineX += (getWidth() - 2 * marginXY) / videoSum; //绘制分隔线 // canvas.drawLine(marginXY + separtatedLineX - (separtatedLineWidth / 2), marginXY, marginXY + separtatedLineX + (separtatedLineWidth/2), marginXY, separtatedPaint); // canvas.drawLine(separtatedLineX , marginXY, separtatedLineX + separtatedLineWidth , marginXY, separtatedPaint); canvas.drawLine(marginXY + separtatedLineX - (separtatedLineWidth / 2), marginXY, marginXY + separtatedLineX + (separtatedLineWidth / 2), marginXY, separtatedPaint); } }
private Handler handler; private Thread thread; private VideoView videoView; //视频进度条的长度 private int perVideoLength; //当前正在播放视频的下标(下标从0开始) private int currentVideoIndex; //线程正在运行标记位 private boolean running = false; //线程正在等待标记位 private boolean waiting = false;
public CustomProgressRunnable(Handler handler, VideoView videoView, int currentVideoIndex) { this.handler = handler; this.currentVideoIndex = currentVideoIndex; this.perVideoLength = (getWidth() - 2 * marginXY) / videoSum; this.videoView = videoView; thread = new Thread(this); //设置进度条的最大进度值 setMax((currentVideoIndex + 1) * perVideoLength + marginXY); }下图中绿色线
@Override public void run() { //当前视频开始的位置 int currentVideoStartPosition = (currentVideoIndex * perVideoLength); while (currentVideoStartPosition < getMax()) { synchronized (this) { if (!running) { break; } if (waiting) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } execute(currentVideoStartPosition); } }
public void execute(int currentVideoStartPosition) { if (running && !waiting) { int videoDuration = videoView.getDuration(); if (videoDuration != -1) { //获取比例 float proportion = (float) videoView.getCurrentPosition() / (float) videoDuration; //计算移动进度 int currentVideoPosition = (int) (proportion * perVideoLength); //计算当前最新进度 int newestVideoPosition = currentVideoPosition + currentVideoStartPosition + marginXY; // CommonTool.showLog("测试:" + newestVideoPosition + " " + videoView.getCurrentPosition() + " " + videoView.getDuration() + " " + proportion + " " + perVideoLength); handler.sendMessage(Message.obtain(handler, newestVideoPosition)); } } }
class TestHandler extends Handler { @Override public void handleMessage(Message msg) { int temp = msg.what; //每设置一次setProgress的值就会调用onDraw方法 setProgress(temp); } }
//开始线程 public void start() { running = true; executorService.execute(thread); } //挂起线程 public void suspend() { if (waiting) { return; } synchronized (this) { this.waiting = true; } } //恢复线程 public void resume() { if (!waiting) { return; } synchronized (this) { this.waiting = false; this.notifyAll(); } } //停止线程 public void stop() { if (!running) { return; } synchronized (this) { running = false; } }
/** * 开始进度条 * * @param videoView * @param currentVideoIndex */ public void startProgress(VideoView videoView, int currentVideoIndex) { if (currentVideoIndex > videoSum) { Log.e("-------------------->", "当前视频下标不能大于视频总数"); return; } customProgressBarRunnable = new CustomProgressBarRunnable(new TestHandler(), videoView, currentVideoIndex); //开启一个线程更新进度条 customProgressBarRunnable.start(); startDrawProgress = true; } public void hangUpThread() { if (customProgressBarRunnable == null) { return; } customProgressBarRunnable.suspend(); Log.e("-------------------->", "挂起线程!"); } public void recoverThread() { if (customProgressBarRunnable == null) { return; } customProgressBarRunnable.resume(); Log.e("-------------------->", "恢复线程!"); } public void stopThread() { if (customProgressBarRunnable == null) { return; } customProgressBarRunnable.stop(); Log.e("-------------------->", "停止线程!"); } /** * 关闭线程池 */ public void closeThreadPool() { executorService.shutdown(); }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F2F2F2" android:orientation="vertical"> <TextView android:id="@+id/txt_bar_title" android:layout_width="match_parent" android:layout_height="40dp" android:layout_centerInParent="true" android:background="#33C774" android:gravity="center_horizontal|center_vertical" android:text="视频" android:textColor="#ffffff" android:textSize="16dp" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <VideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="200dp" android:layout_centerHorizontal="true" android:layout_gravity="center_horizontal" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="10dp" android:text="作者:Edward" android:textSize="16dp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="Android自定义控件---继承ProgressBar功能扩展\n" android:textSize="14dp" /> <TextView android:id="@+id/txt_video_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="2/15" android:textSize="14dp" /> <per.edward.ui.CustomProgressBar android:id="@+id/progressbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image_prev_video" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginRight="30dp" android:layout_toLeftOf="@+id/image_play_stop" android:onClick="onClick" android:src="@mipmap/video_left" /> <ImageView android:id="@+id/image_play_stop" android:layout_width="100dp" android:layout_height="100dp" android:layout_centerInParent="true" android:onClick="onClick" android:src="@mipmap/video_play" /> <ImageView android:id="@+id/image_netx_video" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginLeft="30dp" android:layout_toRightOf="@+id/image_play_stop" android:onClick="onClick" android:src="@mipmap/video_right" /> </RelativeLayout> </LinearLayout> </ScrollView> </LinearLayout>
<per.edward.ui.CustomProgressBar android:id="@+id/progressbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" />
/** * 播放视频页面 * Created by Edward on 2016/4/15. */ public class MainActivity extends Activity { //视频视图实例 private VideoView videoView; //视频路径列表 private ArrayList<String> videoUriList; //咋们写的自定义控件 private CustomProgressBar progressBar; //播放视频按钮 private ImageView imagePlayStop; //用来显示当前视频下标以及视频的总数 private TextView txtVideoNumber; //当前视频的下标 private int currentVideoIndex = 0; //是否开启视频线程标记位 private boolean isOpenVideoThread = false; //获取内部类实例 private CustomProgressBar.CustomProgressBarRunnable customProgressBarRunnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); videoView = (VideoView) findViewById(R.id.video_view); videoUriList = new ArrayList<>(); progressBar = (CustomProgressBar) findViewById(R.id.progressbar); imagePlayStop = (ImageView) findViewById(R.id.image_play_stop); txtVideoNumber = (TextView) findViewById(R.id.txt_video_number); initData(); setCallBackListener(); } public void initData() { int[] videosId = {R.raw.bbb, R.raw.aaa, R.raw.ccc}; //获取raw文件夹内视频 for (int i = 0; i < videosId.length; i++) { videoUriList.add("android.resource://" + getPackageName() + "/" + videosId[i]); } //设置视频段数 progressBar.setVideoSum(videoUriList.size()); txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size()); } /** * 设置回调监听事件 */ public void setCallBackListener() { //视频播放完毕之后回调此方法,关闭线程 videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { //将绘制进度条的线程暂停 progressBar.stopThread(); //将视频下标移动下一个 ++currentVideoIndex; //如果没有视频 if (currentVideoIndex > videoUriList.size() - 1) { Toast.makeText(MainActivity.this, "没有视频了", Toast.LENGTH_LONG).show(); //更换播放视频按钮的图标 imagePlayStop.setImageResource(R.mipmap.video_play); //将当前视频的下标设为0 currentVideoIndex = 0; //将开启线程的标记位设置false isOpenVideoThread = false; } else { //每当一个视频播放结束之后,再播放下一个视频。 openVideoThread(currentVideoIndex); txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size()); } } }); videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Toast.makeText(MainActivity.this, "视频播放错误!", Toast.LENGTH_LONG).show(); return false; } }); } public void onClick(View v) { switch (v.getId()) { //播放或暂停视频 case R.id.image_play_stop: imagePlayStop(); break; //下一个视频 case R.id.image_netx_video: ++currentVideoIndex; if (currentVideoIndex > videoUriList.size() - 1) { Toast.makeText(MainActivity.this, "没有视频了", Toast.LENGTH_LONG).show(); currentVideoIndex = videoUriList.size() - 1; } else { isOpenVideoThread = false; progressBar.stopThread(); imagePlayStop.setImageResource(R.mipmap.video_stop); txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size()); openVideoThread(currentVideoIndex); } break; //上一个视频 case R.id.image_prev_video: --currentVideoIndex; if (currentVideoIndex < 0) { Toast.makeText(MainActivity.this, "没有视频了", Toast.LENGTH_LONG).show(); ++currentVideoIndex; } else { isOpenVideoThread = false; progressBar.stopThread(); imagePlayStop.setImageResource(R.mipmap.video_stop); txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size()); openVideoThread(currentVideoIndex); } break; } } /** * 视频播放与暂停 */ public void imagePlayStop() { txtVideoNumber.setText(currentVideoIndex + 1 + "/" + videoUriList.size()); //如果没有开启视频(线程),那么就打开 if (!isOpenVideoThread) { imagePlayStop.setImageResource(R.mipmap.video_stop); openVideoThread(currentVideoIndex); } else { customProgressBarRunnable = progressBar.getCustomProgressBarRunnable(); //当前视频线程打开了之后,如果线程处于运行状态,那么就挂起,否则恢复线程。 if (!customProgressBarRunnable.isWaiting()) { //挂起进度条的线程 progressBar.hangUpThread(); //暂停视频播放 videoView.pause(); imagePlayStop.setImageResource(R.mipmap.video_play); } else { //恢复进度条的线程 progressBar.recoverThread(); //开始视频播放 videoView.start(); imagePlayStop.setImageResource(R.mipmap.video_stop); } } } /** * 开启视频线程 * * @param currentVideoIndex */ public void openVideoThread(int currentVideoIndex) { //把线程标记位设为已开启 isOpenVideoThread = true; //设置uri videoView.setVideoURI(Uri.parse(videoUriList.get(currentVideoIndex))); //开始视频播放 videoView.start(); //开启进度条绘制 progressBar.startProgress(videoView, currentVideoIndex); } @Override protected void onPause() { CustomProgressBar.CustomProgressBarRunnable customProgressBarRunnable = progressBar.getCustomProgressBarRunnable(); //当APP进入“不可见”状态的时候(例如返回桌面,锁屏,跳转到另一个Activity等情况),将视频暂停 if (customProgressBarRunnable != null && !customProgressBarRunnable.isWaiting()) imagePlayStop(); super.onPause(); } /** * 在该页面被销毁之前,关闭线程池,停止线程 */ @Override protected void onDestroy() { progressBar.closeThreadPool(); progressBar.stopThread(); super.onDestroy(); } }
Android自定义控件---继承ProgressBar功能扩展
标签:
原文地址:http://blog.csdn.net/u012814441/article/details/51350871