高级UI晋升之自定义View实战(九)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680
1.前言:
本文采用自定义view的方法来实现一键清除的动画这个功能。
2.效果图:
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#
高级UI晋升之自定义View实战(九)的更多相关文章
- 高级UI晋升之自定义View实战(六)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从Android 自定义属性动画&Camera动画来介绍自定义V ...
- 高级UI晋升之自定义View实战(五)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从自定义View利器Canvas和Paint来进行详解 一.Canvas ...
- 高级UI晋升之自定义view实战(七)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章自定义ViewGroup实现瀑布流效果来进行详解dispatchTouch ...
- 高级UI晋升之自定义View实战(八)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章自定义流式布局来进行介绍: 一般常见的流式布局由两种,一种是横向的个数固定 ...
- 高级UI晋升之常用View(三)中篇
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从ViewPager来介绍常用View:文章目录 一.简介 二.基本使用 ...
- 高级UI晋升之常用View(三)上篇
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将先从以下两个内容来介绍常用View: [RecycleView] [Ca ...
- 高级UI晋升之常用View(三)下篇
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从WebView来介绍常用View: 一.WebView介绍 Andro ...
- 高级UI晋升之View渲染机制(二)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android ...
- Android自定义View实战(SlideTab-可滑动的选择器)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/52178553 本文出自:[openXu的博客] 目录: 初步分析重写onDraw绘制 重写o ...
随机推荐
- Java空对象模式
在“空对象”模式中,空对象将替换NULL对象实例的检查.而不是检查一个空值,Null对象反映一个无关的关系(即什么也不做). 这种Null对象还可以用于在数据不可用时提供默认行为. 在空对象模式(Nu ...
- ctDNA的分析理论上也可以为多样性的肿瘤
导语 肺腺癌(LUAD)和肺鳞癌(LUSC)是最常见的非小细胞肺癌类型.循环肿瘤DNA(ctDNA)是由凋亡或坏死的肿瘤细胞释放并在血液中循环的小片段DNA.与常规肿瘤活检相比,ctDNA检测具有一定 ...
- 热修复设计之AOT/JIT&dexopt 与 dex2oat (一)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680本篇文章将先从AOT/JIT&dexopt 与 dex2o ...
- SVD和SVD++
参考自:http://blog.csdn.net/wjmishuai/article/details/71191945 http://www.cnblogs.com/Xnice/p/4522671.h ...
- asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。
原文:asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密. GitHub demo https://github.com/zhanglilong23/Asp.NetCore. ...
- Node中的Cookie和Session
1.Cookie HTTP是无状态协议.例:打开一个域名的首页,进而打开该域名的其他页面,服务器无法识别访问者.即同一浏览器访问同一网站,每次访问都没有任何关系. Cookie的原理是:客户端浏览器在 ...
- myBatis配置提示xml和内部DTD
–配置环境:macOS high Sierra 10.13.6/window10–生产环境:eclipse2018.a,myeclipse2018 首先了解xml文件的参数——<!DOCT ...
- 【知识强化】第四章 网络层 4.4 IPv4
这节课我们来学习一个非常重要的概念,就是IPv4地址,其实也是我们常用的IP地址. 首先我们来了解一下,为什么会有IP地址的出现以及它是做什么用的.假如说在很多年前我遇到一个女生非常的漂亮,等了十年之 ...
- 2018-10-8-如何安装-btsync
title author date CreateTime categories 如何安装 btsync lindexi 2018-10-8 9:15:6 +0800 2018-2-13 17:23:3 ...
- for循环(C语言型)流程