之前看到了一个很炫的动态图,是一个加载的进度条
确实挺好看的,有一篇博客做了一个view,几乎一模一样的呈现了和动态图一样的效果
链接看原文
原博客背景用的是一张黄色的图片作为背景.想要修改的话是不能修改的.在我的自定义LeafLoadView中,添加了背景的修改功能
背景和边框都是由Android的view绘制出来的,添加了很多属性,可以自定义修改
我的github链接
LeafLoadView
很多的自定义View
效果图如下
LeafLoadView考入到工程就能使用
一些常见的属性
属性 | 功能 |
---|---|
backgroundColor | 加载精度条的背景颜色 |
borderColor | 边框的颜色 |
seekColor | 进度条的颜色 |
circleLeftStyle | 左边起始加载的时候是选择圆弧还是扇形(boolean值) |
rotationSpeed | 右边圆形图片的旋转数度(一圈的毫秒值) |
borderWidth | 边框的宽度 |
circleWidth | 圆形的外边框宽度 |
circleColor | 圆形的外边框颜色 |
主要是利用Android的canvas。画出各个部分,仔细分析这个View,其中左边是一个半弧,上下各有两个矩形,右边是一个圆环,中间的飞车那车是一个旋转的动画,一步一步的实现这个动画
主要的代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//外层
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mBackgroundColor);
mRect = new RectF(0,0,mHeight,mHeight);
mRectCen=new Rect(mHeight/2,0,mWidth-mHeight/2,mHeight);
canvas.drawArc(mRect,90,180,true,mPaint);
canvas.drawRect(mRectCen,mPaint);
/***********seek****************/
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setColor(mSeekColor);
mCurrentProgressPosition = (mWidth/*-mHeight/2*/) * progress / mTotalProgress;
mRectSeek=new RectF(mBorderWidth,mBorderWidth,mHeight-mBorderWidth,mHeight-mBorderWidth);
//判断在圆弧内部
if(mCurrentProgressPosition<=mHeight-mBorderWidth){
//单边角度
mAngle = (int) Math.toDegrees(Math.acos((mHeight-mBorderWidth - mCurrentProgressPosition)/ (float) (mHeight-mBorderWidth)));
//扫过的角度
mStartAngle = 180 - mAngle;
//进度的seekbar
canvas.drawArc(mRectSeek,mStartAngle,mAngle*2,mCircleStyle,mPaint);
}else { //判断在圆弧外了,需要填满圆弧,并且还要填矩形
canvas.drawArc(mRectSeek,90,180,mCircleStyle,mPaint);
seekRect=new Rect(mHeight/2,mBorderWidth,mCurrentProgressPosition-mHeight/2,mHeight-mBorderWidth);
canvas.drawRect(seekRect,mPaint);
}
/***********seek over****************/
//内层弧度
mRect=new RectF(mBorderWidth/2,mBorderWidth/2,mHeight-mBorderWidth/2,mHeight-mBorderWidth/2);
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setColor(mBorderColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mBorderWidth);
canvas.drawArc(mRect,90,180,false,mPaint);
//上下两条线
mPath.moveTo(mHeight/2,mBorderWidth/2);
mPath.lineTo(mWidth-mHeight/2,mBorderWidth/2);
canvas.drawPath(mPath,mPaint);
mPath.close();
mPath.moveTo(mHeight/2,mHeight-mBorderWidth/2);
mPath.lineTo(mWidth-mHeight/2,mHeight-mBorderWidth/2);
canvas.drawPath(mPath,mPaint);
mPath.close();
//画圆
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setColor(mCircleColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mCircleWidth);
canvas.drawCircle(mWidth-mHeight/2,mHeight/2,mHeight/2- mCircleWidth/2,mPaint);
//画右边的图片
// mPaint.reset();
// canvas.drawBitmap(mRightBitmap,mWidth- mHeight+mBorderWidth,mBorderWidth,mPaint);
}
通过这里,画出了主要的view。其中有风扇的动画
public void rotationView(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"rotation",0,360);
animator.setDuration(mRotationSpeed);
animator.setRepeatCount(Animation.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.setRepeatMode(Animation.RESTART);
animator.start();
}
计算位置是比较麻烦的事儿,有需要的话可以研究研究,在activity中的使用也比较简单
如下:
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
private int totalPro=100;
private int progress=0;
private LeafLoadView mLeafLoadView;
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
progress = progress + 1;
mLeafLoadView.setPrograss(progress);
mHandler.sendEmptyMessageDelayed(1,800); //800ms发送一次
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mLeafLoadView = (LeafLoadView) findViewById(R.id.leafview);
ImageView imageView= (ImageView) findViewById(R.id.fan_p);
//设置精进度条的最大值
mLeafLoadView.setTotalProgress(totalPro);
//设置进度条每次的更新的值
mLeafLoadView.rotationView(imageView);
//handler发送延迟,更新界面
mHandler.sendEmptyMessageDelayed(1,0);
}
布局如下