前言

View,有很多的名称。不论是你熟知的布局,还是控件,他们全部都继承自View。

思维导图

工作流程

measure

其实通过layout中的第二张图我们已经知道了控件大小的计算了。

height = bottom - top

width = right - left

对于ViewGroup而言,就是对容器内子控件的遍历和计算了。

因为直接继承自View的控件使用wrap_cotent和match_parent是显示出来的效果是相同的。需要我们使用MeasureSpec中的getMode()方法来对当前的模式进行区分和比较。

模式

状态

UNSPECIFIED

未指定模式,View想多大就多大,父容器不做限制,一般用于系统内部的测量

AT_MOST

最大模式,对应wrap_content,View的大小不大于SpecSize的值

EXACTLY

精确模式,对应match_parent,View的大小为SpecSize的值

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//用于获取设定的模式

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

// 用于获取设定的长度

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

// 类似这样的判断,后面不过多复述

// 用于判断是不是wrap_content

// 如果不进行处理,效果会是match_parent

if(widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){

setMeasuredDimension(20, 20);

}

}

复制代码

layout

在确定位置时,我们有一个非常需要主要的地方—— 坐标系。Android系统的坐标系和平时画的坐标系并不相同。

所以相对应的,我们的位置计算方法自然和我们原来的正好是相反的。

4个顶点的位置分别由4个值决定:

top:子View上边界到所在容器上边界的距离。

left:子View左边界到所在容器左边界的距离。

bottom:子View下边界到所在容器上边界的距离。

right:子View右边界到所在容器左边界的距离。

所有的计算都是相对于所在容器才能够开始的。

draw

一共有6个步骤:

如果需要,则绘制背景 -- drawBackground(canvas);

保存当前canvas层 -- saveCount = canvas.getSaveCount();

绘制View的内容 -- if (!dirtyOpaque) onDraw(canvas);

绘制子View -- dispatchDraw(canvas);

如果需要,则绘制View的褪色边缘,类似于阴影效果 -- canvas.restoreToCount(saveCount);

绘制装饰,比如滚动条 -- onDrawForeground(canvas);

关于开发者需要重写的方法一般是第三步绘制View的内容对应的onDraw()。

private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

@Override

protected void onDraw(Canvas canvas){

super.onDraw(canvas);

int width = getWidth();

int height = getHeight();

// 在画布上进行类似这样的操作

canvas.drawLine(0, height/2, width,height/2, paint);

}

复制代码

入门自定义View

在日常项目的布局文件中我们经常会使用到xmlns:app="http://schemas.android.com/apk/res-auto"这样标签,其实他就是用来引入我们自定义的标签使用的。

在res/values目录下创建attrs

复制代码在DefaultView(Context context, @Nullable AttributeSet attrs)中获取。以下是整个完整代码。

/**

* author: ClericYi

* time: 2020-01-30

*/

public class DefaultView extends View{

private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

private int mColor = Color.RED;

public DefaultView(Context context, @Nullable AttributeSet attrs){

super(context, attrs);

initAttrs(context, attrs);

initDraw();

}

private void initAttrs(Context context, @Nullable AttributeSet attrs){

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DefaultView);

// 从styleable中获取的名字是系统会生成的,一般是 类名_name 的形式

mColor = array.getColor(R.styleable.DefaultView_color, Color.GREEN);

// 获取完资源后即使回收

array.recycle();

}

private void initDraw(){

paint.setColor(mColor);

paint.setStrokeWidth(3f);

}

@Override

protected void onDraw(Canvas canvas){

super.onDraw(canvas);

int width = getWidth();

int height = getHeight();

canvas.drawLine(0, height/2, width,height/2, paint);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

if(widthMode == MeasureSpec.AT_MOST){

setMeasuredDimension(20, 20);

}

}

}

复制代码

基础的性能优化

首先的话我们先了解如何去知道一个View是否被过度绘制了?

其实在我们手机中的开发模式已经存在这个选项了。

开启前

开启后

下方给出绘制的次数对应图

那如何做到性能优化呢?

在这个问题之前,需要了解什么是过度绘制,你可以理解为同一位置的控件不断的叠加而产生的无用数据,那我们就来说说集中解决方案吧。

方案1: 减少嵌套层数。

使用线性布局

使用约束布局

因为只是一个案例,想说的意思,如果多个LinearLayout嵌套实现的效果,如果能被一个ConstraintLayout直接实现,那么就用后者替代,因为不会这样在同一个区域重复出现

方案2: 去除默认的背景

这个解决方案其实针对的背景会被自动绘制的问题,如果我们把这个层次消去,从绘制角度老说也是一种提升了。正如图示一般直接减少了一层的绘制。

在代码中的具体表现,通过对style.xml中的Theme进行修改:

@null

复制代码

总结

以上就是我的学习成果,如果有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。

