高级UI晋升之自定义View实战(九)

更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680

1.前言:

本文采用自定义view的方法来实现一键清除的动画这个功能。

2.效果图:

 
19956127-b1982e8e14ae7167.gif
 

3.具体详细代码

3.1 \res\values\attrs_on_key_clear_circle_view.xml

<resources>  
    <declare-styleable name="OnKeyClearCircleView">  
        <attr name="innerCircleColor" format="color" />  
        <attr name="outCircleColor" format="color" />  
        <attr name="innerCircleRadius" format="integer" />  
        <attr name="progress" format="integer" />  
        <attr name="textSize" format="dimension" />  
        <attr name="outArcwidth" format="dimension" />  
    </declare-styleable>  
</resources>  

对属性的说明:

  一般,我们在res/values文件夹中添加attrs.xml文件来放置,其实,这个文件名并不一定要写成attrs.xml,但是按照安卓源码的写法并且也便于别人查看代码的时候明确这个文件的用意,还是写成attrs.xml。
  我们可以参看一下安卓的源码:打开源码文件夹下\frameworks\base\core\res\res\values\attrs.xml文件,我们会发现这里面定义了很多attr的标签,下面是我从这里面找到的一些:
<attr name="buttonBarStyle" format="reference" />  
<attr name="cacheColorHint" format="color" />  
<attr name="textColorHint" format="reference|color" />  
<attr name="textIsSelectable" format="boolean" />  
<attr name="scrollbarFadeDuration" format="integer" />  
<attr name="alpha" format="float" />  
<attr name="textSize" format="dimension" />  
<attr name="columnDelay" format="float|fraction" />  
<attr name="fontFamily" format="string" />  
   
    <!-- Default text typeface. -->  
    <attr name="typeface">  
        <enum name="normal" value="0" />  
        <enum name="sans" value="1" />  
        <enum name="serif" value="2" />  
        <enum name="monospace" value="3" />  
    </attr>  
   
    <!-- Default text typeface style. -->  
    <attr name="textStyle">  
        <flag name="normal" value="0" />  
        <flag name="bold" value="1" />  
        <flag name="italic" value="2" />  
    </attr>  

其中,format代表的是这条属性的值的类型:
1.reference: 参考指定Theme中资源ID,这个类型意思就是你传的值可以是引用资源
2.string: 字符 如果你想别人既能直接写值也可以用类似"@string/test"引用资源的方式,可以写成format="string|reference"
3.Color: 颜色
4.boolean: 布尔值
5.dimension: 尺寸值
6.float: 浮点型
7.integer: 整型
8.fraction: 百分数
9.enum: 枚举 ,如果你提供的属性只能让别人选择,不能随便传入,
10.flag: 位或运算

写法样例:

<declare-styleable name="TextViewMultiLineBackgroundState">  
        <!-- State identifier indicating a TextView has a multi-line layout. -->  
        <attr name="state_multiline" format="boolean" />  
    </declare-styleable>  

3.2 OnKeyClearCircleView.java

import android.content.Context;  
import android.content.res.TypedArray;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Matrix;  
import android.graphics.Paint;  
import android.graphics.RectF;  
import android.graphics.SweepGradient;  
import android.util.AttributeSet;  
import android.util.Log;  
import android.view.View;  
import com.example.administrator.customview.R;  
  
public class OnKeyClearCircleView extends View implements Runnable{  
  
    private static final String TAG = "OnKeyClearCircleView";  
    private Paint paint;  
    private Paint outCirclePaint;  
    private Paint textPaint;  
    private Paint outArcPaint;  
    private Paint radarPain;  
    private Paint pointPain;  
  
    private int radarRotateDegree;  
    private int innerCircleColor;  
    private int innerCircleRadius;  
    private int outCircleColor;  
    private float outArcwidth;  
  
    private SweepGradient outArcSweepGradient;  
    private SweepGradient radarSweepGradient;  
  
    private Bitmap pointDrawable;  
    private Matrix pointRotate=new Matrix();  
  
    private int progress;  
    private float textSize;  
    private int padding;  
  
    private float startAngle;  
    private float radarSweepAngle;  
    private float pointRotateDegree;  
  
    private boolean isSart;  
  
    public OnKeyClearCircleView(Context context) {  
        super(context);  
        init(null, 0);  
    }  
  
    public OnKeyClearCircleView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        init(attrs, 0);  
    }  
  
    public OnKeyClearCircleView(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
        init(attrs, defStyle);  
    }  
  
    private void init(AttributeSet attrs, int defStyle) {  
        final TypedArray a = getContext().obtainStyledAttributes(  
                attrs, R.styleable.OnKeyClearCircleView, defStyle, 0);  
        innerCircleColor = a.getColor(R.styleable.OnKeyClearCircleView_innerCircleColor, Color.BLUE);  
        outCircleColor = a.getColor(R.styleable.OnKeyClearCircleView_outCircleColor, Color.GRAY);  
        innerCircleRadius = a.getInt(R.styleable.OnKeyClearCircleView_innerCircleRadius, 10);  
        progress = a.getInt(R.styleable.OnKeyClearCircleView_progress,0);  
        textSize = a.getDimension(R.styleable.OnKeyClearCircleView_textSize, 20);  
        outArcwidth = a.getDimension(R.styleable.OnKeyClearCircleView_outArcwidth, 20);  
        a.recycle();  
        pointDrawable = BitmapFactory.decodeResource(getResources(),R.drawable.point);  
        isSart = false;  
        startAngle = 0;  
        radarRotateDegree = 0;  
        radarSweepAngle = 0;  
        pointRotateDegree = 0;  
        padding = 5;  
        paint = new Paint();  
        paint.setAntiAlias(true);  
        paint.setColor(innerCircleColor);  
        outCirclePaint = new Paint();  
        outCirclePaint.setAntiAlias(true);  
        outCirclePaint.setColor(outCircleColor);  
        outCirclePaint.setStyle(Paint.Style.FILL);  
        textPaint = new Paint();  
        textPaint.setTextSize(textSize);  
        textPaint.setAntiAlias(true);  
        outArcPaint = new Paint();  
        outArcPaint.setAntiAlias(true);  
        outArcPaint.setStyle(Paint.Style.STROKE);  
        outArcPaint.setStrokeWidth(outArcwidth);  
        outArcPaint.setStrokeCap(Paint.Cap.ROUND);  
        radarPain = new Paint();  
        outArcPaint.setAntiAlias(true);  
        pointPain = new Paint();  
        pointPain.setAntiAlias(true);  
        Thread thread=new Thread(this);  
        thread.start();  
    }  
  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
        int width = MeasureSpec.getSize(widthMeasureSpec);  
        int height = MeasureSpec.getSize(heightMeasureSpec);  
        int d = (width >= height) ? height : width;  
        setMeasuredDimension(d,d);  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas) {  
  
        int width = getMeasuredWidth();  
        int height = getMeasuredHeight();  
        int pointX =  width/2;  
        int pointY = height/2;  
        RectF rectf = new RectF(outArcwidth/2,outArcwidth/2,width-outArcwidth/2,height-outArcwidth/2);  
        //outArcSweepGradient = new SweepGradient(0,0,getResources().getColor(R.color.start_color),getResources().getColor(R.color.end_color));  
        outArcSweepGradient = new SweepGradient(pointX,pointY,Color.WHITE,Color.WHITE);  
        outArcPaint.setShader(outArcSweepGradient);  
        canvas.drawArc(rectf,startAngle,180,false,outArcPaint);  
  
        canvas.drawCircle(pointX,pointY,pointX -outArcwidth-padding,outCirclePaint);  
  
        if(radarSweepAngle < 180){  
            radarSweepGradient = new SweepGradient(pointX,pointY,Color.WHITE,Color.RED);  
        }else{  
            radarSweepGradient = new SweepGradient(pointX,pointY,Color.WHITE,Color.GREEN);  
        }  
        radarPain.setShader(radarSweepGradient);  
        RectF rectfRadar = new RectF(outArcwidth+padding,outArcwidth+padding,width-outArcwidth-padding,height-outArcwidth-padding);  
        canvas.drawArc(rectfRadar,0,radarSweepAngle,true,radarPain);  
  
        canvas.save();  
        canvas.translate(pointX,pointY);  
        pointRotate.setRotate(pointRotateDegree);  
        canvas.drawBitmap(pointDrawable, pointRotate, pointPain);  
        canvas.restore();;  
  
        canvas.drawCircle(pointX,pointY,innerCircleRadius,paint);  
  
        float textWidth = textPaint.measureText(progress + "%");  
        if(progress < 50){  
            //textPaint.setColor(oxbf3800);  
            textPaint.setColor(Color.RED);  
        }else{  
            //textPaint.setColor(new Color(ox6ec705));  
            textPaint.setColor(Color.GREEN);  
        }  
        canvas.drawText(progress+"%",pointX - textWidth/2,pointY + textSize/2 ,textPaint);  
    }  
  
    @Override  
    public void run() {  
            while(true){  
                if(isSart){  
                    this.startAngle += 20;  
                    if(this.startAngle > 360){  
                        this.startAngle = this.startAngle-360;  
                    }  
                    this.radarSweepAngle += 10;  
                    if(this.radarSweepAngle > 360){  
                        this.radarSweepAngle = this.radarSweepAngle-360;  
                    }  
                    this.pointRotateDegree += 10;  
                    if(this.pointRotateDegree > 360){  
                        this.pointRotateDegree = this.pointRotateDegree-360;  
                    }  
                    progress = (int)radarSweepAngle*100/360;  
  
                    postInvalidate();  
                    try {  
                        Thread.sleep(50);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }  
    }  
  
    public void startClear(){  
        this.isSart =  true;  
    }  
  
    public void stopClear(){  
        this.isSart =false;  
    }  
  
    public int getProgress() {  
        return progress;  
    }  
  
    public void setProgress(int progress) {  
        this.progress = progress;  
    }  
}  

3.3 res\layout\activity_custom_view_activity4.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    tools:context="com.example.administrator.customview.customview04.CustomViewActivity4">  
  
    <com.example.administrator.customview.customview04.OnKeyClearCircleView  
        android:layout_width="200dp"  
        android:layout_height="200dp"  
        android:id="@+id/onKeyClearCircleView"  
        android:background="#fdda6f"  
        app:innerCircleColor="#ffffff"  
        app:innerCircleRadius="35"  
        app:textSize="20sp"  
        app:progress="82"  
        app:outCircleColor="#dbdad7"  
        app:outArcwidth="10dp"  
    />  
  
    <Button  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="start"  
        android:id="@+id/start"  
        android:layout_below="@+id/onKeyClearCircleView"  
        android:layout_alignParentLeft="true"  
        android:layout_alignParentStart="true" />  
  
    <Button  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="end"  
        android:id="@+id/end"  
        android:layout_below="@+id/start"  
        android:layout_alignParentLeft="true"  
        android:layout_alignParentStart="true" />  
  
</RelativeLayout>  

3.4 CustomViewActivity4.java

[java] view plain copy
import android.app.Activity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import com.example.administrator.customview.R;  
  
public class CustomViewActivity4 extends Activity implements View.OnClickListener {  
  
    private OnKeyClearCircleView onKeyClearCircleView;  
    private Button start;  
    private Button end;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_custom_view_activity4);  
        init();  
    }  
  
    private void init() {  
        onKeyClearCircleView = (OnKeyClearCircleView) findViewById(R.id.onKeyClearCircleView);  
        start = (Button) findViewById(R.id.start);  
        start.setOnClickListener(this);  
        end = (Button) findViewById(R.id.end);  
        end.setOnClickListener(this);  
    }  
  
    @Override  
    public void onClick(View view) {  
        if(view == start){  
            onKeyClearCircleView.startClear();  
        }else if(view == end){  
            onKeyClearCircleView.stopClear();  
        }  
    }  
}  

更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680

原文链接https://blog.csdn.net/hfreeman2008/article/details/43051425#

posted @ 2019-11-28 19:23  AndroidAlvin  阅读(241)  评论(0编辑  收藏  举报