2.自定义控件-冒泡控件

最近在看一些关于自定义控件,发现了一篇非常好文章推荐读者看看https://blog.csdn.net/wingichoy/article/details/50455412

以下是我的学习历程:

一、自定义控件的种类

通过学习我们了解到了自定义控件一共有5中类型,分别下:

1.组合控件。多种控件组合成一种控件使用。

2.扩展系统控件。例如系统提供的控件TextView,我们可以对它的功能进行扩展。

3.继承View。我平常的Button、TextView等控件都是继承View的,我们可以继承View新建一个控件。

4.继承ViewGroup的子控件(LinearLayout)。常见的ViewGroup子类有LinearLayout等控件。

5.继承ViewGroup。继承ViewGroup可以新建一个新的ViewGroup控件。

而本章要做的是一个冒泡控件,它属于第三种继承View,接下来就是实现的步骤。

二、冒泡控件

绘制一个控件一般分为三步:

1.onMeasure(测量)

2.onLayout(位置)

3.onDraw(绘制)

首先继承View并实现它构造函数如下:

package com.jatpack.custonbubbling.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class BubblingView extends View {
public BubblingView(Context context) {
super(context);
}

public BubblingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public BubblingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public BubblingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}

第一步重写onMeasure函数

MeasureSpec.EXACTLY:表示精确模式,有个精确的数值,其代码如下:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heithSize = MeasureSpec.getSize(heightMeasureSpec);
int heithMode = MeasureSpec.getMode(heightMeasureSpec);
if(widthMode == MeasureSpec.EXACTLY){
width = widthSize;
rectWidth = (int) (width * rate);
}
if(heithMode == MeasureSpec.EXACTLY){
height = heithSize;
rectHeight = (int) (height * rate + 0.1);
}
setMeasuredDimension(width,height);
}

在这里onLayout无需重写,所以下一步是onDraw

@Override
protected void onDraw(Canvas canvas) {
Paint p = new Paint();//初始化画笔
p.setColor(Color.parseColor("#2C97DE"));//设置颜色
p.setStyle(Paint.Style.FILL);//设置类型
//绘制
canvas.drawRoundRect(new RectF(5,5,rectWidth,rectHeight),10,10,p);

Path path = new Path();//设置路径
path.moveTo(rectWidth/2 - 30,rectHeight);//设置开始点
path.lineTo(rectWidth/2,rectHeight+30);//从开始点绘制第一条路径
path.lineTo(rectWidth/2+30,rectHeight);//从上一点开始绘制第二天路径
path.close();

canvas.drawPath(path,p);
p.setColor(Color.WHITE);
p.setTextSize(40);
canvas.drawText("你好!",rectWidth/2-40,rectHeight/2,p);
super.onDraw(canvas);
}


所有代码如下
package com.jatpack.custonbubbling.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class BubblingView extends View {
int width;
int height;
int rectWidth;
int rectHeight;
float rate = 0.8f;
public BubblingView(Context context) {
super(context);
}

public BubblingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public BubblingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public BubblingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heithSize = MeasureSpec.getSize(heightMeasureSpec);
int heithMode = MeasureSpec.getMode(heightMeasureSpec);
if(widthMode == MeasureSpec.EXACTLY){
width = widthSize;
rectWidth = (int) width;
}
if(heithMode == MeasureSpec.EXACTLY){
height = heithSize;
rectHeight = (int) (height * rate + 0.1);
}
setMeasuredDimension(width,height);
}

@Override
protected void onDraw(Canvas canvas) {
Paint p = new Paint();//初始化画笔
p.setColor(Color.parseColor("#2C97DE"));//设置颜色
p.setStyle(Paint.Style.FILL);//设置类型
//绘制
canvas.drawRoundRect(new RectF(5,5,rectWidth,rectHeight),10,10,p);

Path path = new Path();//设置路径
path.moveTo(rectWidth/2 - 30,rectHeight);//设置开始点
path.lineTo(rectWidth/2,rectHeight+30);//从开始点绘制第一条路径
path.lineTo(rectWidth/2+30,rectHeight);//从上一点开始绘制第二天路径
path.close();

canvas.drawPath(path,p);
p.setColor(Color.WHITE);
p.setTextSize(40);
canvas.drawText("你好!",rectWidth/2-40,rectHeight/2,p);
super.onDraw(canvas);
}
}
原文地址:https://www.cnblogs.com/riyueqian/p/14673507.html