android自定义view案例,Android自定义View,你摸的透透的了?相关推荐

  1. android自定义view案例,Android自定义View的实现方法实例详解

    一.自绘控件 下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次.新建一个CounterView继承自View,代码如下所示: 可以看到,首先我们在 ...

  2. android+mvp+登录案例,android mvp实现登录

    android的mvp是什么呢? Model:用于数据的增删改查等,也包括一些数据对象 ,主要用来处理一些业务操作. View:用于界面的显示与用户操作的接收,在Android里面View通常就是Ac ...

  3. android记事本项目案例,Android实现记事本项目完整实例源代码

    [实例简介] 记事本项目源码,我的博客有详细描述. 一个记事本,能够输入标题和内容,创建日期.最新修改日期等信息. 如果没有输入标题则使用内容的第一句话作为标题,创建日期和修改日期均由系统自动生成,无 ...

  4. android小球移动代码,Android自定义圆形View实现小球跟随手指移动效果

    本文实例为大家分享了Android实现小球跟随手指移动效果的具体代码,供大家参考,具体内容如下 一. 需求功能 手指在屏幕上滑动,红色的小球始终跟随手指移动. 实现的思路: 1)自定义View,在on ...

  5. android 画布实现签名,Android 自定义View手写签名并保存图片

    1.自定义View--支撑设置画笔色彩,画笔宽度,画板色彩,铲除画板,查看是否有签名,保存画板图片(仿制粘贴可直接使用) /***CreatedbyYyyyQon2020/3/5. *电子签名*/pu ...

  6. android canvas绘制圆角_Android自定义View撸一个渐变的温度指示器(TmepView)

    秦子帅明确目标,每天进步一点点..... 作者 |  andy 地址 |  blog.csdn.net/Andy_l1/article/details/82910061 1.概述 自定义View对需要 ...

  7. android绘制心形_Android自定义View系列(一)——打造一个爱心进度条

    写作原因:Android进阶过程中有一个绕不开的话题--自定义View.这一块是安卓程序员更好地实现功能自主化必须迈出的一步.下面这个系列博主将通过实现几个例子来认识安卓自定义View的方法.从自定义 ...

  8. 我的Android进阶之旅------Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词的功能...

    前言 一LRC歌词文件简介 1什么是LRC歌词文件 2LRC歌词文件的格式 LRC歌词文件的标签类型 1标识标签 2时间标签 二解析LRC歌词 1读取出歌词文件 2解析得到的歌词内容 1表示每行歌词内 ...

  9. Android中实现Bitmap在自定义View中的放大与拖动

    一基本实现思路: 基于View类实现自定义View –MyImageView类.在使用View的Activity类中完成OnTouchListener接口,实现对MotionEvent事件的监听与处理 ...

  10. Android之在Layout中自定义View

    在Layout中自定义View 经常会看到在XML文件中调用别人的View就可以显示出各种奇妙的页面 简单的学习了一下,下面说一下如何自定义一个View, 并设置背景色 // 第一步,创建一个继承自V ...

最新文章

  1. Python Beautiful Soup类的基本元素
  2. 皮一皮:下班的渴望...
  3. 浅谈企业MES与ERP系统集成
  4. Windows Intellij环境下Gradle的 “Could not determine Java version from ‘9.0.1’”的解决方式...
  5. 调试 ASP 程序脚本
  6. MFC开发IM-第七篇、mfc设置默认编辑框内容
  7. asp.net gridview 模板列 弹出窗口编辑_Mac桌面多窗口整理工具Moom,使用教程
  8. Linux(CentOS7.1)修改默认yum源为国内的阿里云yum源
  9. cocos2d-x 输入框CCEditBox的使用
  10. vc red.msi matlab,vc red.msi x64+x32位版下载
  11. 李雅普诺夫指数的计算
  12. 装逼神器,逼真黑客范儿
  13. Win10 Windows Defender 保护历史记录清空方法
  14. VS用SSIS实现SQL Server数据库与Excel表格数据的相互导入
  15. Python游戏之Pygame——太空飞机大战(三)
  16. zoom,登录失败,错误代码(1044)
  17. 弹性均质圆环法计算过程_同济大学地下建筑结构复习要点
  18. [声纹识别]“说话人识别”基本概念
  19. [C++11]_[初级]_[十六进制字符串转换为字节数组]
  20. Windows 2008 Server搭建Radius服务器的方法

热门文章

  1. filebeat配置文件
  2. 基于mysql的可视化日志管理——loganalyzer
  3. 转:基于Jmeter的MQTT测试插件
  4. 同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式
  5. EMOS批量创建用户邮箱
  6. Failed to push selection: Read-only file system
  7. 各种不同服务器301重定向设置代码大全
  8. 关于Symantec企业级防病毒软件的版本历史
  9. java多线程同步与测试_Java多线程同步Synchronized深入解析
  10. 安装SqlServer2014出现(‘无法启动 Windows Management Instrumentation 服务。若要继续安装,必须找到问题并修复该服务‘)