Android自定义View-练习一

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1、实现一个简单的类似于TextView的自定义View

1.1  自定义属性

        在attrs.xml文件中添加了如下的内容

    
        
        
        
    

1.2   在布局xml文件中的使用

        引入了如下包名:

xmlns:zhy="http://schemas.android.com/apk/res-auto"

        具体的代码如下:

    

1.3   自定义一个类extends view类

        自定义一个类,继承android.view.View类,重写其中的构造函数,在构造函数中,获得自定义参数的属性。并重写onDraw方法,绘制对应的文字以及背景色。具体的代码如下所示:

package com.self.view.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.self.view.R;
import com.self.view.common.GraphicsUtil;
import com.self.view.common.L;

/**
 * Graphics中简单Api的练习
 * 模仿TextView
 * Created by Administrator on 2017/6/7 0007.
 */

public class SimpleApiTextView extends View {
    private String titleText;
    private int titleColor;
    private int titleTextSize;
    private Paint paint;
    private float textHeight = 0;
    public SimpleApiTextView(Context context) {
        this(context,null);
        L.i("一个参数的构造函数");
    }

    public SimpleApiTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
        L.i("俩个参数的构造函数");

    }

    public SimpleApiTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        L.i("三个参数的构造函数");
        init(context, attrs,defStyleAttr);
    }

    private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        //获取自定义属性的值
        if(null != attrs){
            int count = attrs.getAttributeCount();
            for(int i =0;i 
   


2、给自定义View添加click事件

2.1  在构造函数中添加对应的click处理事件

        最终构造函数中调用的init方法,变成如下所示的代码:

    private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        //获取自定义属性的值
        if(null != attrs){
            int count = attrs.getAttributeCount();
            for(int i =0;i

     
3、关于自定义View长宽的自定义

       原来的代码,如果你在布局文件中,将对应的长宽设置成wrap_content的时候,会发现没有达到自己想要的结果。主要是因为没有重写onMeasure方法进行重新测量长宽。

3.1  关于MeasureSpec类的理解

        MeasureSpec主要用于自定义view的测量。MeasureSpec是一个32位的int值,其中高2位是测量的模式,低30位为测量的大小。其中测量的模式可以分为:EXACTLY、AT_MOST、UNSPECIFIED.这三种模式的说明如下:

EXACTLY:默认值,对应的长宽的设置:具体值或者是match_parent

AT_MOST:对应的长宽的设置:wrap_content

UNSPECIFIED:这个属性比较奇怪,它不指定其大小测量模式,View想多大就多大,通常情况下在绘制自定义View时才会使用。

        所以,在自定义View的时候,如果没有重写onMeasure方法的话,默认的长宽模式就是EXACTLY.如果需要实现wrap_content的效果,就需要重写onMeasure方法。

3.2  关于onMeasure

        该方法的定义如下:

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

        查看该方法的源码,最终会调用setMeasuredDimension(int measuredWidth,int measuredHeight)方法,将测量后的宽高值设置进去。所以在重写onMeasure方法以后,必须调用此方法,将最终的结果设置进去。

        文中例子中的onMeasure方法,如下所示:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        float viewWidth,viewHeight;//自定义View的宽、高
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if(widthMode == MeasureSpec.EXACTLY){
            viewWidth = MeasureSpec.getSize(widthMeasureSpec);
        }else{
            viewWidth = paint.measureText(titleText)+getPaddingLeft()+getPaddingRight();
        }
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if(heightMode == MeasureSpec.EXACTLY){
            viewHeight = MeasureSpec.getSize(heightMeasureSpec);
        }else{
            viewHeight = textHeight+getPaddingBottom()+getPaddingTop();
        }
        setMeasuredDimension((int)viewWidth,(int)viewHeight);
    }

        文章写的并不是特别的好,可以查看下面的参考地址以及参考书籍

        参考地址:http://blog.csdn.net/lmj623565791/article/details/24252901

         参考书籍:《Android群英传》第三章第3.2节

转载于:https://my.oschina.net/u/2253892/blog/919949

你可能感兴趣的:(Android自定义View-练习一)