Android自定义View入门---自定义一个TextView

自定义一个TextView

本篇作为入门级介绍,以自定义TextView为案例,介绍一下自定义View的流程。自定义View玩的比较溜的小伙伴们可以略过。

  • 简介
  • 自定义View的类型
  • 自定义View的套路
  • 自定义TextView
  • 源码

简介

由系统提供的控件控件,不能满足我们的开发需求,自定义View变得在我们开发中如此常见。但是有很多小伙伴们,对自定义View还是不太了解。作为入门篇就先做个简单介绍。

自定义View的类型

自定义View逃不过下面三种

1、继承自View和ViewGroup(最原始、因为很多事情都需要我们自己处理)
2、继承自系统原有的控件(在系统控件上做适当修改)
3、组合控件(就是把系统原有控件做一个整合,实现一个更炫的效果,其实也算不上自定义控件,入门级)

自定义View的套路

先说概念,再举例子,这也是我们学习中最常见的一种手段,大家在学习的时候,一定要熟读概念,分析例子,总结套路

自定义View

1、 自定义属性,获取自定义属性(达到配置的效果)
2、onMeasure()方法用于测量计算自己的宽高,前提是继承自View,如果是继承自系统已有的 TextView , Button ,已经给你计算好了宽高
3、onDraw() 用于绘制自己的显示
4、 onTouch() 用于与用户交互

自定义ViewGroup

1、 自定义属性,获取自定义属性(达到配置的效果)很少有
2、onMeasure() 方法,for循环测量子View,根据子View的宽高来计算自己的宽高
3、onDraw() 一般不需要,默认情况下是不会调用,如果你要绘制需要实现dispatchDraw()方法
4、onLayout() 用来摆放子View,前提是不是GONE的情况
5、在很多情况下不会继承自ViewGroup ,往往是继承 系统已经提供好的ViewGroup 如 ViewPager ScrollView RelativeLayout

自定义TextView

上面已经介绍了自定义View的套路,那么我们现在就根据套路,自定义一个简单的TextView

1、 自定义属性,获取自定义属性(达到配置的效果)

首写这一步我们需要思考一下,我们TextView需要哪些个属性?TextView首先是用来显示文字的,肯定需要text,text的有有颜色有大小,肯定的需要color、size(这里就简单介绍这三个属性)。那么我们在value文件夹下创建一个attrs的文件,在这个里面自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CostomTextView">

        <attr name="costom_text" format="string"/>
        <attr name="costom_text_color" format="color"/>
        <attr name="costom_text_size" format="dimension"/>

    </declare-styleable>
</resources>

再做一下补充,创建一个类继承自View,要创建View的三个构造方法(实际上是4个最后一个不常用)。
1、public CostomTextView(Context context)
在代码里面new的时候调用
2、CostomTextView(Context context, AttributeSet attrs)
在布局layout中使用(调用)
3、CostomTextView(Context context, AttributeSet attrs, int defStyleAttr)
在布局layout中使用(调用),但是会有style

public class CostomTextView extends View{
    //在代码里面new的时候调用
    public CostomTextView(Context context) {
        this(context,null);
    }
    //在布局layout中使用(调用)
    public CostomTextView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    //在布局layout中使用(调用),但是会有style
    public CostomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CostomTextView);

        costom_text = array.getString(R.styleable.CostomTextView_costom_text);
        costom_text_color = array.getColor(R.styleable.CostomTextView_costom_text_color,
                costom_text_color);
        costom_text_size = array.getDimensionPixelSize(R.styleable
                .CostomTextView_costom_text_size,costom_text_size);
        //属性回收
        array.recycle();

    }
2、 onMeasure()方法用于测量计算自己的宽高,前提是继承自View,如果是继承自系统已有的 TextView , Button ,已经给你计算好了宽高

这个我们是继承自View的,所以这个方法需要我们自己来进行实现。这里说涉及到一个测量模式的问题。这里做一个简单介绍。我这个会另写一篇。

三种测量模式:

1、MeasureSpec.AT_MOST : 在布局中指定了wrap_content
2、MeasureSpec.EXACTLY : 在布居中指定了确切的值 100dp match_parent fill_parent
3、MeasureSpec.UNSPECIFIED : 尽可能的大,很少能用到,ListView , ScrollView 在测量子布局的时候会用UNSPECIFIED

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode =  MeasureSpec.getMode(widthMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);
        if(widthMode == MeasureSpec.AT_MOST){

            Rect bounds = new Rect();
            paint.getTextBounds(costom_text,0,costom_text.length(),bounds);
            width = bounds.width() + getPaddingLeft() +getPaddingRight();
        }

        int heightMode =  MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(widthMeasureSpec);

        if(heightMode == MeasureSpec.AT_MOST){
            Rect bounds = new Rect();
            paint.getTextBounds(costom_text,0,costom_text.length(),bounds);
            height = bounds.height() + getPaddingTop() +getPaddingBottom();
        }

        // 设置控件的宽高
        setMeasuredDimension(width,height);
    }
3、onDraw() 用于绘制自己的显示

涉及知识点:
文字基线的问题(详细做一个讲解)

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int x = getPaddingLeft();

        //dy 代表的是:高度的一半到 baseLine的距离
        Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
        // top 是一个负值  bottom 是一个正值    top,bttom的值代表是  bottom是baseLine到文字底部的距离(正值)
        // 必须要清楚的,可以自己打印就好
        int dy = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
        int baseLine = getHeight()/2 + dy;

        canvas.drawText(costom_text,x,baseLine,paint);
    }
onTouch() 用于与用户交互

简单的入门先不涉及这个问题,如果想要继续了解,详见Android自定义View的事件分发机制系列

源码下载

源码下载

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值