2019独角兽企业重金招聘Python工程师标准>>>
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节