1.继承自view

系统提供的view 如 TextView 、ImageView 都是继承自view的;

2.自定义一个TextView

通过自定义一个TextView 来熟悉继承自view 的自定义view的api用法

3.onMeasure

用来处理控件的大小

 	@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
}
//获取宽高的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec); //mode
//MeasureSpec.AT_MOST 指定了wrap_content
//MeasureSpec.EXACTLY 指定了确切的值 match_parent fill_parent
//MeasureSpec.UNSPECIFIED 尽可能的大

4.onDraw

用于绘制

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

5.onTouchEvent

用于处理用户触摸事件

    @Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
} return super.onTouchEvent(event);
}

6.自定义属性

用来配置自定义控件的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义控件的名称 name="TextView"-->
<declare-styleable name="TextView">
<attr name="text" format="string" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
<attr name="maxLength" format="integer" />
<attr name="background" format="reference|color" /> <!--枚举-->
<attr name="inputType" format="enum">
<enum name="number" value="1" />
<enum name="text" value="2" />
<enum name="password" value="3" />
</attr>
</declare-styleable>
</resources>

在布局中使用

<com.nb.customview.TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:text="张三"
app:textColor="@color/purple_500"
app:textSize="16" />

在自定义控件中获取

    public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TextView);
mText = typedArray.getString(R.styleable.TextView_text);
mTextSize = typedArray.getDimensionPixelSize(R.styleable.TextView_textSize, mTextSize);
mTextColor = typedArray.getColor(R.styleable.TextView_textColor, mTextColor);
typedArray.recycle();
}

7.完整的代码

package com.nb.customview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout; import androidx.annotation.Nullable; /**
* Created by DongKing on 2020/11/5
* Version 1.0
* Describe:自定义TextView
*/
class TextView extends View { private static final String TAG = "TextView"; private String mText;
private int mTextSize = 15;
private int mTextColor = Color.BLACK; private Paint mPaint; // 在java 代码中new 的时候使用
public TextView(Context context) {
this(context, null);
} // 在layout 中使用
public TextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
} //有style时使用
public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取xml中设置的属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TextView);
mText = typedArray.getString(R.styleable.TextView_nbText);
mTextSize = typedArray.getDimensionPixelSize(R.styleable.TextView_nbTextSize, sp2px(mTextSize));
mTextColor = typedArray.getColor(R.styleable.TextView_nbTextColor, mTextColor);
typedArray.recycle(); //初始化画笔
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(mTextSize);
mPaint.setColor(mTextColor); } private int sp2px(int sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
getResources().getDisplayMetrics());
} /**
* 指定宽高
* 针对不同的情况
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec); //1.如果指定大小
int width = MeasureSpec.getSize(widthMeasureSpec);
//2.wrap_content 计算获取值
if (widthMode == MeasureSpec.AT_MOST) {
Rect bounds = new Rect();
mPaint.getTextBounds(mText, 0, mText.length(), bounds);
width = bounds.width() + getPaddingLeft() + getPaddingRight();
} int height = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
Rect bounds = new Rect();
mPaint.getTextBounds(mText, 0, mText.length(), bounds);
height = bounds.height() + getPaddingTop() + getPaddingBottom();
}
//设置控件的宽高
setMeasuredDimension(width, height); } /**
* 用于绘制
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
int baseLine = getHeight() / 2 + dy; canvas.drawText(mText, getPaddingLeft(), baseLine, mPaint);
} }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <com.nb.customview.TextView
android:padding="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/purple_200"
app:nbText="张三"
app:nbTextColor="@color/teal_200"
app:nbTextSize="20sp" /> </LinearLayout> </LinearLayout>

最新文章

  1. 使用DB4o做一个.Net版的website(一)环境
  2. DWZ (JUI) 教程 tree 控件的选中事件
  3. C#源码大汇总
  4. MVC小系列(十四)【MVC+ZTree大数据异步树加载】
  5. win32程序中简单应用mfc
  6. 设置outlook自动回复
  7. Fortran与C混合编程(转自Ubuntu)
  8. 数据结构学习:KMP模式匹配算法
  9. VS2013 添加控制台程序
  10. 【ML入门系列】(二)分类与回归
  11. Android Jetpack 概述
  12. Shell高级编程学习笔记(基础篇)
  13. JS获取系统时间--JavaScript基础
  14. php 有意思的小题
  15. hdu 5064 满足b2−b1≤b3−b2... 的最长子序列
  16. ArcGIS放射状流向地图
  17. Android利用广播监听设备网络连接(断网)的变化情况
  18. LNMP环境下独立安装Mysql5.7.18 并对数据库文件进行本地物理迁移 (需暂停数据库服务方式)
  19. 679. 24 Game
  20. HDU4280:Island Transport(最大流)

热门文章

  1. Verilog之阻塞赋值非阻塞赋值
  2. DataTable 将一列转为List
  3. 痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程
  4. PyQt(Python+Qt)学习随笔:QListWidget对项进行排序的sortItems方法
  5. 第11.14节 正则表达式转义符和Python转义符相同引发问题的解决办法
  6. PyQt(Python+Qt)学习随笔:Qt Designer中部件mimimumSize和maximumSize的含义
  7. PyQt(Python+Qt)学习随笔:Designer中ItemViews类部件的frameShadow属性
  8. Hello TLM
  9. PHP代码审计分段讲解(6)
  10. python-列表list和元组tuple