---- The mark of the immature man is that he wants to die nobly for a causer while the mark of the mature man is that he wants to live humbly for one
1-1 定义显示进度指示的图形
drawable目录下progress_v_01.xml
关于shape使用详情可 查阅 点击打开链接
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <!--默认图形大小--> <size android:width="500dp" android:height="50dp" /> <!--填充颜色 --> <solid android:color="#6633CC" /> <!--边框角度?--> <corners android:radius="20dp" /> </shape>
效果图 1-1-1
1-2. 在drawable目录下新建一个clip标签的文件
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal" android:drawable="@drawable/progress_v_01" android:gravity="left"> </clip>
clipOrientation设置方向为水平方向
gravity设置过程中对齐方式为左
drawable 中引用要显示设置的图形
1-3.在页面布局文件中使用
在src属性下引入我们1-2中创建的clip标签的文件
<ImageView android:layout_margin="10dp" android:background="#e6e6e6" android:id="@+id/iv_image_clip_left" android:layout_width="match_parent" android:layout_height="wrap_content" android:src="@drawable/clip_left_01"/>
1.4 在java代码中动态设置进度
private ImageView mClipLeftImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mClipLeftImageView = (ImageView) findViewById(R.id.iv_image_clip_left); mClipLeftImageView.setImageLevel(10000); handler.postDelayed(runnable,2000); } private int mUnmber = 0; private Handler handler = new Handler(); Runnable runnable = new Runnable() { @Override public void run() { if (mUnmber<=10000){ mClipLeftImageView.getDrawable().setLevel(mUnmber); handler.postDelayed(runnable,20); mUnmber+=100; } } };
2-1 定义显示进度的图片,这里使用的是1-1中定义的图形
2-2 创建clip标签文件
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal" android:drawable="@drawable/progress_v_01" android:gravity="right" > </clip>
clipOrientation设置方向为水平方向
gravity设置过程中对齐方式为右(从而达到进度从右向左的实现效果)
drawable 中引用要显示设置的图形
2-3 在布局文件中的使用 同1-3;
2-4 java代码中的设置同 1-4;
3-1 定义显示进度的图片,这里使用的是1-1中定义的图形
3-2 创建clip标签文件
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal" android:drawable="@drawable/progress_v_01" android:gravity="center_horizontal" > </clip>clipOrientation设置方向为水平方向
gravity设置过程中对齐方式 为垂直中心对齐(从而达到进度从中间向两边扩展的实现效果)
3-3 在布局文件中的使用 同 1-3;drawable 中引用要显示设置的图形
3-4 在java代码中的设置同 1-4;
4-1 定义使用到的显示进度的图形 drawbale目录下progress_oval_01.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <!--设置黑夜显示大小--> <size android:width="100dp" android:height="100dp" /> <!--设置图形颜色--> <gradient android:centerColor="#CC9933" android:centerX="0.5" android:centerY="0.5" android:endColor="#33FF33" android:gradientRadius="45" android:startColor="#FFFF33" android:type="radial" /> <!--设置图形边框--> <stroke android:width="2dp" android:color="#0000CC" /> </shape>4-2 创建使用到的clip文件
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal" android:drawable="@drawable/progress_oval_01" android:gravity="left" > </clip>
clipOrientation设置方向为水平方向
gravity设置过程中对齐方式 为左边对齐(从而达到进度从左边向右的扩展的实现效果)
drawable 中引用要显示设置的图形
3-3 在布局文件中的使用 同 1-3;
3-4 在java代码中的设置同 1-4;
5-1 创建显示进度的图形 这里引用的是4-1中创建的图形
5-2 创建对应显示的clip标签文件
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal|vertical" android:drawable="@drawable/progress_oval_01" android:gravity="center" > </clip>
clipOrientation设置方向为水平方向gravity设置过程中对齐方式 为中心对齐(从而达到进度从中间向两边的扩展的实现效果)
5-3 在布局文件中的使用 同 1-3;drawable 中引用要显示设置的图形
创建ImageView标签,在src属性下进行引用
5-4 在java代码中的设置同 1-4;
6-1 创建显示进度的图形
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <size android:width="5dp" android:height="100dp"/> <gradient android:angle="45" android:startColor="#FF9900" android:centerColor="#FFFF00" android:endColor="#66FF00" /> <corners android:radius="5dp"/> </shape>效果图: 6-1-1
6-2 创建对应的clip标签文件
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="vertical" android:drawable="@drawable/progress_oval_01" android:gravity="bottom" > </clip>
clipOrientation设置方向为竖直方向
gravity设置过程中对齐方式 底部(从而达到进度从底部向上增加的实现效果)
如果设置为top,那么进度将成为从上到下
6-3 在布局文件中的使用 同 1-3;drawable 中引用要显示设置的图形
创建ImageView标签,在src属性下进行引用
6-4 在java代码中的设置同 1-4;
ClipDrawable代表从其它位图上截取一个“图片片段”。在XML文件中使用<clip.../>元素定义ClipDrawable对象,可指定如下三个属性:
android:drawable:指定截取的源Drawable对象,也可以指定drawable类的子标签
android:clipOrientation:指定截取的方向,可设置为 horizontal vertical
android:gravity:指定截取时的对齐方式,可设置为top bottom right center_vertical fill_vertical center_horizontal center fill clip_vertaical start end 等等
使用ClipDrawable对象时可以调用setLevel(int level)方法来设置截取的区域大小,当level为0时,截取的图片片段为空;当level为10000时,截取整张图片。
可以使用ClipDrawable的这种性质控制截取图片的区域大小,让程序不断调用setLevel方法并改变level的值,达到让图片慢慢展开的效果
效果图 8-1
看这样的进度条确实有点风骚,不过效果还行
9-1 定义一个类,继承ProgressBar
public class HorizontalProgressBarWithNumber extends ProgressBar { public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) { super(context, attrs); } public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Over
官方推荐的使用方式为public class HorizontalProgressBarWithNumber extends ProgressBar { public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) { this(context, attrs, 0); } public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mPaint.setTextSize(mTextSize); mPaint.setColor(mTextColor); } @Over
也就是说g..官方推荐的使用两个构造参数去调用三个构造参数的写法,我个人不建议这样写,两个构造去调用三个构造的方法,那么有时我们在构造中进行初时化操作的时候只需要在三个构造参数的方法进行一次初始化操作就好,但是当我们开发的应用遇到低版本的手机时,会遇到崩溃的问题(无法加载初始化xml布局文件),因为三个构造的方法是在高版本中才有的,所以我这里将初始化的操作全部封装到另一个方法中去,分别在两个构造中和三个构造方法中调用。9-2 复写父控件的onDraw方法,来进行重新绘制
@Override protected synchronized void onDraw(Canvas canvas) { canvas.save(); /** * 定义画笔的初始位置 */ canvas.translate(getPaddingLeft(), getHeight() / 2); /** * 计算加载进度的比例 */ float radio = getProgress() * 1.0f / getMax(); /** * 计算已加载的进度 */ float progressPosX = (int) (mRealWidth * radio); /** * 定义进度上显示的文字信息 */ String text = getProgress() + "%"; /** * 获取绘制文字的宽与高 */ float textWidth = mPaint.measureText(text); float textHeight = (mPaint.descent() + mPaint.ascent()) / 2; /** * 判断绘制 */ if (progressPosX + textWidth > mRealWidth) { progressPosX = mRealWidth - textWidth; } /** * 绘制已加载的进度 */ mPaint.setColor(mBarColor); mPaint.setStrokeWidth(mProgressBarHeight); canvas.drawLine(0, 0, progressPosX, 0, mPaint); /** * 绘制加载显示的文字 */ mPaint.setColor(mTextColor); canvas.drawText(text, progressPosX, -textHeight, mPaint); /** * 绘制未加载的进度 */ float start = progressPosX + textWidth; mPaint.setColor(mUnBarColor); mPaint.setStrokeWidth(mProgressBarHeight); canvas.drawLine(start, 0, mRealWidth, 0, mPaint); canvas.restore(); }
这里进行绘制的过程是 先绘制已加载的进度,然后再绘制显示进度的文字,最后再绘制滑加载的进度,
9-3 设置并初始化相关的变量
其中使用到一些变量,比如绘制文字的颜色,绘制进度的颜色,高度等等。
这里使用的方法是在成员变量中进行了设置默认的值
/** * 定义一个画笔 */ protected Paint mPaint = new Paint(); /** * 设置默认的显示进度文字的颜色 */ protected int mTextColor = 0xff253688; /** * 设置显示默认的显示进度的文字的大小 */ protected int mTextSize = sp2px(10); /** * 设置默认的绘制进度条的高度 */ protected int mProgressBarHeight = dp2px(10); /** * 设置默认的绘制进度条颜色 */ protected int mBarColor = 0xffffcc00; /** * 未加载进度条的颜色 */ protected int mUnBarColor = 0xffe6e6e6; /** * 绘制进度条的实际宽度 */ protected int mRealWidth;
第一个变量是我们绘制过程中使用到的画笔,我们这里在类加载的时候进行了初时化操作,同时也给这个画笔设置一些对应的属性值
private void initFunction(){ mPaint.setTextSize(mTextSize); mPaint.setColor(mTextColor); }
我们这里设置的是显示文字的大小与颜色(如果用到测量的话,在测量的时候可能会用到要测量绘制文字的大小,而我们这里是通过画笔的属性进行测量的)
变量mRealWidth是我们实际中需要绘制的进度条的实际宽度,可以在onMeaure方法中进行初始化(请查看下面的代码块)
也可以在方法中进行初始化
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mRealWidth = w-getPaddingLeft()-getPaddingRight(); }
其他的相应变量就是一些颜色与大小 ,其中有一个个将dp值转为px值的方法和sp转为px的方法(这是一些工具类)
/** * dp 2 px * * @param dpVal */ protected int dp2px(int dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); } /** * sp 2 px * * @param spVal * @return */ protected int sp2px(int spVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getResources().getDisplayMetrics()); }走到这里,我们的自定义进度条就可以使用了当然我们可以设置初始化这些变量的值
/** * 设置已绘制的进度条的颜色 * * @param mBarColor */ public void setmBarColor(int mBarColor) { this.mBarColor = mBarColor; } /** * 设置过度条的高度 * * @param mProgressBarHeight */ public void setmProgressBarHeight(int mProgressBarHeight) { this.mProgressBarHeight = mProgressBarHeight; } /** * 设置指示进度条的显示文字的颜色 * * @param mTextColor */ public void setmTextColor(int mTextColor) { this.mTextColor = mTextColor; } /** * 设置指示进度条进度的显示文字的颜色 * * @param mTextSize */ public void setmTextSize(int mTextSize) { this.mTextSize = mTextSize; } /** * 设置未加载进度条处的进度颜色 * * @param mUnBarColor */ public void setmUnBarColor(int mUnBarColor) { this.mUnBarColor = mUnBarColor; }
9-4 自定义属性方式设置初始化变量值
也可以通过自定义属性的方式来进行操作
values文件夹下attrs.xml文件中
定义自定义属性 :绘制文本的颜色
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="HorizonProgressBarWidthNumber"> <attr name="textProColor" format="color" /> </declare-styleable> </resources>在构造方法中获取到自定义属性的值,并进行相应的赋值操作
/** * 获取自定义属性操作 * @param context * @param attrs * @param defStyle */ private void initFunction(Context context, AttributeSet attrs, int defStyle) { final TypedArray attributes = getContext().obtainStyledAttributes( attrs, R.styleable.HorizonProgressBarWidthNumber); mTextColor = attributes.getColor(R.styleable.HorizonProgressBarWidthNumber_textProColor, 0xff000000); }
9-5 onMeasure方法中的测量
在onMeasure方法进行一些测量
@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一) * 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小) * 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式) */ /** * 三种测量模式 * UNSPECIFIED:父布局没有给子布局任何限制,子布局可以任意大小。 * EXACTLY:父布局决定子布局的确切大小。不论子布局多大,它都必须限制在这个界限里。 * AT_MOST:子布局可以根据自己的大小选择任意大小。 */ /** * 获取测量宽度大小 */ int width = MeasureSpec.getSize(widthMeasureSpec); /** * 对高度进度测量 */ int height = 0; /** * 获取高度的测量模式 */ int specMode = MeasureSpec.getMode(heightMeasureSpec); /** * 获取测量高度的大小 */ int specSize = MeasureSpec.getSize(heightMeasureSpec); /** * 判断如果是非精准度的,那么就进行测量大小的重新设定 */ if (specMode == MeasureSpec.EXACTLY) { height = specSize; } else { /** * 获取显示加载进度的显示文本的宽度与高度 */ float textHeight = (mPaint.descent() - mPaint.ascent()); /** * 计算测量的高度 */ height = (int) (getPaddingTop() + getPaddingBottom() + Math.max( mProgressBarHeight, Math.abs(textHeight))); if (specMode == MeasureSpec.AT_MOST) { height = Math.min(height, specSize); } } /** * 设置测量 */ setMeasuredDimension(width, height); /** * 获取实际需要绘制进度条的宽度 */ mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft(); }
9-6 风骚进度条设置使用
使用:
在xml中引入控件
在java代码中
public class CustomProgressActivity extends Activity { private HorizontalProgressBarWithNumber mProgressBarView; private int mNumber = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_progress); mProgressBarView = (HorizontalProgressBarWithNumber) findViewById(R.id.custom_progress_view); mProgressBarView.setMax(100); handler.sendEmptyMessage(1001); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1001) { mProgressBarView.setmBarColor(randomColor()); mProgressBarView.setProgress(mNumber); if (mNumber > 100) { handler.removeMessages(1001); } if (mNumber < 100) { handler.sendEmptyMessageDelayed(1001, 300); } mNumber++; } } }; public int randomColor(){ Random random = new Random(); //如果值太大,会偏白,太小则会偏黑,所以需要对颜色的值进行范围限定 int red = random.nextInt(150)+50;//50-199 int green = random.nextInt(150)+50;//50-199 int blue = random.nextInt(150)+50;//50-199 return Color.rgb(red, green, blue);//根据rgb混合生成一种新的颜色 } }
到这里就可以设置比较风骚的水平进度条了,我这里只是动态改变了绘制已加载进度条的颜色
效果图 10-1
写作过程同 9 ,主要是在onDraw方法中进行的绘制
@Override protected synchronized void onDraw(Canvas canvas) { /** * 获取显示进度的文字指示 */ String text = getProgress() + "%"; /** * 获取显示进度的文字的宽与高 */ float textWidth = mPaint.measureText(text); float textHeight = (mPaint.descent() + mPaint.ascent()) / 2; canvas.save(); /** * 将画布移动到中心 */ canvas.translate(getPaddingLeft() + mProgressBarHeight / 2, getPaddingTop() + mProgressBarHeight / 2); mPaint.setStyle(Style.STROKE); /** * 绘制未加载的进度 */ mPaint.setColor(mUnReachedBarColor); mPaint.setStrokeWidth(mProgressBarHeight); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); /** * 绘制已加载的圆环进度 */ mPaint.setColor(mReachedBarColor); mPaint.setStrokeWidth(mProgressBarHeight); float sweepAngle = getProgress() * 1.0f / getMax() * 360; canvas.drawArc(new RectF(0, 0, mRadius * 2, mRadius * 2), 0, sweepAngle, false, mPaint); /** * 绘制显示进行的颜色 */ mPaint.setStyle(Style.FILL); canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight, mPaint); canvas.restore(); }
/** * 定义设置进度圆的默认半径 */ private int mRadius = dp2px(30); /** * 圆环的默认宽度 */ private int mProgressBarHeight = dp2px(5); /** * 声明初始化一个画笔 */ private Paint mPaint = new Paint(); /** * 设置未加载进度的默认颜色 */ private int mUnReachedBarColor = 0xffe6e6e6; /** * 设置已加载进度的默认颜色 */ private int mReachedBarColor = 0xff89cc99; /** * 设置进度已加载进度条的颜色 * 这里只写了这个设置颜色 * 当然也可以写出代码动态设置改变 未加载进度条的颜色 * 还有显示文字的颜色 * 还有进度条的宽度等等 * @param color */ public void setReachedBarColor(int color){ this.mReachedBarColor = color; }
public RoundProgressBar(Context context) { this(context, null); } public RoundProgressBar(Context context, AttributeSet attrs) { this(context, attrs,0); } public RoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint.setStyle(Style.STROKE); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStrokeCap(Cap.ROUND); }
代码中的使用
public class MainActivity extends Activity { private int number =0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final RoundProgressBar progress1 = (RoundProgressBar)findViewById(R.id.progress1); progress1.setMax(100); final RoundProgressBar progress2 = (RoundProgressBar)findViewById(R.id.progress2); progress2.setMax(100); new Timer().schedule(new TimerTask() { @Override public void run() { if (number>10){ progress2.setReachedBarColor(0xff00FF00); }else if (number>10){ progress2.setReachedBarColor(0xff00FF00); }else if (number>20){ progress2.setReachedBarColor(0xff228B22); }else if (number>30){ progress2.setReachedBarColor(0xff008000); }else if (number>40){ progress2.setReachedBarColor(0xff006400); }else if (number>50){ progress2.setReachedBarColor(0xff483D8B); }else if (number>60){ progress2.setReachedBarColor(0xff8A2BE2); }else if (number>70){ progress2.setReachedBarColor(0xff4B0082); }else if (number>90){ progress2.setReachedBarColor(0xff8B008B); } progress2.setProgress(number); progress1.setProgress(number); number+=1; } }, 0, 100); } }
关于计时器Timer与TimerTask使用
可以点击查看
原文:http://blog.csdn.net/zl18603543572/article/details/51250216