Android 自定义View

Android-无障碍服务(AccessibilityService) 什么是无障碍服务? 无障碍服务(AccessibilityService)是一套可以模拟操作的系统级别的API。用户同意我们的应用获取无障碍服务的权限之后就可以模拟操作,来控制用户的手机。无障碍被广泛用于抢红包、自动回复、一键获取权限等应用中。 无障碍服务的好处很多,可以实现一键操作,帮助残障人士使用手机。当然坏处也有,开启无障碍服务以后,因为服务对手机的实时监控,会引起手机的卡顿。这个怎么优化我们待会会说到。 无障碍服务文档和说明 以下我将结合各大博主的文章、Google官方文档对无障碍服务进行一 阅读详情

声明,翻译自谷歌官方文档:http://developer.android.com/training/custom-views/create-view.html


一、创建View类

一个好的自定义view应该遵循以下规则:

  • 符合android标准
  • 提供自定义的 styleable attributes 以便在XML layouts中试用。
  • 设计辅助功能。(这个是用来支持无障碍阅读的)
  • 兼容android的多平台。
android 的 framework 提供了一系列的 类和 XML 的标签来帮助创建 符合上述规则的view。本课程将讨论怎么使用 Android的framework 创建 view的核心功能。

1.继承View类
Android framework中的所有view都继承自View类,所以 你自定义的view也应该继承自 View类,或者也可以继承自 framework中的其它已经存在的view 类(例如:Button类)。

为了允许  Android Developer Tools 关联到你的 view(在XML 布局中预览你的view),你必须声明一个包含  Context 和AttributeSet 参数的构造方法。 这个构造函数允许 布局编辑器 来创建和编辑 你的view。
class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}
2.声明自定义属性(Attributes)

要在XML布局中添加你的view,并通过XML 来控制view的外观和行为,你必须实现以下功能:
  • 在 res/values/attrs.xml 资源文件中添加 <declare-styleable> 来声明自定属性。
  • 在XML布局中指定 属性的值。
  • 在运行时解析 指定的属性值。
  • 根据解析的数据值来初始化view。
下面讲解如何自定义属性:
需要在 res/values/attrs.xml  资源文件中声明<declare-styleable> 标签,直接看例子:

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>
name属性必须指定,在运行时需要根据这个名称来取得 自定义属性列表中的所有值。具体attr 属性的定义规则,这里不做讲解,可以自行百度。需要注意的一点是自定义属性的 name 值应该与你的自定view的 类名相同,这样方便IDE来自动补全代码。

定义好属性后,可以在XML布局中调用,调用之前需要声明一个自定义命名空间,这个是用来区分 属性归属的,下面看例子:

<?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/com.example.customviews">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

每个布局中都会有
 xmlns:android="http://schemas.android.com/apk/res/android"
     这个命名空间,这个是声明 android framework中的view需要的属性的命名空间,而自定义的属性命名空间需要 http://schemas.android.com/apk/res/[your package name] 这样申请。申请完后就可以通过 命名空间  名称 来调用了 。  


3.应用在XML布局中设置的自定义属性
当view 从XML 布局中创建时,所有在XML标签中声明的属性都会通过AttributeSet  传递给view的构造方法。这样就能够直接从传递过来的AttributeSet 中读取到自定义属性的值了,这样做有以下几个缺点;
  •      在AttributeSet  的属性值不会自动解析。
  •      主题Styles 不会自动申请。
而是会传递 AttributeSet     给 obtainStyledAttributes()   。这个方法会返回一个用来提取已经被样式化的属性值集合 TypedArray  。
 Android的资源编辑器在你调用obtainStyledAttributes() 时会做很多工作,会把所有的<declare-styleable>   值封装到  TypedArray 中,而你需要从TypedArray  中提取需要的属性值,看例子:
public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}
注意: TypedArray   是系统共享资源,所以必须在用完后 回收掉!

4.动态添加属性和事件
在XML中添加属性是非常强大的方法来控制view的显示和行为,但是只能在初始化时控制view。如果需要动态的控制view的属性就需要公开每个 属性的 getter和 setter 方法,看例子:
public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}
注意: setShowText  调用了   invalidate() 和 requestLayout() 方法。这两个方法的调用是非常重要的能够确保view的可靠性。 invalidate() 让系统重新绘制view 、 requestLayout() 通知系统重新布局view(例如view的尺寸,形状改变等)。     
自定义view 应该支持监听view的重要事件。例如 PieChart 声明一个自定义的事件回调OnCurrentItemChanged  来通知监听者 用户旋转了饼图。

5.设计辅助功能
自定义view应该支持更广泛的使用者,包括聋哑人和盲人等,为了支持辅助功能,你应该:
  • 使用Android的标签输入字段android:contentDescription 。
  •  在适当的时候通过调用  sendAccessibilityEvent() 发送辅助事件。
  • 支持设备控制器,例如 轨迹球等。
更多关于辅助功能请访问   Making Applications Accessible 。
  
二、Custom Drawing
自定义view的最重要的就是其外观。自定义绘制 能够非常容易或者复杂的实现你的需求。本课程介绍一些最常见的操作。

1.重写 onDraw()方法
自定义view的最重要的步骤是重写 onDraw()  方法。该方法的参数是Canvas 类,让view可以来绘制自己。Canvas 类定义了绘制文本、线条、位图和许多其它基本图形的方法。你可以在onDraw()   方法中创建自定义的 UI。

在可以调用 绘制方法的前,需要创建 Paint  类。

2.Create Drawing Objects (创建绘图对象)
android.graphics framework 把绘制分成两个部分:
  • 绘制什么,通过Canvas 实现。
  • 怎么绘制,通过Paint 实现。
例如:Canvas 提供方法来绘制线条,而Paint 提供方法来确定线条的颜色。Canvas 提供方法来绘制矩形,而Paint 提供方法来确定怎样填充矩形。总的来说,Canvas 提供方法绘制形状,而Paint 提供方法来确定形状的颜色、样式、字体等。

     所以在你绘制任何东西之前,你需要创建一个或者多个Paint 对象。 PieChart 例子在init 方法(在构造函数中调用)中声明:
private void init() {
   mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
   mTextPaint.setColor(mTextColor);
   if (mTextHeight == 0) {
       mTextHeight = mTextPaint.getTextSize();
   } else {
       mTextPaint.setTextSize(mTextHeight);
   }

   mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
   mPiePaint.setStyle(Paint.Style.FILL);
   mPiePaint.setTextSize(mTextHeight);

   mShadowPaint = new Paint(0);
   mShadowPaint.setColor(0xff101010);
   mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));

   ...
提前创建对象是一个重要的优化。Views 会非常频繁的重绘,并且许多对象都需要昂贵的初始化。在 onDraw()  方法中创建绘制对象会显著的降低性能,造成UI卡顿。

3.Handle Layout Events
为了正确的绘制出自定义的view,需要确定view的尺寸。复杂的自定义view需要根据多个布局在屏幕上的大小和形状来计算。哪怕只有一个app使用你的view,你都不能假设自定义view在屏幕上的尺寸。你应该处理不同屏幕尺寸、多屏幕密度以及各种宽高纵横比和屏幕方向。

虽然View 有很多方法来获取尺寸,但是大多数的这些方法不需要重写。如果自定义view不需要特别控制它的尺寸,只需要重写一个方法:onSizeChanged() 。

 onSizeChanged() 方法会在view第一次分配尺寸大小 或者 由于其它原因view的尺寸改变了 的时候调用。在onSizeChanged() 方法中计算view的位置、尺寸和其它与view尺寸有关的值,而不是每次绘制view的时候计算。 在 PieChart  例子中,在onSizeChanged() 方法中计算了 饼图的边框、文本标签 和 其它视觉元素的 相对位置。

当view被分配给一个尺寸,布局管理器会设定这个大小包括视图的所有padding。当你计算view的尺寸时,你必须自己取得padding值。下面是PieChart.onSizeChanged() :
 // Account for padding
       float xpad = (float)(getPaddingLeft() + getPaddingRight());
       float ypad = (float)(getPaddingTop() + getPaddingBottom());

       // Account for the label
       if (mShowText) xpad += mTextWidth;

       float ww = (float)w - xpad;
       float hh = (float)h - ypad;

       // Figure out how big we can make the pie.
       float diameter = Math.min(ww, hh);
如果需要更好的控制view的布局参数,重写 onMeasure() 方法。这个方法 的参数是 View.MeasureSpec 它会描述view的 父容器分配给view的尺寸,和分配的尺寸是硬性的最大值还是只是一个建议。为了优化,这些值都会压缩成整数,可以使用 View.MeasureSpec 的静态方法来解压出存储的每个整数信息。

下面是一个重写 onMeasure() 方法的例子。在实现过程中,PieChart  视图使它的区域足够大来使饼图能够放的下它的标签。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   // Try for a width based on our minimum
   int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
   int w = resolveSizeAndState(minw, widthMeasureSpec, 1);

   // Whatever the width ends up being, ask for a height that would let the pie
   // get as big as it can
   int minh = MeasureSpec.getSize(w) - (int)mTextWidth + getPaddingBottom() + getPaddingTop();
   int h = resolveSizeAndState(MeasureSpec.getSize(w) - (int)mTextWidth, heightMeasureSpec, 0);

   setMeasuredDimension(w, h);
}
在代码中有三个地方需要注意:
  
4.Draw !
  完成上述的初始化和测量代码后,就可以重写 onDraw() 方法了。每个view重写的 onDraw()  方法都是不同的,但是也有一些相同的常用操作: 



Android自定义View注意事项,初级安卓开发面试题 4.注意padding,让view支持padding,在onDraw方法中获取padding 5.注意滑动冲突,解决滑动冲突 6.尽量不要使用handl er,因为里边已有post系列方法,不需要再用handler 继承View重写onDraw方法 主要用于实现不规则的效果,即这种效果不方便通过布局的组合方式来实现。相当于就是得自己“画”了。采用这种方式需要自己支持wrap_content,padding也需要自己处理 继承ViewGroup派生特殊的Layout 主要用于实现自定义的布局,看起来很像几种V 阅读详情

相关推荐

安卓面试之自定义View流程及原理

自定义View原理学习博客整理

lentolove的博客 3412

Android 无障碍服务

它可以实时查看 Android 设备上的界面结构(UI 层级)、获取控件的各种属性,如 text、resource-id、class 等。AccessibilityService 是 Android 提供的一种系统级服务接口,允许开发者监听和控制全局界面交互,以便辅助操作、自动化任务或提供无障碍支持。Switch Access 是 Android 系统提供的一种无障碍功能,旨在帮助存在行动障碍的用户使用一种或多种“开关设备”来控制手机,而无需直接触摸屏幕。

heiyl的专栏 4385

安卓自定义view

自定义view

qq_33386162的博客 830

Android开发: 通过修改数据库改变屏幕旋转方向screen rotation

转自:http://whithin.blog.51cto.com/690417/1066779/通过修改数据库System settings 来修改手机屏幕的旋转方向, 设置Settings.System. ACCELEROMETER_ROTATION和Settings.System. USER_ROTATION的值,可以通过命令行和Java API来实现 1.通过命令行来修改su sqlite

高飞的专栏 4813

如何用Python+Librosa实现轴承异响检测?5步搞定工业设备故障预警

本文详细介绍了如何利用Python和Librosa库,通过5个步骤构建工业轴承异响检测与故障预警系统。从音频采集、预处理、频谱特征提取,到构建机器学习模型并进行实时监测,提供了完整的代码级解决方案。该方法能有效识别轴承早期故障特征,实现低成本、高效的设备预测性维护。

rnn9storyteller的博客 632

告别卡顿!在RK3588上优化Gstreamer推拉流与RKNN推理的完整Pipeline实战

本文详细介绍了在RK3588平台上优化Gstreamer推拉流与RKNN推理的全链路Pipeline实战。通过解码环节参数调优、RKNN线程管理、内存预分配策略以及编码输出优化,实现60FPS流畅处理与亚秒级延迟。特别针对实时视频分析场景,提供了从rtspsrc到appsink的毫秒级优化方案,助力开发者构建零卡顿的智能视觉系统。

weixin_30698527的博客 483

山川湖海 - Android无障碍功能优化实践

Hi,很高兴见到你!???????? 本文主要分享Android无障碍功能的一些优化经验,希望看完本篇,可以帮助到你,以及哪些特殊的用户。 前言 最近我们团队收到了一些用户的反馈: 有用户反馈,我们的部分功能按钮在无障碍下无法正常识别。其实这已经不是我第一次看到反馈了,第一次是16年ios端收到了用户的反馈,进行过一次优化。说来惭愧,反而是我们 Android 这边也一直没有专门进行过适配。 什么是无障碍功能? 对于一些视障人群或者听障人群而言,普通的App对它们来说使用起来可能困难重重。在 Androi

petterp的博客 4343

Proxmox VE(PVE)与UPS联动配置:实现智能断电保护方案

本文详细介绍了为Proxmox VE (PVE)服务器配置UPS智能断电保护的完整方案。通过安装和配置apcupsd软件,实现PVE与UPS的联动,可在市电中断、电池电量不足时自动触发安全关机流程,有效保护虚拟机数据与服务连续性。文章涵盖了硬件选择、软件配置、策略设定及实战测试指南,并扩展了网络共享UPS的高级应用。

python9snake的博客 508

onConfigurationChanged的作用

onConfigurationChanged的作用API原文说明:android:configChangesLists configuration changes that the activity will handle itself. When a configuration change occurs at runtime,the activity is shut d...

weixin_33842328的博客 398

ARM CMSIS DAP源码分析(二)

今天分析的是RDDI_DAP_GetARMRegs(DWORD *regs, DWORD *rfpu, ULONG64 mask)和RDDI_DAP_SetARMRegs(DWORD *regs, DWORD *rfpu, ULONG64 mask)这两个函数。 以RDDI_DAP_GetARMRegs(DWORD *regs, DWORD *rfpu, ULONG64 mask)为例,代码如下:

pengxiao618的专栏 7977

用python画年度和月度的日历图

用python画各种日历图,可以区分月份来画也可以画一整年的,日历图中可以体现自己的信息

weixin_44853840的博客 2138

Android自定义View

概述 Android开发进阶的必经之路 为什么要自定义View 自定义View的基本方法 自定义View的最基本的三个方法分别是: onMeasure()、onLayout()、onDraw(); View在Activity中显示出来,要经历测量、布局和绘制三个步骤,分别对应三个动作:measure、layout和draw。 测量:onMeasure()决定View的大小; 布局:onLayout()决定View在ViewGroup中的位置; 绘制:onDraw()决定绘制这个View。 自定义控

Rayman的博客 1万+

Backtrader Web:开源量化交易全栈平台

Backtrader Web是一个基于Backtrader框架的现代化量化交易全栈平台,将专业回测引擎与Web技术结合,提供从策略开发到实盘交易的完整解决方案。平台采用FastAPI+Vue3技术栈,具有118个内置策略模板、专业可视化分析工具和完整的策略生命周期管理功能。支持策略版本控制、参数优化、模拟/实盘交易及监控告警,通过RESTful API和WebSocket实现前后端交互。系统采用模块化设计,包含策略服务、回测服务等核心模块,支持SQLite/PostgreSQL等多种数据库。安装简单,5分钟

云金杞 641

安卓自定义View

安卓自定义View

eos-i的博客 5250

PCIe协议之 Equalization篇 之 理论篇 之 FFE

作为最后一道“精加工”工序,DFE利用其不放大噪声的优势,精准地消除残余的、强烈的后光标ISI,最终得到一个非常干净、张得很开的眼图,供判决器使用。信号经过信道衰减后变得模糊,首先由CTLE进行“粗调”,提供一个宽频带的增益,将眼图初步打开,为后面的DFE创造一个可以正常工作的信号环境。,它通过将输入信号在不同时间点上的多个副本(称为“抽头”)进行加权求和,来直接塑造或“整形”输出信号的波形。:这是最主要的信号路径,通常系数为正值,决定了信号的幅度。:将所有加权后的信号相加,产生最终的均衡输出。

那么菜的博客 752

YOLOv12改进专栏目录 | 本专栏持续更新500+篇内容 | 包含各种卷积、主干网络、各种注意力机制、检测头、损失函数、小目标检测改进、二次创新模块、独家创新等几百种创新点改进

《YOLOv12高效涨点改进专栏》提供500+创新改进方案,涵盖卷积、主干网络、注意力机制等模块优化,适用于检测、分割等任务。改进点来自顶会论文和个人经验,支持多种模型版本和任务场景。专栏包含详细教程、数据集增强、性能评估工具等,帮助科研人员快速实现模型优化和论文发表。提供完整运行项目和环境配置指导,适合计算机及相关专业研究人员使用,持续更新保障长期科研需求。

Ai缝合怪、助力小伙伴高效发论文 2301

安卓Android---自定义view

android的自定义view

Chenbaozeng的博客 2161

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

安卓开发 之小白养成-Android自定义View

自定义View的作用和场景 Android中内置的UI控件和布局⽆无法满⾜足需求的时候,就需要进⾏外观、操作都是⾃自定义的⼀一些控件, 定义View。 自定义View三种方式 继承已有的控件来实现自定义控件。 主要是当要实现的控件和已有的控件在很多方面比较类似, 通过对已有控件的扩展来满足要求。增加新的功能。 2.继承ViewGroup,把多个控件组合成一个自定义控件(组合控件...

qq_34506989的博客 590

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android开发之自定义View

在自定义View的时候,需要两个构造函数。否则在编译的时候会报异常:Binary XML file line Error inflating class. 原因是:Android在根据xml文件夹创建View对象的时候会调用View的双参构造方法,即public SquareView(Context context, AttributeSetattrs),所以如果没有写全的话就会报错。...

weixin_43858011的博客 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

重学Android:自定义View基础(一)

作为一名安卓开发,也被称为大前端,做一个美观的界面,是我们必备的基础技能,可能在开发中我们最常用的是系统自带的View,因为他能满足绝大部分需求,难一点的我们也可以上Github上找个三方库使用,少数情况下会让我们进行自定义View,当然这不代表着我们可以不去掌握其原理,因为它是通往中高级程序员的必经之路,也是大厂面试的热门知识,只有熟练掌握其核心原理,才能让我们在后续的开发中游刃有余。

WriteBug001的博客 1292

Android最全自定义view的入门,面试安卓卡顿

本人从事Android开发已经有十余年,算是一名资深的移动开发架构师了吧。根据我的观察发现,对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。所以在此将我十年载,从萌新小白一步步成长为Android移动开发架构师的学习笔记,从Android四大组件到手写实现一个架构设计,我都有一一的对应笔记为你讲解。当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。

2401_84544914的博客 372

安卓自定义view(全面)

安卓自定义view 一、view的测量 1.测量的模式: EXACTLY :精确值模式,当把空间的layout_width属性或者layout_height的属性设置为具体的数值时,或者指定为match_parent时候,系统就是使用的EXACTLY 模式; AT_MOST: 最大值模式,当空间的layout_width属性或者layout_height属性指定为wrap_content时候,控件大小跟着控件的内容变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。 UNSPECIFIED: 这

twenty_four_7的博客 3254

安卓自定义view小实例 + MVC 思想

安卓自定义view小实例 + MVC 思想 一、自定义view实例 1.布局文件下添加控件 <?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://schem

twenty_four_7的博客 659

深入理解Android之自定义View

自定义View、多线程、网络,被认为是Android开发者必须牢固掌握的最基础的三大基本功。而自定义View又是Android开发中特别重要的一环,很多地方都需要用到自定义View。这篇文章我就梳理一下自定义View的相关知识。 目录 (一)什么是自定义View (二)自定义组合View (三)自定义View的绘制 1. Canvas.drawXXX() Pa...

Fighting_初心的博客 1万+

【安卓开发】自定义View

实现特殊UI效果封装复杂交互逻辑提高View的复用性优化性能(针对特定场景)继承现有View(如Button、TextView等)继承ViewGroup(实现特殊布局)直接继承View(完全自定义)// 在代码中new时调用init();// 在XML布局中使用时调用init();// 解析自定义属性// 带样式时调用init();init();// 初始化画笔等对象try {// 必须回收// 必须实现的构造方法...@Override。

weixin_46896210的博客 1115
上一篇: java关键字之assert
下一篇: 在Android Studio中直接编译C/C++文件
恶魔果实
博客等级 码龄15年 6粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值