- 浏览: 131448 次
- 性别:
- 来自: 成都
最新评论
-
yi_chao_jiang:
你好,多谢分享,问个问题,在上传数据的时候判断文件是否有上传记 ...
断点续传和下载原理分析 -
a41606709:
为什么我的tabhost显示不出来? 怎么设置在全部页面中让他 ...
TabActivity中的Tab标签详细设置 -
Zero颴:
大神篇,思路,配图都很清晰,perfect!
Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解 -
QAZ503602501:
牛死人了!!!
B-树 -
mengsina:
很牛的文档。数学功底好啊
Android Matrix理论与应用详解
最近由于需要,做了一个音乐播放控制view,在上面需要能
*控制播放
*显示剩余时间
*显示进度(整个view就是一个进度条)
*实现播放暂停,以及ProgressBar的第一二进度功能
开始想到用组合的方式实现,然后重写ProgressBar的方式实现,但是发现很困难而且文字显示也不行
最后只有自己动手写一个新的控制条
主要的原理就是绘制视图的时候控制onDraw,然后在上面画图片和文字
然后在进度变化的时候不断重绘View就可以了
先上图:
其主要的View部分:
package com.hao; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.MeasureSpec; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; public class ProgressButton extends View{ private Bitmap begin , bm_gray, bm_yellow, bm_second, end_gray, end_yellow, line,begin_gray; private Bitmap pausePressedImg; private Bitmap playPressedImg; private int bitmapWidth = 0 , bitmapHeight = 0, btWidth = 0, btHeight = 0; private int progress = 0, secondProgress = 0; private double perLen = 0, max = 0, maxSize = 0; private OnProgressChanged mOnProgressChanged; private boolean isPlaying = false; private Paint mTextPaint; private String time = "00:00"; private int color = Color.BLUE; public ProgressButton(Context context) { super(context); // TODO Auto-generated constructor stub init(); } public ProgressButton(Context context, AttributeSet attrs, int defStyle){ super(context, attrs, defStyle); init(); } public ProgressButton(Context context, AttributeSet attrs){ super(context, attrs); init(); } private void init(){ begin = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_left_yellow)); begin_gray = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_left_gray)); bm_gray = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_gray)); bm_yellow = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_yellow)); bm_second = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_second_yellow)); end_gray = drawableToBitmap(getResources().getDrawable( R.drawable.rectangle_right_gray)); end_yellow = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_right_yellow)); line = drawableToBitmap(getResources().getDrawable(R.drawable.rectangle_line)); pausePressedImg = BitmapFactory.decodeResource(getResources(), R.drawable.pause_button_pressed); playPressedImg = BitmapFactory.decodeResource(getResources(), R.drawable.play_button_pressed); bitmapHeight = begin.getHeight(); bitmapWidth = begin.getWidth(); btWidth = pausePressedImg.getWidth(); btHeight = pausePressedImg.getHeight(); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(14); mTextPaint.setColor(color); setPadding(3, 3, 3, 3); } public static Bitmap drawableToBitmap(Drawable drawable) { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, drawable .getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, width, height); drawable.draw(canvas); return bitmap; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub Log.e("*******", "onMeasure"); setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); perLen = maxSize/max; } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub Log.e("*******", "onDraw"); int middle1 = (int) (progress*perLen), middle2 = (int) (secondProgress*perLen) ,end = (int) maxSize-4; if(progress == 0 && secondProgress == 0){ //draw background canvas.drawBitmap(begin_gray, new Rect(0,0,bitmapWidth,bitmapHeight), new Rect(0, 0, bitmapWidth, bitmapHeight), null); canvas.drawBitmap(bm_gray, new Rect(0,0,end-middle1,bitmapHeight), new Rect(bitmapWidth, 0, end, bitmapHeight), null); canvas.drawBitmap(end_gray, new Rect(0,0,4,bitmapHeight), new Rect(end, 0, end+4, bitmapHeight), null); //draw button and line canvas.drawBitmap(playPressedImg, new Rect(0, 0, btWidth, btHeight), new Rect(0, 0, btWidth, bitmapHeight), null); canvas.drawBitmap(line, new Rect(0, 0, 2, bitmapHeight), new Rect(btWidth, 0, btWidth+2, bitmapHeight), null); //draw time and line if(time.length() == 5){ canvas.drawBitmap(line, new Rect(0, 0, 2, bitmapHeight), new Rect(end - 50, 0, end-48, bitmapHeight), null); canvas.drawText("-"+time, end-45, bitmapHeight/2+5, mTextPaint); }else{ canvas.drawBitmap(line, new Rect(0, 0, 2, bitmapHeight), new Rect(end - 60, 0, end-58, bitmapHeight), null); canvas.drawText("-"+time, end-55, bitmapHeight/2+5, mTextPaint); } }else{ //begin canvas.drawBitmap(begin, new Rect(0,0,bitmapWidth,bitmapHeight), new Rect(0, 0, bitmapWidth, bitmapHeight), null); canvas.drawBitmap(bm_yellow, new Rect(0,0,middle1-bitmapWidth,bitmapHeight), new Rect(bitmapWidth, 0, middle1, bitmapHeight), null); //middle if(secondProgress != 0 && secondProgress > progress){ canvas.drawBitmap(bm_second, new Rect(0,0,bitmapWidth,bitmapHeight), new Rect(middle1, 0, middle2, bitmapHeight), null); canvas.drawBitmap(bm_gray, new Rect(0,0,bitmapWidth,bitmapHeight), new Rect(middle2, 0, end, bitmapHeight), null); }else{ canvas.drawBitmap(bm_gray, new Rect(0,0,end-middle1,bitmapHeight), new Rect(middle1, 0, end, bitmapHeight), null); } //end canvas.drawBitmap(end_gray, new Rect(0,0,4,bitmapHeight), new Rect(end, 0, end+4, bitmapHeight), null); if(middle2 >= end || middle1 >= end){ canvas.drawBitmap(end_yellow, new Rect(0,0,4,bitmapHeight), new Rect(end, 0, end+4, bitmapHeight), null); } //draw button if(!isPlaying) { canvas.drawBitmap(playPressedImg, new Rect(0, 0, btWidth, btHeight), new Rect(0, 0, btWidth, bitmapHeight), null); }else{ canvas.drawBitmap(pausePressedImg, new Rect(0, 0, btWidth, btHeight), new Rect(0, 0, btWidth, bitmapHeight), null); } //draw line and time canvas.drawBitmap(line, new Rect(0, 0, 2, bitmapHeight), new Rect(btWidth, 0, btWidth+2, bitmapHeight), null); if(time.length() == 5){ canvas.drawBitmap(line, new Rect(0, 0, 2, bitmapHeight), new Rect(end - 50, 0, end-48, bitmapHeight), null); canvas.drawText("-"+time, end-45, bitmapHeight/2+5, mTextPaint); }else{ canvas.drawBitmap(line, new Rect(0, 0, 2, bitmapHeight), new Rect(end - 60, 0, end-58, bitmapHeight), null); canvas.drawText("-"+time, end-55, bitmapHeight/2+5, mTextPaint); } } super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub //在这里因为要换按钮,故而需要更新整个视图 if(event.getAction() == MotionEvent.ACTION_DOWN){ onClickListener.onClick(this); invalidate(); } return true; } /** * 这个方法必须设置,当播放的时候 * @param isPlaying */ public void setStateChanged(boolean isPlaying){ this.isPlaying = isPlaying; } public void setTextColor(int color){ this.color = color; invalidate(); } /** * Determines the width of this view * @param measureSpec A measureSpec packed into an int * @return The width of the view, honoring constraints from measureSpec */ private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { // We were told how big to be result = specSize; } else { result = (int) ((int)max*perLen + getPaddingLeft() + getPaddingRight()); if (specMode == MeasureSpec.AT_MOST) { // Respect AT_MOST value if that was what is called for by measureSpec result = Math.min(result, specSize); } } System.out.println("width:"+result); maxSize = result; return result; } /** * Determines the height of this view * @param measureSpec A measureSpec packed into an int * @return The height of the view, honoring constraints from measureSpec */ private int measureHeight(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { // We were told how big to be result = specSize; } else { // Measure the text (beware: ascent is a negative number) result = (int) getPaddingTop() + getPaddingBottom() + bitmapHeight; if (specMode == MeasureSpec.AT_MOST) { // Respect AT_MOST value if that was what is called for by measureSpec result = Math.min(result, specSize); } } System.out.println("Height:"+result); return result; } /** * set the time * @param currentTime 当前播放时间 * @param totalTime 总播放时间 */ public void setTime(int currentTime, int totalTime){ int time = totalTime - currentTime; if(time <= 1000){ this.time="00:00"; return; } time/=1000; int minute = time/60; int hour = minute/60; int second = time%60; minute %= 60; if(hour == 0){ this.time = String.format("%02d:%02d", minute,second); }else{ this.time = String.format("%02d:%02d:%02d", hour, minute,second); } } /** * * @param viewWidth 组件的宽度 */ public void setMax(int max){ this.max = max; } public int getMax(){ return (int)max; } /** * 设置第一进度 * @param progress */ public void setProgress(int progress){ if(progress>max){ progress = (int) max; } else if(progress<0){ progress = 0; } if(mOnProgressChanged!=null){ mOnProgressChanged.onProgressUpdated(); } this.progress = progress; invalidate(); } /** * 设置第二进度 * @param secondProgress */ public void setSecondProgress(int secondProgress){ if(secondProgress>max){ secondProgress = (int) max; } else if(secondProgress<0){ secondProgress = 0; } if(mOnProgressChanged!=null){ mOnProgressChanged.onSecondProgressUpdated(); } this.secondProgress = secondProgress; invalidate(); } /** * 设置进度监听器 * @param mOnProgressChanged */ public void setmOnProgressChanged(OnProgressChanged mOnProgressChanged) { this.mOnProgressChanged = mOnProgressChanged; } public interface OnProgressChanged{ void onProgressUpdated(); void onSecondProgressUpdated(); } @Override public void setOnClickListener(OnClickListener l) { // TODO Auto-generated method stub if(l != null) onClickListener = l; super.setOnClickListener(l); } private View.OnClickListener onClickListener; }
控制非常简单,在这里设置了第一和二进度:
package com.hao; import java.util.Timer; import java.util.TimerTask; import com.hao.ProgressView.OnProgressChanged; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; public class SeekBarTestActivity extends Activity { ProgressButton bp; int time = 60000 , currentTime = 0; boolean flag = true; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_progress_bar); bp = (ProgressButton) findViewById(R.id.pbt); bp.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub System.out.println("main onck"); bp.setStateChanged(flag); flag = !flag; } }); bp.setMax(60000); Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // TODO Auto-generated method stub handler.sendEmptyMessage(0); } }, 0, 2000); } Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub currentTime +=1000; bp.setProgress(currentTime); bp.setSecondProgress(currentTime+1000); bp.setTime(currentTime, time); } }; }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="音乐播放"/> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="5dip" android:gravity="center_horizontal"> <com.hao.ProgressButton android:id="@+id/pb1" android:layout_width="300dp" android:layout_height="45dp" android:background="@drawable/button_left_gray_background"/> </LinearLayout> </LinearLayout>
我用到的进度图片都是通过xml定义的在附件中
发表评论
-
手机游戏的优化
2012-05-14 15:46 1067手机游戏设计中由于设备性能限制,可能出现资源不足的情况 ... -
断点续传和下载原理分析
2011-12-07 15:22 14661最近做一个文件上传和下载的应用对文件上传和下载进行了一个完整的 ... -
Android Matrix理论与应用详解
2011-11-21 10:58 17634本文转自http://blog.csdn.net/kuku20 ... -
Android图片处理(Matrix,ColorMatrix)
2011-11-20 22:47 3261在编程中有时候需要对图片做特殊的处理,比如将图片做出黑 ... -
Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解
2011-11-19 20:53 7288参考文档: http://blog.cs ... -
Android下基于XML的 Graphics(转载)
2011-04-23 15:39 1302Android下基于XML的 Graphi ... -
Android之父深入解析Android
2011-04-22 16:10 1038Android之父深入解析Android By: 海 ... -
实现ListView的条目下自动隐藏显示Button的方法
2011-04-17 09:42 6610这个想法是我在看了sina ... -
TabActivity中的Tab标签详细设置
2011-03-24 17:19 7283参考链接: http://www.iteye.com/ ...
相关推荐
本话题主要关注的是“一个可以控制进度的Flash播放器”,这意味着该播放器具备用户界面,让用户能够自由调整播放进度,如快进、快退、暂停和播放等基本功能。 Flash播放器的核心是Adobe Flash Player,这是一个跨...
"易语言带播放进度的播放器"是一个使用易语言编写的项目,旨在实现一个能够显示播放进度的媒体播放器。这个项目对于学习易语言的初学者来说是一个很好的实践案例,它涉及到多媒体处理、用户界面设计以及事件驱动编程...
这个“易语言源码带播放进度的播放器.rar”压缩包文件显然包含了一个使用易语言编写的播放器程序源代码,并且这个播放器具备显示播放进度的功能。 首先,我们要理解播放进度的实现原理。在任何多媒体播放器中,播放...
总之,通过从CStatic类派生CTimebar类,我们可以创建一个具有时间和播放功能的时间轴控件,为视频播放器带来更好的用户体验。理解并实现这样的自定义控件是提升多媒体应用专业性的关键步骤,同时也能锻炼开发者在...
LRC文件是一种常见的歌词文件格式,包含时间戳和歌词内容,使得播放器能够准确地在特定时间点显示相应的歌词行。 2. **实时同步**:音乐播放器需要有算法来匹配音频播放的位置与歌词的时间轴,确保歌词与歌曲旋律...
在开发一个显示进度的MP3播放器时,我们需要掌握一系列的IT知识点,这些知识点涵盖了...以上就是开发显示进度的MP3播放器所需的关键知识点,每个点都可以深入学习和探讨,以实现一个高效、稳定且用户体验良好的播放器。
1. **时间轴(Time Axis)**:在视频播放器中,时间轴是一个直观展示视频播放进度的组件。它通常显示在播放器下方,由一个条状图形表示,上面有刻度和滑块,用户可以通过拖动滑块来跳转到视频的任意时间点。时间轴的...
综上所述,jQuery自适应时间播放器结合了jQuery的强大功能和现代Web的响应式设计,为视频、音频播放或其他需要时间轴的应用提供了实用的解决方案。通过灵活的配置和扩展,开发者可以轻松集成并定制这个插件,以满足...
在C# Winform应用开发中,创建一个播放器时间轴是一项常见的需求,它通常用于显示媒体文件的播放进度,提供用户交互控制,如拖动、快进、快退等。本项目通过自定义控件来实现这一功能,下面将详细阐述相关知识点。 ...
1. **动态计算歌曲时间**:在播放过程中,播放器能够实时计算当前歌曲的播放时间,并在界面上展示出来,使用户可以清晰地了解到歌曲的播放进度。 2. **拖放中动态显示进度**:用户可以通过拖动播放条来控制歌曲的...
而指针效果可能是指在播放过程中,类似时钟指针的进度指示器,为用户提供了更直观的播放时间感知。 标签同样重复了这个描述,进一步巩固了这个播放器的核心特点:实用、轻量级以及其独特的视觉元素。 在压缩包文件...
2. **时间同步**:利用GetLRCLocation和ConvertLRCToOLR等函数,将LRC时间转换为可以与音频播放进度同步的形式。 3. **歌词显示**:当音乐播放到特定时间点时,通过SetStr更新歌词显示区域,展示对应的歌词内容。 4....
音视频播放器的时间轴控件是用户界面中的一个重要组成部分,特别是在多媒体应用中,它允许用户直观地查看并控制媒体的播放进度。在C#开发环境中,构建这样的控件通常涉及与后端服务交互,可能还需要利用Microsoft...
在这个名为“一个音频播放器demo(带seekbar和显示时间)”的项目中,开发者提供了一个基本的音频播放器实现,具备了播放、暂停、进度控制(通过seekbar)以及显示播放时间的功能。这个demo主要围绕Android平台上的`...
例如,`audio.currentTime`可以获取当前播放时间,`audio.duration`则代表总时长,这些信息可以用来计算和更新进度条的显示。 总之,“带圆形进度条的音乐播放器”是一个结合了Canvas图形绘制和音频处理技术的项目...
【基于jQuery的时间播放器】是一种使用JavaScript库jQuery开发的交互式媒体播放控制工具。这个播放器功能丰富,允许用户对时间进度进行精确控制,比如加速、减速、开始、停止以及重新播放。它不仅提供了基本的播放...
`SeekBar`的`setProgress()`和`setMax()`方法分别设置当前进度和最大值,对应音频的播放时间和总时长。为了使进度条与音频播放同步,我们需要监听`MediaPlayer`的`OnSeekCompleteListener`和`...
在IT行业中,构建一个应用程序或网站时,"上传、...以上所述是实现"上传、下载、播放器、进度"功能所需的关键技术和注意事项。在实际开发中,还需要考虑用户体验、安全性、兼容性等多个方面,确保功能的稳定和高效。
这个"手势实现播放器的进度和音量调节.zip"源码示例,旨在教你如何利用手势操作来控制播放器的播放进度和音量,这对于开发音乐、视频类应用非常实用。下面我们将详细探讨其中涉及到的关键知识点。 1. **手势识别...