`

对TextView的小探索

阅读更多

1、前言:

看了书上对于自定义组件的讲解,在看的测量view宽度和高度的时候,有点不理解,我们在写安卓的时候使用UI的时候习惯使用XML布局来定义控件,其实对view不太了解。总结一下刚才学习的吧,可能会有错误,首先是面向对象的思想,xml中的每个控件,肯定会转成视图对象,再看每个控件都定义了属性,所以在实例化的时候这个属性值都会被传入view对象当中。一个view要想被画在屏幕上,肯定最先需要知道要画多大,这个事情非常中要吧,其实就TextView而言,如果其中有字体也是可以计算出字体需要多宽和多高的。所以系统得到这些值是很容易的。借别人一个图片来看看吧:

2、先来看view的三个构造方法。

android开发者网站上有相关的说明文档:
public View (Context context)是在java代码创建视图的时候被调用,如果是从xml填充的视图,就不会调用这个
public View (Context context, AttributeSet attrs)这个是在xml创建但是没有指定style的时候被调用
public View (Context context, AttributeSet attrs, int defStyle)这个不用说也懂了吧

 

3、我们先来看个子简单的自定TextView吧,当然是从TextView继承的:

package com.lmj.zidingyizujian;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;

 public class XiugaiTextView extends TextView {
	//在ondraw方法中需要使用的画刷
	private Paint marginPaint;
	private Paint linePaint;
	private int pageColor;
	private float margin;
	
	
		
//覆写父类的构造方法,在view显示的时候,会调用这个方法,里面有上下文,和属性集合
	public XiugaiTextView(Context context, AttributeSet attrs, int defStyle) {
		//调用父类的构造方法,这样我们在标准中的使用的父类(TextView)的属性就可以生效了
		super(context, attrs, defStyle);
		//再调用我们自己方法,来修改一下界面
		init();
	}

	public XiugaiTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		//再调用我们自己方法,来修改一下界面
				init();
		
	}

	public XiugaiTextView(Context context) {
		super(context);
		
	}
	
	//对界面进行自己的修改
	public void init(){
		//获得系统资源的引用
		Resources res =    this.getResources();
		//对画刷进行赋值
		marginPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		marginPaint.setColor(res.getColor(R.color.xiugai_margin));
		linePaint  = new Paint(Paint.ANTI_ALIAS_FLAG);
		linePaint.setColor(res.getColor(R.color.xiugai_lines));
		
		//获得页面背景颜色和边缘宽度
		pageColor = res.getColor(R.color.xiugai_pager);
		margin = res.getDimension(R.dimen.xiugai_margin);
			
	}
	//覆写ondraw方法
	@Override
	protected void onDraw(Canvas canvas) {
		//就向ps中的图层
		
		//canvas的一些属性,其实在构造方法中已经进行了赋值,这里我们绘制背景,宽度会充满
		// 父容器,所以可以看出这个canvas画布的大小已经确定了。
		//绘制整个textview页面的颜色
		canvas.drawColor(pageColor);
		
		//绘制边缘
		canvas.drawLine(0,0,0, getMeasuredHeight(), linePaint);
		canvas.drawLine(0,  getMeasuredHeight(),getMeasuredWidth(), getMeasuredHeight(), linePaint);
		
		//绘制间隔线
		canvas.drawLine(margin,0, margin,getMeasuredHeight(), marginPaint);
		
		//移动文本,让textview上面的文本跨过分隔先
		
		canvas.translate(margin, 0);
		
		//使用textview渲染文本,父类的方法再次绘制,这个时候会绘制出textview上的的文本
		//界面上的最后一层
		//父类textview,只设置了文本,所以只会绘制出文本,其他上面都没有了。
		super.onDraw(canvas);
		 canvas.restore();
	}
	

}

 

 <com.lmj.zidingyizujian.XiugaiTextView
        android:id="@+id/xiugaiTextView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:textSize="20sp" />

 

颜色代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="xiugai_pager">#EEF8E0A0</color>
    <color name="xiugai_lines">#FF0000FF</color>
    <color name="xiugai_margin">#90FF0000</color>
    <color name="xiugai_text">#AA0000FF</color>
</resources>

 4、看完上面的代码,已经有点了解自定组件了。但是并不是就是重写ondraw那么简单

如果是自己直接继承view的话,就需要自己去规定大小了,于是探索了一下TextView的大小测定规律吧

 

当需要绘制view的整个大小的时候,或者需要多大空间的时候
父容器会询问子view需要多大,

做个试验,
在textview中,不设置内容,
设置高度大小为包裹内容,宽度设置也为包裹内容,背景为红色
这个时候其实没有内容,那么包裹内容,宽和高都是,理论上就是0,

试验结果:
这个时候确实没有任何内容

接着试验:
把宽度改为充满父容器,高度任然是包裹内容,背景为红色,
这个时候由于高度任然是0,对吧,因为没有内容,所以也不该显示

试验结果:有一条红色的线,
推理,试验一的时候,其实是有一个默认高度,默认高度不为0,但是模式宽度为0,
所以那个时候没有体现出高度,
简单说吧,如果第一次,两个值都是0,那么下一次,改变成一个0 和一个 1,
那么还是在界面上无法话出来的对吧,所以唯一的解释就是高度在包裹内容的时候
如果没有内容,那么在测量高度的时候会返回一个不为0的默认值,而宽度如果是0,那么测量的时

候返回的值也是0。

后话:我们在自定义的时候可以重写测量的方法,根据情况返回我们自己的测量大小
所以我猜测TextView 的高度的为0 的时候,返回的默认值不是0,或者至少当他的宽度
不为0的时候他的高度不为0.

 

  • 大小: 16.5 KB
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics