自定义View--概述(一)

自定义View–概述(一)

自定义View是Android开发中的一个有趣而有用的技能,它可以让我们实现一些系统控件无法满足的效果。比如,我们可以自己写一个TextView,来显示一些特殊的文字或图案。 要实现自定义View,我们需要了解几个重要的方法,它们分别是:

  • onMeasure():这个方法用来确定View的大小,它会根据不同的测量模式(UNSPECIFIED,EXACTLY,AT_MOST)来计算出View的宽度和高度。测量模式与父View的布局参数有关,我们后面会详细分析。

  • onDraw():这个方法用来绘制View的内容,它会根据onMeasure()方法得到的大小,在画布上画出我们想要的效果。我们可以使用Canvas类提供的各种方法来绘制文字、图形、图片等。

  • onTouch():这个方法用来处理View的触摸事件,它会根据用户的手指动作,来改变View的状态或执行一些操作。我们可以使用MotionEvent类提供的各种信息来判断用户的触摸行为。

  • 自定义属性:这个方法用来给View添加一些可配置的参数,比如文字颜色、大小、样式等。我们可以在布局文件中使用android:开头的属性来设置这些参数。

1.1. onMeasure()方法

这个方法用来测量View的大小,它会在View的构造方法之后被调用,接收两个int参数作为宽度和高度的测量规格。我们可以通过MeasureSpec类提供的一些静态方法来获取或设置这些参数,比如:

  • MeasureSpec.getMode():获取测量模式,有三种可能的值,分别是UNSPECIFIED(未指定),EXACTLY(精确),AT_MOST(最大)。
  • MeasureSpec.getSize():获取测量大小,单位是像素。
  • MeasureSpec.makeMeasureSpec():根据给定的模式和大小,创建一个测量规格。

测量模式与父View的布局参数有关,比如如果父View的布局参数是match_parent,那么子View的测量模式就是EXACTLY,表示子View的大小要和父View一样;如果父View的布局参数是wrap_content,那么子View的测量模式就是AT_MOST,表示子View的大小不能超过父View;如果父View没有给子View设置任何布局参数,那么子View的测量模式就是UNSPECIFIED,表示子View可以任意大小。

在onMeasure()方法中,我们需要根据不同的测量模式和大小,来计算出View的实际宽度和高度,并通过setMeasuredDimension()方法来设置。我们还可以使用getSuggestedMinimumWidth()和getSuggestedMinimumHeight()方法来获取View的建议最小宽度和高度,以便在UNSPECIFIED模式下使用。

下面是一个简单的例子,演示了如何在onMeasure()方法中根据不同的测量模式和大小来设置View的宽度和高度:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //获取宽度的测量模式和大小
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    //获取高度的测量模式和大小
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    //根据不同的测量模式,计算出实际的宽度和高度
    int width;
    int height;
    if (widthMode == MeasureSpec.EXACTLY) {
        //如果宽度是精确值,直接使用
        width = widthSize;
    } else {
        //如果宽度是未指定或最大值,使用建议最小宽度
        width = getSuggestedMinimumWidth();
        if (widthMode == MeasureSpec.AT_MOST) {
            //如果宽度是最大值,取最小值和测量值中较小的一个
            width = Math.min(width, widthSize);
        }
    }
    if (heightMode == MeasureSpec.EXACTLY) {
        //如果高度是精确值,直接使用
        height = heightSize;
    } else {
        //如果高度是未指定或最大值,使用建议最小高度
        height = getSuggestedMinimumHeight();
        if (heightMode == MeasureSpec.AT_MOST) {
            //如果高度是最大值,取最小值和测量值中较小的一个
            height = Math.min(height, heightSize);
        }
    }
    //设置实际的宽度和高度
    setMeasuredDimension(width, height);
}

1.2. onDraw()方法

这个方法主要用来绘制View的内容,它会在onMeasure()方法之后被调用,接收一个Canvas参数作为画布。我们可以利用Canvas提供的各种方法来绘制我们想要的效果,比如:

canvas.drawCircle():绘制圆形
canvas.drawBitmap():绘制位图
canvas.drawText():绘制文本
由于我们要实现一个自定义TextView,所以我们主要用到的是canvas.drawText()方法,它可以让我们在指定的位置、大小和颜色上绘制文字。我们还可以使用Paint类来设置一些文字的属性,比如字体、粗细、对齐方式等。

