Android -- 每日一问:如何实现自定义View?

news/2024/10/30 19:28:00/

在这里插入图片描述

经典回答

回忆一下,你去面试时常被问到的自定义 View 方面的问题是那些。有没有:

  • invalidate 和 postInvalidate 方法的区别?
  • 自定义 View 的绘制流程?
  • View 的 Touch 事件分发流程?

因为在实际的工作中并不是每个人都会涉及UI的实现,所以有些人没有做过自定义 View 并不能否决这个人在 Android 开发上的能力,包括会问你这方面问题的面试官也可能并没有自定义 View 的经验。所以很多面试中,一般也就是问问如上面的那些机制方面的问题,看面试者是否有一个正确的认识。但如果一个人说他精通自定义View的话,不妨从细节上检验一下他。

在说我怎么检验面试者的自定义View水平之前,先来一道老外的面试题,大家不妨先自己试着敲一下代码看能不能实现。

image.png

效果界面如下:
image.png

这一道题其实把我们刚刚提到的面试常被问到的那些机制问题都涉及到了,你很容易就能查找和了解并可以很好的回答上那几个基础问题,但是你能做出这个自定义View吗?

这就是机制和现实的差距!你有必要了解机制(基础),但了解并不等于会了,会的过程需要一定的积累,只有融会贯通了才能轻而易举地完成这个老外的面试题。

我们简单剖析一下,这个可左右滑动的View中是一组子View组成的,每个子View(圆盘carousel)可以自定界面,但背景的样式是相似(每组背景只是颜色不一样),有点ListView中的Adapter味道,对滑动的过渡是有要求的,这个其实是更真实操作Touch的样例(没有人想看生硬的滑动效果)。那么我们要能实现上面的效果,需要注意以下几个点:

  • ViewGroup的布局(计算一行能显示的圆盘数量和大小)
    圆盘View的效果(背景和半透明过渡)
    左右列表和BaseAdapter
    圆盘View的滑动(需要自动回弹,保证滑动后要有一个圆盘处于中间位置)

  • View & ViewGroup
    自定义View(有时我们也可以叫自定义UI或者自定义UI组件),从实现或者分类上我觉得可以分为三类:

  • 直接继承View
    继承自ViewGroup
    对现有组件的扩展(如继承自TextView)
    第3种方式是比较容易的,因为父组件常常帮我处理了绘制、分发和Touch等事件,我们只需要加入一些特别的功能就行。比如继承自ImageView实现图片圆角显示。

第1和第2种方式,需要我们对前面提到的那些机制问题有一定的了解,也要搞清楚View和ViewGroup在哪些方面有什么区别。

ViewGroup继承自View,是一种特殊的View,可以理解成一种View的容器,它可以装其他的View或其他的ViewGroup。
ViewGroup需要控制子View如何布局,所以必须实现onLayout(在ViewGroup中是抽像方法)。
ViewGroup可以通过onInterceptTouchEvent拦截当前事件,再决定是否分发给子View处理。
ViewGroup默认是不会调用onDraw方法的,如果需要重绘容器的背景需要在构造函数调用setWillNotDraw(false)。

除此之外,要熟悉一些概念(或者类):Canvas, Paint, Matrix,Path & PathMeasure,贝塞尔曲线,SufaceView & OpenGL等等。是不是觉得概念太多了,是的,没有实际做过,你一定会这样想。让你为了面试去准备这么多东西,貌似也起不到多大的作用,面试官不一定会问(除非指明了招专门做自定义UI的开发)。而且就算面试官问了一个你准备好的主题,但他换一种说法问你,如果你只是准备过但并没有掌握的话,也不一定能答得上来。就拿PathMaesure来说,做为面试官一般不会直接问你:“这个PathMeasure有什么方法或者主要是做什么用的啊?”

而往往会用实例来看你的实现思路,例:“如何实现下图的这个箭头图标(png图片)围绕园周运动的自定义View”。如果你的做法不是使用PathMeasure,那么我也会很有兴趣想听听你的思路和实现方法。

121212.gif

灵活使用PathMeasure的常见的两个方法可以轻松的实现很多神奇的效果。
getSegment:截取整个Path的片段;
getPosTan:获取路径上的坐标点和对应点的切线坐标。

使用PathMeasure实现的核心代码:

    path = new Path();path.addCircle(0, 0, 200, Path.Direction.CW); //添加一个圆的pathpathMeasure = new PathMeasure(path, false);float[] pos = new float[2];float[] tan = new float[2];pathMeasure.getPosTan(pathMeasure.getLength() * value, pos, tan);float degress = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI); // 计算箭头图片的旋转角度

如果面试者不了解PathMeasure的话,也可以问一下图片圆角(或称矩形圆角)或者圆形头像的实现方式,这个也是一个很常见的功能,效果如下图:
image.png

把原图直接做成圆角外,常见有三种方式实现:

  • 使用 Xfermode 混合图层;
  • 使用 BitmapShader;
  • 通过裁剪画布区域实现指定形状的图形(ClipPath)

你的朋友是不是也在准备面试呢?你可以把今天的题目分享给好友,或许你可以帮到他。


http://www.ppmy.cn/news/6072.html

相关文章

刷爆力扣之仅含 1 的子串数

刷爆力扣之仅含 1 的子串数 HELLO,各位看官大大好,我是阿呆 🙈🙈🙈 今天阿呆继续记录下力扣刷题过程,收录在专栏算法中 😜😜😜 该专栏按照不同类别标签进行刷题&#x…

常用的 Emoji 符号

表情类 😀 😁 😂 🤣 😃 😄 😅 😆 😉 😊 😋 😎 😍 😘 😗 😙 😚 ☺️ &…

数字化时代,看商业智能BI与业务发展分析

每一家企业我们都可以从模式、问题和求解这三个角度对企业的业务经营管理进行探讨,比如模式,公司目前的管理模式和运营模式效果如何,是否符合公司长期战略目标或中短期业绩增长目标? 数据分析 - 派可数据商业智能BI可视化分析平台…

2022世界杯回忆录:我的青春我的歌

前言 2022世界杯硝烟散尽,12月19号凌晨,阿根廷夺冠后,我如释重负地倒头睡了。醒来后一直想写点文字,这是我一直以来的习惯。我知道,在地球的另一端,在那个正处在夏天的南美大陆,和北京的数九寒…

2005-2020年全国及31省绿色信贷水平原始数据及测算

2005-2020年各省绿色信贷水平原始数据及测算 1、时间:2005-2020年 2、来源:整理自统计NJ、工业NJ、2018年经济普查,其中2017年采用插值法填补 3、范围:包括全国及31省市 4、数据内容:包含计算过程和原始数据 5、具…

H3C 二层链路聚合

简介: 它通过将多条以太网物理链路捆绑在一起成为一条逻辑链路,从而实现增加链路带宽的目的。 成员端口: 选中(Selected)状态:此状态下的成员端口可以参与用户数据的转发,处于此状态的成员端口…

限定城市|临床医生自费赴日本大阪公立大学医学院访学观摩

X医生拟自费访学,目标是日本大阪都市圈,包括大阪、京都、奈良、神户等,优先考虑大阪市及京都市。最终我们申请到大阪公立大学医学院,对方在一周内连续发来两封邀请函,以便于X医生办理护照及单位的审批手续。对于首次办…

记录Android Jni编译过程

Gradle配置 我们主要看这个配置文件里面吧,这里面有关于ndk配置的选项。 大概介绍一下,这里面一些字段是干嘛的。 我们看,这里面有两个相仿的字段,都是externalNativeBuild字段,但是位于两个不同的位置,其…