android 自定义View(一、基础认识)

本文章参考了部分Android 自定义View (一)并结合我自己的完善和思考后得出


界面部分一直是我比较薄弱的地方,所以为了填补我的这份弱点,在自我学习的过程中,自定义View的熟悉与熟练,就成了我的必经之路,那么这次我就开始一步一步了解自定义View

那么,自定义View需要做哪些事情呢?



一、继承一个View

这种方式很多人都熟悉,继承Layout,继承系统的组件如TextView等,最基础的就是继承一个View,例如

public class MyView extends View{

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
    
}
这样就有了一个最简单的自定义View,当然这个View现在还不能显示,还需要下面的第二步第三步等步骤才能显示,

但是,现在的这个View是只能显示一片白的,什么都没有的

在我们使用的时候,当然会希望有我们自己要显示的内容,这时候就会需要我们知道几个方法


View框架中大量的on函数基本上都应用到了Template模式(模板模式),掌握这一模式对于理解这些框架大有裨益(找时间去了解一下)

注:View在ViewGroup中被分配的位置大小如何,这由onLayout()决定

参数说明:参数changed表示view有新的尺寸或位置;参数left表示相对于父view的Left位置;参数top表示相对于父view的Top位置;参数right表示相对于父view的Right位置;参数bottom表示相对于父view的Bottom位置

@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
	}





注:View本身大小多少,这由onMeasure()决定

widthMeasureSpec, heightMeasureSpec这两个参数,这两个参数由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定。权值weight也是尤其需要考虑的因素,有它的存在情况可能会稍微复杂点

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


注:绘制View,onDraw()定义了如何绘制这个View

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



二、布局中声明View

就像系统提供的组件一样,我们的自定义组件也要这样

在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:myview="http://schemas.android.com/apk/res/com.example.testview"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  
  
    <com.example.customview01.view.CustomTitleView  
        android:layout_width="200dp"  
        android:layout_height="100dp"  
        myview:titleText="3712"  
        myview:titleTextColor="#ff0000"  
        myview:titleTextSize="40sp" />  
  
</RelativeLayout> 

那么,这个配置里面又有哪些需要注意的呢,我来做一张图解

android 自定义View(一、基础认识)_第1张图片

这张图我是从网上直接拷过来做了一下注解

在实际使用中,自定义属性的配置其实用的不算频繁,很多人直接是写在View里面直接写在内部的



三、自定义属性的获取

其实,到了上面两步配置好后,已经可以直接运行显示自定义View了,这一步的话是用于上图中用绿色标注出来的

自定义属性的配置的,写的完善的话,就跟TextView这种组件一样使用了,那么,要类似于这种组件的属性配置的话,需要做哪些事情呢


1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
  
    <attr name="titleText" format="string" />  
    <attr name="titleTextColor" format="color" />  
    <attr name="titleTextSize" format="dimension" />  
  
    <declare-styleable name="CustomTitleView">  
        <attr name="titleText" />  
        <attr name="titleTextColor" />  
        <attr name="titleTextSize" />  
    </declare-styleable>  
  
</resources> 
我定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:

一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;

然后就是在布局文件中的使用了

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:myview="http://schemas.android.com/apk/res/com.example.testview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    
    <com.example.testview.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        
        myview:titleText="我是文字内容"
        myview:titleTextColor="#ff0000"
        myview:titleTextSize="40sp"
        />

</LinearLayout>

这是我自己在家实验的时候写的了


在布局文件写好之后,就是在代码中显示了,我这里就直接贴出我的测试代码了

public class MyView extends View{  
	/** 
     * 文本 
     */  
    private String mTitleText;  
    /** 
     * 文本的颜色 
     */  
    private int mTitleTextColor;  
    /** 
     * 文本的大小 
     */  
    private float mTitleTextSize;  
  
    /** 
     * 绘制时控制文本绘制的范围 
     */  
    private Rect mBound;  
    private Rect mBound2;
    private Paint mPaint;  
    private Paint mPaint2;  
    
    public MyView(Context context) {
		this(context,null);
	}
    
	  
    public MyView(Context context, AttributeSet attrs) {  
        this(context, attrs,0);  
    }  
    
	public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		initMyViewData(context, attrs);
	}
    
    
    
    private void initMyViewData(Context context,AttributeSet attrs){
    	//这里获取到我们在attrs.xml设置的declare-styleable
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyView);
        //然后通过declare-styleable获取到之前定义在里面的几个属性
        mTitleText = array.getString(R.styleable.MyView_titleText);
        mTitleTextColor = array.getColor(R.styleable.MyView_titleTextColor, Color.BLACK);
        mTitleTextSize = array.getDimension(R.styleable.MyView_titleTextSize, 36);
        array.recycle(); //一定要调用,否则这次的设定会对下次的使用造成影响  
        /** 
         * 获得绘制文本的宽和高 
         */  
        mPaint = new Paint();  
        mPaint2 = new Paint();
        mPaint.setTextSize(mTitleTextSize);  
        mPaint2.setTextSize(mTitleTextSize);  
        // mPaint.setColor(mTitleTextColor);  
        mBound = new Rect();  
        mBound2 = new Rect();
        //这句话我自己的理解是在mBound的矩形内,适配mTitleText第一个字符到最后一个字符的范围,这里是我第二和第三个参数填的0和字符串长度所以是第一个字符到最后一个字符的宽度范围
        mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
        Log.i("main", "结果:" + mBound.left + ",右边:" + mBound.right + ",上面:" + mBound.top + ",下面:" + mBound.bottom);
        
        mPaint2.getTextBounds("我是第二行吗", 0, 6, mBound2);
    }
    
    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
    		int bottom) {
    	// TODO Auto-generated method stub
    	super.onLayout(changed, left, top, right, bottom);
    }
    
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    	// TODO Auto-generated method stub
    	super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    
    
    @Override
    protected void onDraw(Canvas canvas) {
    	// TODO Auto-generated method stub
    	super.onDraw(canvas);
    	Log.i("main", "开始画画");
        mPaint.setColor(Color.YELLOW);  
        //在画布的x、y、right、bottom范围内画,画笔为mPaint
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);  
        
        //设置画笔颜色
        mPaint.setColor(mTitleTextColor);  
//        canvas.drawText(text, x, y, paint),第一个参数是我们需要绘制的文本,第三个参数是我们的画笔,
//        这两个不用多说,主要是第二和第三个参数的含义,这两个参数在不同的情况下的值还是不一样的,x默认是这个字符串的左边在屏幕的位置,
//        如果设置了paint.setTextAlign(Paint.Align.CENTER);那就是字符的中心,y是指定这个字符baseline在屏幕上的位置
        canvas.drawText(mTitleText, 0, mBound2.height(), mPaint); 
        
        
        canvas.drawText("我是第二行吗", getWidth() / 2 - mBound2.width() / 2, getHeight() / 2 + mBound2.height() / 2, mPaint2);  
    	
    }
      
} 

在这里面我还是进行了一点实验的,不过都是针对方法的熟悉,并且在注释中已经有所体现,就不一一说明了,下面放出效果图



那么第一篇就到这里,这里主要是对环境方面的配置以及方法的初步功能识别,具体的细化研究就等以后几篇深入研究了




你可能感兴趣的:(android 自定义View(一、基础认识))