在自定义View-仿QQ运动步数进度效果基础上衍生的网络加载,效果图如下:
<declare-styleable name="LoadingView">
<attr name="typeLoading" format="string"/>
<attr name="circleWidth" format="dimension"/>
<attr name="InnerColor" format="color"/>
<attr name="foreginColor" format="color" />
</declare-styleable>
<com.example.myapplication.Widget.LoadingView
android:id="@+id/loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:foreginColor="@color/colorBlue"
app:InnerColor="@color/colorRed"
app:circleWidth="5dp"
app:typeLoading="water"
/>
package com.example.myapplication.Widget;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;
import androidx.annotation.Nullable;
import com.example.myapplication.R;
public class LoadingView extends View {
/**
* 内外弧的宽高
*/
private int circleWidth = 5;
/**
* 内弧颜色
*/
private int InnerColor = Color.BLUE;
/**
* 外弧颜色
*/
private int foreginColor = Color.RED;
/**
* 圆角颜色,也可在layout中设置背景,如果自己设置背景的话还要加圆角,这里已经是处理好了
*/
private int rectColor = Color.parseColor("#999999");
/**
* 外弧画笔
*/
private Paint paintforegin;
/**
* 内弧画笔
*/
private Paint paintInner;
/**
* 背景圆角画笔
*/
private Paint paintRect;
/**
* 外弧起始与终止点
*/
private int startForegin = 135;
private int endForegin = 275;
/**
* 内弧起始与终止点
*/
private int startInner = 45;
private int endInner = 90;
/**
* 内外弧半径
*/
private int radus = 150;
private int innerPading = radus - 70;
/**
* 背景圆角的半径
*/
private int rectRadus = radus + 50;
/**
* 背景圆角大小
*/
private int rectCircle = 30;
public LoadingView(Context context) {
super(context, null);
}
public LoadingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initType(attrs, context);
loading();
}
/**
* 获得属性
* @param attrs
* @param context
*/
private void initType(AttributeSet attrs, Context context) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LoadingView);
foreginColor = typedArray.getColor(R.styleable.LoadingView_foreginColor, foreginColor);
InnerColor = typedArray.getColor(R.styleable.LoadingView_InnerColor, InnerColor);
circleWidth = typedArray.getDimensionPixelSize(R.styleable.LoadingView_circleWidth, circleWidth);
typedArray.recycle();
initCirclePaint();
}
/**
* 初始化画笔
*/
private void initCirclePaint(){
paintforegin = new Paint();
paintforegin.setAntiAlias(true);
paintforegin.setDither(true);
paintforegin.setStrokeWidth(circleWidth);
paintforegin.setColor(foreginColor);
paintforegin.setStyle(Paint.Style.STROKE);
paintforegin.setStrokeCap(Paint.Cap.ROUND);
paintforegin.setStrokeJoin(Paint.Join.ROUND);
paintInner = new Paint();
paintInner.setAntiAlias(true);
paintInner.setDither(true);
paintInner.setStrokeWidth(circleWidth);
paintInner.setColor(InnerColor);
paintInner.setStyle(Paint.Style.STROKE);
paintInner.setStrokeJoin(Paint.Join.ROUND);
paintInner.setStrokeCap(Paint.Cap.ROUND);
paintRect = new Paint();
paintRect.setAntiAlias(true);
paintRect.setDither(true);
paintRect.setColor(rectColor);
paintRect.setStyle(Paint.Style.FILL);
}
/**
* 测量处理
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取宽高的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//指定宽高的大小
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//如果宽高设置为wrap_content时,刚默认为300
if(widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST){
width = 300;
height = width;
}
//如果宽高不一致时,则以宽为标准
if(width != height){
height = width;
}
setMeasuredDimension(width,height);
}
/**
* 中心点
*/
private int y;
private int x;
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
x = (right - left) / 2;
y = (bottom - top) / 2;
super.onLayout(changed, left, top, right, bottom);
}
private int DptoPx(int dp, Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
@Override
protected void onDraw(Canvas canvas) {
drawCircle(canvas);
drawArc(canvas);
drawArc2(canvas);
}
/**
* 绘制外弧
* @param canvas
*/
private void drawArc(Canvas canvas) {
RectF rectF = new RectF(x - radus, y - radus, x + radus, y + radus);
canvas.drawArc(rectF, startForegin, endForegin, false, paintforegin);
}
/**
* 绘制内弧
* @param canvas
*/
private void drawArc2(Canvas canvas) {
RectF rectF = new RectF(x - innerPading, y - innerPading, x + innerPading, y + innerPading);
canvas.drawArc(rectF, startInner, endInner, false, paintInner);
}
/**
* 绘制背景圆角
* @param canvas
*/
private void drawCircle(Canvas canvas){
RectF rectF = new RectF(x - rectRadus, y - rectRadus, x + rectRadus, y + rectRadus);
canvas.drawRoundRect (rectF,rectCircle,rectCircle,paintRect);
}
/**
* 绘制更新
* @param value
*/
private void reDraw(int value) {
startForegin += value;
startInner -= value;
postInvalidate();
}
/**
* 设置属性动画来重新绘制
*/
@SuppressLint("WrongConstant")
private void loading() {
ValueAnimator valueAnimator = ValueAnimator.ofInt(0,2);
valueAnimator.setDuration(1);
//设置重复次数
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
//设置重复模式
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (int) valueAnimator.getAnimatedValue();
reDraw(value);
}
});
}
}
简书地址:Android-自定义View网络加载