CircleTextView的实现
来源:互联网 发布:python的位运算作用 编辑:程序博客网 时间:2024/06/06 03:36
“CircleTextView”顾名思义就是带圆边框的TextView,先来看效果图:
之前的项目中如果有带圆边框的需求,基本是都是在drawable中创建一个shape,然后将它设置为TextView的background,但是这样有个弊端,就是每次只要边框的颜色、边框的宽度或者填充颜色不同,就要创建一个新的shape文件,这样做显然不是一个有长久之计,想到CircleImageView的效果受到大家的认可,就产生了自己写一个CircleTextView的想法。
废话少说,开始分析。从需求上来说,至少要支持以下几点:
- 支持圆形的背景
- 支持外加边框的宽度和颜色自定义
- 支持填充颜色自定义
Ok,需求分析完毕,开始动工。
声明自定义属性
要想满足以上几点需求,原生Android肯定是不支持了,因此,我们首先要为支持上面的需求,自定义属性。这个很简单,只需要在values/attr中创建自定义属性即可。
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="border_width" format="dimension" /> <!-- 边框的宽度 --> <attr name="border_color" format="color" /> <!-- 边框的颜色 --> <attr name="fill_color" format="color" /> <!-- 填充颜色 --> <declare-styleable name="CircleTextView"> <attr name="border_width" /> <attr name="border_color" /> <attr name="fill_color" /> </declare-styleable></resources>
创建CircleTextView
创建一个类,我们就命名为“CircleTextView”,并且让它继承TextView,并实现它的构造方法。
public class CircleTextView extends TextView { public CircleTextView(Context context) { this(context, null); } public CircleTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
可以看到这里实现了3个构造方法,第一个构造方法调用第二个构造方法,第二个构造方法调用第三个构造方法,而第三个构造方法调用父类的构造方法。也就是说,无论我们调用哪个构造方法,最后都会调用第三个构造方法。所以我们把自定义属性的解析,放在第三个构造方法中。解析属性之前,首先声明变量。
private int borderWidth; private int borderColor; private int fillColor;
接下来解析自定义属性的值。
public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleTextView); borderWidth = typedArray.getDimensionPixelSize(R.styleable.CircleTextView_border_width, 0); borderColor = typedArray.getColor(R.styleable.CircleTextView_border_color, Color.WHITE); fillColor = typedArray.getColor(R.styleable.CircleTextView_fill_color, Color.WHITE); typedArray.recycle(); setGravity(Gravity.CENTER); setPadding(Utils.dip2px(context,10), Utils.dip2px(context,10), Utils.dip2px(context,10), Utils.dip2px(context,10)); }
代码中原理都很简单,就是取出用户自定义属性的值,如果没有定义该属性,并赋予默认值。另外,为了美观,默认将gravity属性设置为居中,最后一行setPadding是为了避免边框与文字内容重叠所以设置padding默认为10dp,用到了dp转px的方法,可以移步https://github.com/CodeXiaoMai/MyProject/中查看具体实现。
测量重写onMeasure方法
属性的值我们都得到了,接下来就该根据得到的值去给TextView加上圆形的背景和边框。那么这个圆形该画多大呢,如果需要用户手动设置圆形的大小,那么圆太大太小都不合适,显然这种方法太low了。可是,一般我们设置textview的宽度与高度时,基本上都是wrap_content就行了,但是如果这里还用wrap_content的话,那么宽和高是不一定相等的,应该说是极大可能是不相等的。
我们的TextView中的文字内容可能是这样的:
第一种宽明显比高的值要大,第二种高明显比宽的值要大,第三种,恩~,看着好像差不多了,不过你仔细一看,还是宽高不一样的。这时候,你可能迷茫了,尼玛,我到底要画多大的圆才行。。。哈哈,接下来,就来通过重写onMeasuer方法,让它的文字内容无论是怎样排列,都会宽高相同。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int measuredWidth = getMeasuredWidth(); int measuredHeight = getMeasuredHeight(); int max = Math.max(measuredWidth, measuredHeight); setMeasuredDimension(max, max); }
其实原理还是很简单的,就是获取TextView的宽和高,然后取出最大值,重新设置TextView的宽和高都为这个最大值,这样就实现了宽和高一致了。
画圆
终于到了最后一步,也是效果出现的时候了。
@Override protected void onDraw(Canvas canvas) { int width = getWidth(); int height = getWidth(); // 半径 radius = Math.min(width, height) / 2; if (borderWidth > 0) { //创建绘制边框的画笔 Paint borderPaint = new Paint(); //设置画笔的颜色 borderPaint.setColor(borderColor); //在画布上用绘制边框的笔,画出边框 canvas.drawCircle(getWidth() / 2, getWidth() / 2, radius, borderPaint); } //创建绘制背景圆的画笔 Paint fillPaint = new Paint(); fillPaint.setColor(fillColor); //在画布上画出背景圆,圆的大小为TextView的宽度减去边框的宽度 canvas.drawCircle(getWidth() / 2, getWidth() / 2, radius - borderWidth, fillPaint); super.onDraw(canvas); }
Ok,到这里CircleTextView就已经全部实现了。最后,为了方便代码的阅读,贴出完整的代码:
package com.xiaomai.myproject.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.Gravity;import android.widget.TextView;import com.xiaomai.myproject.R;import com.xiaomai.myproject.utils.Utils;/** * Created by XiaoMai */public class CircleTextView extends TextView { private int radius; private int borderWidth; private int borderColor; private int fillColor; public CircleTextView(Context context) { this(context, null); } public CircleTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleTextView); borderWidth = typedArray.getDimensionPixelSize(R.styleable.CircleTextView_border_width, 0); borderColor = typedArray.getColor(R.styleable.CircleTextView_border_color, Color.WHITE); fillColor = typedArray.getColor(R.styleable.CircleTextView_fill_color, Color.WHITE); typedArray.recycle(); setGravity(Gravity.CENTER); setPadding(Utils.dip2px(context, 10), Utils.dip2px(context, 10), Utils.dip2px(context, 10), Utils.dip2px(context, 10)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int measuredWidth = getMeasuredWidth(); int measuredHeight = getMeasuredHeight(); int max = Math.max(measuredWidth, measuredHeight); setMeasuredDimension(max, max); } @Override protected void onDraw(Canvas canvas) { int width = getWidth(); int height = getWidth(); // 半径 radius = Math.min(width, height) / 2; if (borderWidth > 0) { Paint borderPaint = new Paint(); borderPaint.setColor(borderColor); canvas.drawCircle(getWidth() / 2, getWidth() / 2, radius, borderPaint); } Paint fillPaint = new Paint(); fillPaint.setColor(fillColor); canvas.drawCircle(getWidth() / 2, getWidth() / 2, radius - borderWidth, fillPaint); super.onDraw(canvas); }}
- CircleTextView的实现
- 三子棋的实现的实现的实现
- JAVA实现的时钟实现
- 模态框的的实现
- 杀毒软件的简单实现的简单实现
- android的实现电话号码的实现
- 音频的实现音乐声音的实现
- malloc的实现、内存池的实现
- 异形窗体的实现
- 个性化的分页实现
- ASP数据库连接的实现
- Struts单选框的实现
- 梅西迭代算法的实现
- 翻页功能的实现
- Struts,MVC 的实现
- 实现JavaScript的继承
- 接口的显示实现
- TTerm的实现( 一)
- iOS端执行包含外部引用的js并相互通信
- 由于SSH配置文件的不匹配,导致的Permission denied (publickey)及其解决方法及基础ssh知识理解
- 策略模式(Strategy)
- XAPI Host Plugins
- nginx解决跨域问题
- CircleTextView的实现
- 使用java 操作MongoDB 的增删操作
- 数据库Schema的优化
- 关于linux环境变量的设置
- javascript请求天气API大全
- 【Java集合系列】---ArrayList
- JavaScript location对象用法详解
- iperf局域网测速
- hibernate中cascade和inverse