自定义万能的progressView
来源:互联网 发布:功夫熊猫中的师傅知乎 编辑:程序博客网 时间:2024/04/29 11:00
效果预览
控件由来
这两天有个哥们给我商量他们公司语音播放进度条的做法。如图
看到这个图片我首先想到的是自定义view,怎么自定义view呢?
第一个想法
数一下一共有多少根竖条,然后找到每一根竖条直接高度的比例,通过自定义view宽高的比例算数每个竖条和中间横条的位置。这个办法肯定是可以的,但是感觉有点麻烦而且不通用,万一哪天设计的妹子把这个进度图换了我还得重新找规律重新通过复杂的计算来做。
第二种想法
其实这种进度的显示就是两个图层。第一个图层显示灰色全部画下来,第二个要根据进度画出不发蓝色图层就可以了。而且这种方法放之四海都可以用(只要让设计MM给你切两个大小一致颜色不同的图片就ok了)
编码
通过上边的比较我们决定用第二种方法来实现
我们先来分析下我们需要哪些属性:
- 我们要两个大小相等颜色不同的图片
- 当前进度和总进度
分析了下好像就学这四个属性就够了于是我们先定attr
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="MyProgress"> <attr name="bg_drawable" format="reference"></attr> <attr name="progress_drawable" format="reference"></attr> <attr name="progress" format="integer"></attr> <attr name="max_progress" format="integer"></attr> <attr name="orientation" format="enum"> <enum name="left" value="0"></enum> <enum name="top" value="1"></enum> <enum name="right" value="2"></enum> <enum name="bottom" value="3"></enum> </attr> </declare-styleable></resources>
好像多了一个属性orientation,既然是是自定义要放之四海皆准我们就要考虑到他进度方向有可能是从左向右,有可能是从下往上,所以这里我定义了4个方向
再看看我的自定义view的java代码
- 定义上边需要的5个属性变量并在构造函数里获取到赋值
public MyProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.MyProgress,defStyleAttr,0); //背景图片 res_bg= typedArray.getResourceId(R.styleable.MyProgress_bg_drawable,0); //进度图片 res_progress=typedArray.getResourceId(R.styleable.MyProgress_progress_drawable,0); /方向 orientation=typedArray.getInteger(R.styleable.MyProgress_orientation, 0); //最大进度 max=typedArray.getInteger(R.styleable.MyProgress_max_progress,100); //进度值并转化为百分比 progressP=typedArray.getInteger(R.styleable.MyProgress_progress,100)*1.0f/max; typedArray.recycle(); init(); }
- 既然自定义view就要重写onMeasure确定它的宽高,这个宽高我们自然是用图片自己打宽高了,所以我们在init()里获取图片的bitmap和宽高,再onMeasure里设置成图片的宽高
private void init(){ //进度图的bitmap if(res_progress!=0){ mBlueBitmap= BitmapFactory.decodeResource(getResources(),res_progress); }else{ mBlueBitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.blue); } //背景图的bitmap if(res_bg!=0){ mWhiteBitmap= BitmapFactory.decodeResource(getResources(),res_bg); }else { mWhiteBitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.white); } //图片宽 width=mBlueBitmap.getWidth(); //图片高 height=mBlueBitmap.getHeight(); }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(width, height); }
- 接下下来就是在onDraw()里画图了。其实就两步:1、画背景图 2、按进度比例截取进度图的部分图像,并画在画不上
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(mWhiteBitmap, 0, 0, null); ImageCrop(canvas, mBlueBitmap, progressP); }
- 那我们重点来看看这个截取图片的代码ImageCrop(),代码也很简单就是通过progress的进度值再结合定义的方向算出来对应的x,y坐标和对应截取图片的大小区域
public void ImageCrop(Canvas canvas,Bitmap bitmap,float progress) { int w = bitmap.getWidth(); // 得到图片的宽,高 int h = bitmap.getHeight(); int x=0; int y=0; if(orientation==0){ w=(int) (w*progress); } if(orientation==1){ h=(int)(h*progress); } if(orientation==2){ x=w-(int)(w*progress); w=(int)(w*progress); } if(orientation==3){ y=h-(int)(h*progress); h=(int)(h*progress); } //下面这句是关键 Bitmap tempBitmap=Bitmap.createBitmap(bitmap, x, y, w, h, null, false); canvas.drawBitmap(tempBitmap,x,y,null); }
- 到这里这个自定义view已经可以用了,但是我们通常的进度是通过代码控制的 所以我们加个方法来控制进度值progress
public void setProgress(int progress){ this.progressP=progress*1.0f/max; invalidate(); }
- 接下来就是使用了,在xml里定义我们的view,在activity里new个线程调用调用setProgress
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" android:background="#000000"> <com.leisure.progressview.MyProgress android:layout_margin="10dp" android:id="@+id/left_progress" android:layout_width="fill_parent" android:layout_height="fill_parent" app:orientation="left" app:bg_drawable="@mipmap/btn_photo_select_normal" app:progress_drawable="@mipmap/btn_photo_select_push" app:progress="50" app:max_progress="100"/> <com.leisure.progressview.MyProgress android:layout_margin="10dp" android:id="@+id/top_progress" android:layout_width="fill_parent" android:layout_height="fill_parent" app:orientation="top" app:bg_drawable="@mipmap/btn_file_browser_up_level_normal" app:progress_drawable="@mipmap/btn_file_browser_up_level_pressed" app:progress="50" app:max_progress="100"/> <com.leisure.progressview.MyProgress android:layout_margin="10dp" android:id="@+id/right_progress" android:layout_width="fill_parent" android:layout_height="fill_parent" app:orientation="right" app:bg_drawable="@mipmap/enterprise_normal" app:progress_drawable="@mipmap/enterprise_press" app:progress="50" app:max_progress="100"/> <com.leisure.progressview.MyProgress android:layout_margin="10dp" android:id="@+id/bottom_progress" android:layout_width="fill_parent" android:layout_height="fill_parent" app:orientation="bottom" app:progress="50" app:max_progress="100"/></LinearLayout>
package com.leisure.progressview;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;public class MainActivity extends AppCompatActivity { MyProgress mProgressLeft,mProgressTop,mProgressRight,mProgressBottom; Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); mProgressLeft.setProgress(msg.what); mProgressTop.setProgress(msg.what); mProgressRight.setProgress(msg.what); mProgressBottom.setProgress(msg.what); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mProgressLeft= (MyProgress) findViewById(R.id.left_progress); mProgressTop= (MyProgress) findViewById(R.id.top_progress); mProgressRight= (MyProgress) findViewById(R.id.right_progress); mProgressBottom= (MyProgress) findViewById(R.id.bottom_progress); new Thread(){ @Override public void run() { super.run(); for(int i=1;i<=100;i++){ mHandler.sendEmptyMessage(i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }}
总结
自己总是特别懒,不愿意多动脑,但是比较乐于助人,如果是自己的事可能就不会写这个控件了,但是朋友给机会讨论 我就写个试试吧 感谢这个朋友给的机会 就刚学android的时候写过博客 ,好久没有写了希望有人能看懂
github地址:https://github.com/leisurelife/ProgressView
3 0
- 自定义万能的progressView
- iOS自定义progressView的实现
- android 自定义View简单的ProgressView圆形进度条
- (笔记)自定义Progress 动画 ProgressView
- progressview
- 自定义简单的万能适配器
- IOS progressview的简单使用
- iOS 自定义控件 progressView(环形进度条)
- iOS 自定义控件 progressView(环形进度条)
- iOS 自定义控件 progressView(环形进度条)
- RecyclerView的自定义万能分割线
- NSTimer与ProgressView进度条的使用
- [Android]自定义万能Dialog
- 自定义万能对话框
- 使用ActiveX实现的Web自定义查询-万能查询
- 水经注万能地图下载器的自定义瓦片导出功能
- 自定义万能的titlebar和沉浸式状态栏
- 使用 自定义布局 实现灵活的万能遥控器界面
- z-index无效
- vretica自动收集统计信息脚本
- 基于Winodws平台的Github使用(初级):
- 12306模拟登录
- 工作环境搭建(10) - CentOS7安装OpenCV(带Python开发环境)
- 自定义万能的progressView
- 打包 ipa (转载)
- 四字节与float转换
- 使用Jenkins配置Git+Maven的自动化构建
- Android Studio 的快捷键介绍
- Ext.js5的表格插件—展开和冻结和Ext.XTemplate(14)
- Xcode常用插件及失效解决办法
- Spring相关技术
- Java提高篇(二七)-----TreeMap