Android自定义View从0到1(二)分类及核心功能.png
1.自定义View分类
常见的Android自定义视图主要有两种类型:
1. 组合控制
它由Android的基本控件(TextView、ImageView、Button、ProgressBar等)组成,如下拉刷新、瀑布流控制、带左右滑动功能的控件、视频控制等。此类的难度自定义View在于程序逻辑处理
2.完全可定制的控件
继承自View、TextureView或SurfaceView,然后重写核心回调方法。以View为例,根据需要重写其构造、onMeasure、onLayout、onTouchEvent、onDraw、onAttachedToWindow、onDetachedFromWindow等方法。这种自定义View的难点在于程序设计、效率优化和排版,比如输入法中的手写控件、图文混合控件(现在很多都是通过webview加载网页来实现的)、个性化进度条、弹幕显示控件、Markdown控件、IDE代码编辑控件等
注意:
我们需要合理使用自定义View,切不可滥用。不要每次都自定义视图。基本控件能完成的功能不要自定义View,因为Android本身的基本空间就有性能优化和自定义View。价值在于实现基本控件无法达到的效果,为应用程序的性能增色不少;将常见的交互效果提取到自定义控件中可以促进重用并减少不必要的重复工作。
2.定制查看核心知识点
这部分主要介绍自定义View的核心知识点。上面提到,完全自定义的View通常会继承View、TextureView、SurfaceView,所以我们先来了解一下三者之间的区别。
1.View、SurfaceView、TextureView的区别
看法
普通视图与主窗口共享相同的绘图表面。 UI在主线程中绘制,可以在有或没有硬件加速的情况下工作(没有硬件加速,canvas的某些方法会失败)
表面视图
继承自View,绘图和显示效率高。因为它有独立的绘图表面,所以UI是在独立的线程中绘制的,不占用主线程的资源。 SurfaceView的使用与普通View不同,需要与SurfaceHodler配合使用。由于它不与主窗口共享相同的绘图表面,因此对其进行动画处理可能无法达到所需的效果。
纹理视图
继承自View,与SurfaceView相比,TextureView没有创建单独的绘图表面,这使得它可以像普通View一样执行一些变换操作,例如移动、动画等,但TextureView必须在硬件加速开启的窗口中在。正常工作;
2.几个重要的功能
最后我们通过自定义View的流程图了解一下自定义View的几个重要功能。
自定义view流程图.jpg
(1) 构造函数
构造函数是View的入口,可以用来初始化一些内容以及获取自定义属性。
View的构造函数有四个重载
自定义视图构造函数.png
从上图也可以看出,自定义View的构造函数最多有四个参数,而四个参数的构造函数只能在API 21或以上版本中使用,所以暂时不考虑四参数构造函数,但是我们还需要了解这四个参数到底代表什么?
Context:在View中随处使用
AttributeSet:XML 属性(从XML 扩充时使用)
int defStyleAttr:应用于View的默认样式(在主题中定义)
int defStyleRes:如果不使用defStyleAttr,则应用到View的默认样式
所以这里有一个问题。构造函数有四个,我们应该如何选择呢?
例如上图所示的自定义MyView就继承了View对象。如果我们想在普通代码中创建一个新的MyView,我们可以直接使用单参构造函数,这也是大多数人选择使用的方式。
单参数构造函数.png
那么什么时候使用二参数构造函数呢?比如有时候在xml中添加一个自定义的View,添加一些布局属性、宽高属性、边距属性等。这些属性将存储在第二个构造函数的AttributeSet 参数中。
带两个参数的构造函数.png
三个参数的构造函数比第二个构造函数多了一个int类型值,名为defStyleAttr。从名字上看,这是一个关于自定义属性的参数。第三个构造函数默认不会被系统调用,但是我们需要自己显式地调用它,比如在第二个构造函数中调用第三个函数,并将第三个参数设置为0。defStyleAttr指定一个在Theme样式中定义的attr。其类型为参考。主要在obtainStyledAttributes方法中生效。 getStyledAttributes 方法有四个参数。第三个参数是defStyleAttr。第四个参数是你自己指定的样式。当且仅当defStyleAttr 为0 或Theme 中未找到defStyleAttr 时,第四个参数才会在指定指定属性时生效。这些指的是默认属性。在xml中定义时,以xml文件中指定的为准,所以优先级大概是: xmlstyledefStyleAttrdefStyleResTheme 指定,当defStyleAttr 为0时,会跳过defStyleAttr指定的引用,所以一般使用0就可以满足一些基本的开发。
(2)onMeasure(测量View尺寸)
这个功能有什么用呢?把这个问题转化为问为什么我们需要测量View的大小?
因为View的大小不仅由自身决定,还受到父控件的影响。为了让我们的控件更好地适应各种情况,我们通常会自己进行测量。
onMeasure.png
MeasureSPce 共有三种模式:EXACTLY、AT_MOST 和UNSPECIFIED。除UNSPECIFIED外,还有两种模式:
当父布局为EXACTLY时,子控件决定大小或match_parent,模式为EXACTLY。当子控件为wrap_content时,模式为AT_MOST;
当父布局为AT_MOST时,子控件决定大小,模式为EXACTLY。当子控件wrap_content或match_parent时,模式为AT_MOST。
因此,在确定控件的大小时,需要确定MeasureSpec的模式,不能直接使用MeasureSpec的大小。执行一些逻辑处理后,调用setMeasureDimension() 方法并传递测量的宽度和高度以供布局使用。
onMeasure流程.png
在实际应用中,您只需记住三种测量模式即可。使用MeasureSpec的getSize获取值,使用getMode获取众数。如果修改了View的宽高,则不要调用super.onMeasure( widthMeasureSpec, heightMeasureSpec);但调用setMeasuredDimension( widthsize, heightsize);反而。
(3)onSizeChanged(确定View大小)
那么这个函数什么时候被调用呢?
当视图大小改变时调用该函数。
那么问题又来了。上面的onMeasure函数不是说修改View的宽高后,要调用setMeasuredDimension吗?调用该方法后,View的大小就基本确定了。 View的大小还会改变吗?这是因为View的大小不仅由其本身决定,还由其父控件决定,因此在确定View的大小时最好使用系统提供的onSizeChanged回调函数。
onSizeChanged.png
(4)onLayout(确定子View的布局位置)
确定布局的函数是onLayout,用于确定子View的位置。它用在自定义ViewGroup中。它调用子View的布局函数。比如有时候我们在自定义View的时候,需要使用这个函数来获取View的一些信息。当然,如果是纯View的话,就不需要重写这个方法了。为什么这么说呢?
因为简单的View不是View容器,没有子View,而onLayout方法主要指定子View的位置,水平还是垂直,所以在简单的自定义View中不需要重写onLayout方法。不过需要注意的一点是,子View的margin属性是否生效取决于父View是否在自己的onLayout方法中处理,而View的padding属性则在onDraw方法中生效。
(5)onDraw(绘制内容)
重点是onDraw,是实际的绘图部分。
onDraw.png
【深入探索Android UI:自定义视图基础教程(第二部分)】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于出了基础篇的第二部分了!
有9位网友表示赞同!
这篇文章应该讲一些更复杂的自定义View吧?
有20位网友表示赞同!
我已经对自定义View有点了解,期待学习更高级的内容。
有13位网友表示赞同!
想做个漂亮的App界面,就得自己动手设计View啊
有14位网友表示赞同!
什么时候出第三篇,我急着要学啊!
有18位网友表示赞同!
这篇文章应该能让我解决一些定制化布局的需求吧。
有9位网友表示赞同!
自定义View真难,希望文章能解释得详细点
有18位网友表示赞同!
我已经开始尝试做简单的自定义View了,感觉很有成就感。
有6位网友表示赞同!
学习Android开发需要掌握很多知识,自定义View很重要啊!
有7位网友表示赞同!
期待看到一些实际的代码示例
有8位网友表示赞同!
希望文章里能包含各种类型的自定义View的设计。
有6位网友表示赞同!
看了第一篇基础课,感觉这篇文章应该会给我更多实践经验。
有9位网友表示赞同!
Android开发越来越流行,掌握自定义View很有必要。
有11位网友表示赞同!
自定义View可以提升App的个性化和美观度。
有6位网友表示赞同!
学习Android开发真是个宝贵的技能!
有12位网友表示赞同!
这篇文章会不会讲一些动画效果怎么实现?
有12位网友表示赞同!
我已经掌握了基本的Android开发知识,期待继续深 dive 。
有17位网友表示赞同!
自定义View让我能够更自由地设计App界面。
有18位网友表示赞同!
希望文章能提供一些调试技巧,方便我解决问题。
有10位网友表示赞同!
期待作者继续分享高质量的Android开发内容!
有8位网友表示赞同!