下面是一个简单的例子,演示了如何在onDraw()方法中绘制一段文本:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //创建一个Paint对象
    Paint paint = new Paint();
    //设置文字颜色为黑色
    paint.setColor(Color.BLACK);
    //设置文字大小为30像素
    paint.setTextSize(30);
    //设置文字居中对齐
    paint.setTextAlign(Paint.Align.CENTER);
    //获取View的宽度和高度
    int width = getWidth();
    int height = getHeight();
    //绘制一段文本,位置在View的中心
    canvas.drawText("Hello, this is a custom TextView", width / 2, height / 2, paint);
}

1.3. onTouch()方法

这个方法用来处理View的触摸事件,它需要实现View.OnTouchListener接口,并重写onTouch(View v, MotionEvent event)方法,接收两个参数,第一个参数是触摸的View对象,第二个参数是封装了触摸事件的MotionEvent对象。我们可以根据不同的触摸动作,来执行一些操作,比如:

  • MotionEvent.ACTION_DOWN:手指按下屏幕
  • MotionEvent.ACTION_MOVE:手指在屏幕上移动
  • MotionEvent.ACTION_UP:手指离开屏幕
    在onTouch()方法中,我们需要返回一个布尔值,表示是否消费了这个事件。如果返回true,表示事件被消费,不会再传递给其他的回调方法,比如onTouchEvent()或onClick();如果返回false,表示事件未被消费,会继续传递给其他的回调方法。

下面是一个简单的例子,演示了如何在onTouch()方法中根据不同的触摸动作来改变View的背景颜色:

//创建一个TextView对象
TextView textView = new TextView(this);
//设置TextView的文本内容
textView.setText("Hello, this is a custom TextView");
//设置TextView的背景颜色为灰色
textView.setBackgroundColor(Color.GRAY);
//给TextView设置触摸监听器
textView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //根据不同的触摸动作,改变View的背景颜色
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //手指按下时,背景颜色变为红色
                v.setBackgroundColor(Color.RED);
                break;
            case MotionEvent.ACTION_MOVE:
                //手指移动时,背景颜色变为绿色
                v.setBackgroundColor(Color.GREEN);
                break;
            case MotionEvent.ACTION_UP:
                //手指离开时,背景颜色变为蓝色
                v.setBackgroundColor(Color.BLUE);
                break;
        }
        //返回true,表示事件被消费
        return true;
    }
});

这个方法用来给View添加一些可配置的参数,比如文字颜色、大小、样式等。我们可以在布局文件中使用自定义属性来设置这些参数,也可以在代码中动态地获取或修改这些参数。自定义属性的好处是可以让我们的View更灵活、更适应不同的需求和场景。

要使用自定义属性,我们需要做以下几个步骤:

  • 在res/values目录下创建一个attrs.xml文件,用来定义自定义属性的名称、类型、默认值等。 在布局文件中使用xmlns命名空间来引用自定义属性,并在需要的View上设置自定义属性的值。
  • 在自定义View的构造方法中,通过TypedArray对象来获取自定义属性的值,并根据需要进行处理。
  • 在自定义View的onDraw()方法中,根据自定义属性的值来绘制View的内容。

下面是一个简单的例子,演示了如何使用自定义属性来设置一个TextView的文字颜色和大小:

在res/values/attrs.xml文件中,定义两个自定义属性:text_color和text_size,分别表示文字颜色和大小,类型分别是color和dimension,默认值分别是黑色和16sp:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomTextView">
        <attr name="text_color" format="color" />
        <attr name="text_size" format="dimension" />
    </declare-styleable>
</resources>
  • 在布局文件中,使用xmlns:custom命名空间来引用自定义属性,并在CustomTextView上设置text_color为红色,text_size为24sp:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.example.CustomTextView
        android:id="@+id/custom_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:text_color="#FF0000"
        custom:text_size="24sp" />

</LinearLayout>
  • 在CustomTextView类中,继承TextView,并在构造方法中,通过obtainStyledAttributes()方法来获取TypedArray对象,然后通过getColor()和getDimension()方法来获取自定义属性的值,并通过setTextColor()和setTextSize()方法来设置文字颜色和大小:
public class CustomTextView extends TextView {

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //获取TypedArray对象
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
        //获取文字颜色,默认为黑色
        int textColor = typedArray.getColor(R.styleable.CustomTextView_text_color, Color.BLACK);
        //获取文字大小,默认为16sp
        float textSize = typedArray.getDimension(R.styleable.CustomTextView_text_size, 16);
        //释放TypedArray对象
        typedArray.recycle();
        //设置文字颜色
        setTextColor(textColor);
        //设置文字大小
        setTextSize(textSize);
    }
}
  • 在CustomTextView类中,重写onDraw()方法,在画布上绘制一段文本:
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //绘制一段文本
    canvas.drawText("Hello, this is a custom TextView", 0, 0, getPaint());
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值