转载请注明出处:http://blog.csdn.net/binbinqq86/article/details/46313437
这种效果在游戏中见到的比较多,一般用在初始化加载的时候。最近项目中需要用到这种效果,于是就自己实现了一个,废话不多说,先上效果图

怎么样,如果你感兴趣,就继续向下看吧~
首先说说实现的原理:整个界面上下是两个文本布局,没什么说的,主要是中间的动画展示进度条层。不要小看这一层哦,它一共包含了上、中、下三层,每一层都是一个自定义的View。最下层就是那个5段的总进度加上蓝色段分割线,而中间层是动画向前冲的那层,最上层就是蓝色走过的每两段之间的竖直白色分割线~好晕
下面还是直接看实际代码:
package com.binbin.tprogressbar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.binbin.mywidget.R;
/**
* 三层分段组合进度条最底层背景层
* @author tianbin
*
* Created on 2015-3-12 下午2:21:22
*/
public class ProgressBottomView extends View {
private Paint mPaint;
/**
* 边框颜色
*/
private int lineColor=0xFFA0DB58;
/**临时的画布对象*/
private Bitmap mBitmap;
/**临时的画布*/
private Canvas mCanvas;
/**画布宽高*/
private float height,width;
/**两边圆的直径*/
private float rad;
/**画笔宽*/
private float penWidth;
public ProgressBottomView(Context context) {
this(context, null);
}
public ProgressBottomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressBottomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
rad=getResources().getDimension(R.dimen.dpradius);
penWidth=getResources().getDimension(R.dimen.penwidth);
height=getResources().getDimension(R.dimen.height);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width=getMeasuredWidth();
mPaint = new Paint();
mPaint.setColor(lineColor);
mPaint.setStrokeWidth(penWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setSubpixelText(true);
mBitmap = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_4444);
mCanvas = new Canvas(mBitmap);
//画左边半圆
RectF rf=new RectF(0, 0,rad ,height);
/**
* oval :指定圆弧的外轮廓矩形区域。
startAngle: 圆弧起始角度,单位为度。
sweepAngle: 圆弧扫过的角度,顺时针方向,单位为度。
useCenter: 如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形。
*/
mCanvas.drawArc(rf, 90, 180, false, mPaint);
//画右边半圆
RectF rf1=new RectF(width-rad, 0,width ,height);
mCanvas.drawArc(rf1, -90, 180, false, mPaint);
mPaint.setStyle(Paint.Style.FILL);
//画上下两条线
mCanvas.drawLine(rad/2f, 0, width-rad/2f, 0, mPaint);
mCanvas.drawLine(rad/2f, height, width-rad/2f, height, mPaint);
//画垂直的分割线
for(int i=0;i<TProgressView.duanNum-1;i++){
//画垂直的分割线
mCanvas.drawLine(width*(i+1)/TProgressView.duanNum, 0, width*(i+1)/TProgressView.duanNum, height, mPaint);
}
//把准备好的bitmap绘制到当前画布上
canvas.drawBitmap(mBitmap, 0, 0, null);
}
public int getLineColor() {
return lineColor;
}
/**
* 设置边框颜色
* @param color
*/
public void setLineColor(int color){
this.lineColor=color;
invalidate();
}
}
package com.binbin.tprogressbar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import com.binbin.mywidget.R;
/**
* 三层分段组合进度条中间滑动层
* @author tianbin
*
* Created on 2015-3-12 下午2:21:56
*/
public class ProgressMiddleView extends View {
private Paint mPaint;
/**
* 线颜色
*/
private int lineColor=0xFFA0DB58;
/**临时的画布对象*/
private Bitmap mBitmap;
/**临时的画布*/
private Canvas mCanvas;
/**画布宽高*/
private float height,width;
/**画笔宽*/
private float penWidth;
/**两边圆的直径*/
private float rad;
public ProgressMiddleView(Context context) {
this(context, null);
}
public ProgressMiddleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressMiddleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
penWidth=getResources().getDimension(R.dimen.penwidth);
height=getResources().getDimension(R.dimen.height);
rad=getResources().getDimension(R.dimen.dpradius);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width=getMeasuredWidth();
//把准备好的bitmap绘制到当前画布上
if(mBitmap==null){
return;
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
/**
* 设置画线颜色
* @param lineColor
*/
public void setLineColor(int lineColor) {
this.lineColor = lineColor;
}
public int getLineColor() {
return lineColor;
}
/**
* 根据当前进度坐标画进度条
* @param x 当前进度在屏幕上的坐标
*/
public void drawMiddle(int x){
if(width<=0||height<=0){
return;
}
mPaint = new Paint();
mPaint.setColor(lineColor);
mPaint.setStrokeWidth(penWidth);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mPaint.setSubpixelText(true);
mBitmap = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_4444);
mCanvas = new Canvas(mBitmap);
/**画左边圆*/
mCanvas.drawCircle(rad/2, rad/2, rad/2, mPaint);
/**画中间矩形*/
mCanvas.drawRect(rad/2, 0, x-rad, height, mPaint);
/**画右边圆*/
mCanvas.drawCircle(x-rad, rad/2, rad/2, mPaint);
invalidate();
}
}
package com.binbin.tprogressbar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import com.binbin.mywidget.R;
/**
* 三层分段组合进度条最顶层分割白线层
* @author tianbin
*
* Created on 2015-3-12 下午2:21:56
*/
public class ProgressTopView extends View {
private Paint mPaint;
/**
* 线颜色
*/
private int lineColor=0xFFFFFFFF;
/**临时的画布对象*/
private Bitmap mBitmap;
/**临时的画布*/
private Canvas mCanvas;
/**画布宽高*/
private float height,width;
/**画笔宽*/
private float penWidth;
public ProgressTopView(Context context) {
this(context, null);
}
public ProgressTopView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressTopView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
penWidth=getResources().getDimension(R.dimen.penwidth);
height=getResources().getDimension(R.dimen.height);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width=getMeasuredWidth();
//把准备好的bitmap绘制到当前画布上
if(mBitmap==null){
return;
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
/**
* 设置画线颜色
* @param lineColor
*/
public void setLineColor(int lineColor) {
this.lineColor = lineColor;
}
public int getLineColor() {
return lineColor;
}
/**
* 根据数量画分割线
* @param num
*/
public void drawLine(int num){
if(width<=0||height<=0){
return;
}
mPaint = new Paint();
mPaint.setColor(lineColor);
mPaint.setStrokeWidth(penWidth);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mBitmap = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_4444);
mCanvas = new Canvas(mBitmap);
for(int i=0;i<num;i++){
//画垂直的分割线
mCanvas.drawLine(width*(i+1)/TProgressView.duanNum, 0, width*(i+1)/TProgressView.duanNum, height, mPaint);
}
invalidate();
}
}三层的代码就这么多,怎么样,是不是有点眉目了,下面就用一个自定义view把这三层view整合起来,这样便于在代码中引用:
package com.binbin.tprogressbar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import com.binbin.mywidget.R;
import com.nineoldandroids.animation.IntEvaluator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
/**
* 自定义带动画分段显示进度条,目前暂不支持直接设置段数,需要手动重写
* @author tianbin
*
* Created on 2015-3-12 下午4:29:35
*/
public class TProgressView extends FrameLayout {
/**控件宽度*/
private int viewWidth;
/**中间动画层*/
private ProgressMiddleView progressView;
/**顶层白色垂直分割线层*/
private ProgressTopView ptv;
/**底层*/
private ProgressBottomView pbv;
/**当前进度*/
private int progress;
/**进度条分为几段(5段有6个等级值,4个垂直分割线)*/
public static int duanNum=5;
/**等级分级标准*/
private int[] positions=new int[duanNum+1];
/**动画完成时间(ms)*/
private long animTime=1000;
public TProgressView(Context context) {
this(context, null);
}
public TProgressView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TProgressView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
pbv=new ProgressBottomView(context);
progressView=new ProgressMiddleView(context);
// progressView.setBackgroundResource(R.drawable.my_of_bg);
//默认不可见,动画开始时可见
progressView.setVisibility(8);
ptv=new ProgressTopView(context);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TProgressView, defStyle, 0);
int mBottomColor = a.getColor(R.styleable.TProgressView_bottom_color, pbv.getLineColor());
int mTopColor = a.getColor(R.styleable.TProgressView_top_color, ptv.getLineColor());
int mMiddleColor = a.getColor(R.styleable.TProgressView_bottom_color, progressView.getLineColor());
a.recycle();
//设置边框颜色
pbv.setLineColor(mBottomColor);
ptv.setLineColor(mTopColor);
progressView.setLineColor(mMiddleColor);
addView(pbv);
addView(progressView,(int)getResources().getDimension(R.dimen.height),(int)getResources().getDimension(R.dimen.height));
addView(ptv);
}
/**
* 执行动画
* @param target 执行动画的目标控件
* @param start 开始坐标
* @param end 结束坐标
*/
@SuppressLint("NewApi")
private void performAnimate(final View target, final int start,
final int end) {
// 把当前进度等分成多少份
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, end);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
// 持有一个IntEvaluator对象,方便下面估值的时候使用
private IntEvaluator mEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator animator) {
// 获得当前动画的进度值,整型,1-100之间
int currentValue = (Integer) animator.getAnimatedValue();
progressView.drawMiddle(currentValue);
if (currentValue < viewWidth * 1f / duanNum) {
} else if (currentValue < viewWidth * 2f / duanNum) {
ptv.drawLine(1);
} else if (currentValue < viewWidth * 3f / duanNum) {
ptv.drawLine(2);
} else if (currentValue < viewWidth * 4f / duanNum) {
ptv.drawLine(3);
} else {
ptv.drawLine(4);
}
// 计算当前进度占整个动画过程的比例,浮点型,0-1之间
float fraction = (float) currentValue / end;
// 直接调用整型估值器通过比例计算出宽度,然后再设给view
target.getLayoutParams().width = mEvaluator.evaluate(fraction,
start, end);
target.requestLayout();
}
});
valueAnimator.setDuration(animTime).start();
}
/**
* 开始动画
*/
public void startAnim(){
//延时,以便得到viewWidth
postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
progressView.setVisibility(0);
int pos=calculatePosition();
if(progress>=positions[positions.length-1]){
pos+=1;
}else if(progress>0){
pos+=10;
}
performAnimate(progressView, progressView.getWidth(), pos);
}
}, 100);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
super.onLayout(changed, left, top, right, bottom);
if(changed){
viewWidth=getMeasuredWidth();
}
}
private int calculatePosition(){
int pos=0;
if(viewWidth==0){
return pos;
}
//每一段的长度
float perLength=viewWidth/duanNum;
if(progress<positions[0]){
pos=0;
}else if(progress<positions[1]){
pos=(int) (perLength*(float)(progress/(positions[1]-positions[0])));
}else if(progress<positions[2]){
pos=(int) (perLength*(1+(float)(progress-positions[1])/(positions[2]-positions[1])));
}else if(progress<positions[3]){
pos=(int) (perLength*(2+(float)(progress-positions[2])/(positions[3]-positions[2])));
}else if(progress<positions[4]){
pos=(int) (perLength*(3+(float)(progress-positions[3])/(positions[4]-positions[3])));
}else if(progress<positions[5]){
pos=(int) (perLength*(4+(float)(progress-positions[4])/(positions[5]-positions[4])));
}else{
pos=(int) (perLength*5);
}
return pos;
}
public int getProgress() {
return progress;
}
/**
* 设置当前进度
* @param progress
*/
public void setProgress(int progress) {
this.progress = progress;
}
public int[] getPositions() {
return positions;
}
/**
* 设置每段代表的进度值
* @param positions
*/
public void setPositions(int[] positions) {
this.positions = positions;
}
public long getAnimTime() {
return animTime;
}
public void setAnimTime(long animTime) {
this.animTime = animTime;
}
}
下面终于派上用场了,在Activity中引用:
package com.binbin.mywidget;
import com.binbin.tprogressbar.TProgressView;
import android.app.Activity;
import android.os.Bundle;
public class ProgressActivity extends Activity {
private TProgressView tpv;
private int[] positions=new int[]{0,50,100,200,450,800};
private int currentProgress=330;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress_main);
tpv=(TProgressView) findViewById(R.id.tpv);
tpv.setPositions(positions);
tpv.setProgress(currentProgress);
tpv.startAnim();
}
}
下面是一些布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#fff"
android:orientation="vertical"
android:padding="20dp" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="12dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_degree1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="1级"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_degree2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="2级"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_degree3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="3级"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_degree4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="4级"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_degree5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="5级"
android:textColor="#949494"
android:textSize="12sp" />
</LinearLayout>
<com.binbin.tprogressbar.TProgressView
android:id="@+id/tpv"
app:bottom_color="#021356"
app:top_color="#fff"
android:layout_width="match_parent"
android:layout_height="@dimen/height" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_pro1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center_vertical"
android:text="0"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_pro2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="50分"
android:textColor="#949494"
android:textSize="12sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_pro3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="100分"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_pro4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="200分"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_pro5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="450分"
android:textColor="#949494"
android:textSize="12sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="800分"
android:gravity="right|center_vertical"
android:textColor="#949494"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
其实在实现的过程中,顶层跟底层View可以采用图片的方式(不用自定义View),中间滑动层也可以用一个图片来进行水平方向缩放移动来达到效果,这两种方式均可以~
本文介绍如何在Android中实现一个带有动画的不规则分段进度条,常见于游戏初始化加载场景。通过创建多层自定义View,包括上下文布局、动画展示层、动态效果等,实现独特的加载效果。

587

被折叠的 条评论
为什么被折叠?



