我们经常会看到这样的网络加载效果:
思路分析:
1.这个控件是一个组合控件,我们需要一个自定义圆,然后一个自定义ViewGroup排列这几个圆。
2.在这个ViewGroup里面找到这些圆的对象,然后添加属性动画。
3.监听动画事件,处理变色效果。
圆的绘制
public class MyCircleView extends View {
private int circle_color;
private Paint paint;
private int width;
private int height;
private int radius;
public MyCircleView(Context context) {
this(context,null);
}
public MyCircleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public MyCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.MyCircleView);
circle_color = a.getColor(R.styleable.MyCircleView_circle_color,
getResources().getColor(R.color.red));
a.recycle();
initPaint();
}
private void initPaint() {
paint = new Paint();
paint.setDither(true);
paint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width > height ? height : width, width > height ? height : width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
radius = (width > height ? height : width)/2;
canvas.drawCircle(radius,radius, radius,paint);
}
public void setCircle_color(int color){
Log.e("color+",color+"");
paint.setColor(color);
invalidate();
}
public int getCircle_color(){
return circle_color;
}
}
自定义属性(只需要一个颜色,用于添加画笔颜色)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCircleView">
<attr name="circle_color" format="color"/>
</declare-styleable>
</resources>
自定义ViewGroup
public class MyCircleLayout extends LinearLayout {
private MyCircleView c_red;
private MyCircleView c_green;
private MyCircleView c_blue;
private int r;
public static final int DEFAULT_TIME = 1600;
public MyCircleLayout(Context context) {
this(context,null);
}
public MyCircleLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public MyCircleLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayout();
post(new Runnable() {
@Override
public void run() {
//view绘制完成才能获取宽高
r = c_red.getWidth()/2;
c_red.setCircle_color(Color.parseColor("#FF0000"));
c_green.setCircle_color(Color.parseColor("#FFFF00"));
c_blue.setCircle_color(Color.parseColor("#0000FF"));
animFromLeftToRight(c_red);
animFromRightToLeft(c_blue);
}
});
}
private void animFromRightToLeft(final MyCircleView view) {
ObjectAnimator animator = ObjectAnimator
.ofFloat(view,"translationX",0,
-(getWidth()-2*r-1),0);
animator.setDuration(DEFAULT_TIME);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float f = animation.getAnimatedFraction();
long v = animation.getCurrentPlayTime();
float f1 = new BigDecimal(((float)v/(float) DEFAULT_TIME))
.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
if (f1 == 0.25f){
c_red.setCircle_color(Color.parseColor("#FFFF00"));
c_green.setCircle_color(Color.parseColor("#0000FF"));
c_blue.setCircle_color(Color.parseColor("#FF0000"));
}
if (f1 == 0.75f) {
c_red.setCircle_color(Color.parseColor("#FF0000"));
c_green.setCircle_color(Color.parseColor("#FFFF00"));
c_blue.setCircle_color(Color.parseColor("#0000FF"));
}
if (f == 1.0f){
animFromRightToLeft(view);
}
}
});
animator.start();
}
private void animFromLeftToRight(final MyCircleView view) {
ObjectAnimator animator = ObjectAnimator
.ofFloat(view,"translationX",0,
getWidth()-2*r,0);
animator.setDuration(DEFAULT_TIME);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float f = animation.getAnimatedFraction();
if (f == 1.0f){
animFromLeftToRight(view);
}
}
});
animator.start();
}
private void initLayout() {
inflate(getContext(),R.layout.loading_view,this);
initChildView();
}
private int dp2x(int dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getResources().getDisplayMetrics());
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public int px2dp(float pxValue) {
return (int) (pxValue / Resources.getSystem().getDisplayMetrics().density);
}
private void initChildView() {
c_red = findViewById(R.id.circle_red);
//c_red.setCircle_color(R.color.red);
c_green = findViewById(R.id.circle_green);
//c_green.setCircle_color(R.color.yellow);
c_blue = findViewById(R.id.circle_blue);
//c_blue.setCircle_color(R.color.blue);
}
}
ViewGroup里面的布局排列:
<?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:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.example.view_08.MyCircleView
android:id="@+id/circle_red"
android:layout_width="15dp"
android:layout_height="15dp"
/>
<com.example.view_08.MyCircleView
android:id="@+id/circle_green"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginLeft="20dp"
/>
<com.example.view_08.MyCircleView
android:id="@+id/circle_blue"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginLeft="20dp"
/>
</LinearLayout>
最后在ManActivity布局中添加:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.view_08.MyCircleLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>