android自定义view实现原理,android随笔之自定义View基本原理
前言:
在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理。
自定义控件要求:
1. 应当遵守Android标准的规范(命名,可配置,事件处理等)。
2. 在XML布局中可配置控件的属性。
3. 对交互应当有合适的反馈,比如按下,点击等。
4. 具有兼容性, Android版本很多,应该具有广泛的适用性。
自定义控件学习步骤:
1 .View的工作原理
2 .编写View类
3.为View类增加属性
4 .绘制屏幕
5. 响应用户消息
6 .自定义回调函数
自定义控件两种方式:
1. 继承ViewGroup
例如:ViewGroup、LinearLayout、FrameLayout、RelativeLayout等。
2. 继承View
例如:View、TextView、ImageView、Button等。
自定义控件基本绘制原理:
View的绘制基本上由measure()、layout()、draw()这个三个函数完成
1.)测量-Measure过程是计算视图大小,View measure过程相关方法主要有三个:
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
measure调用onMeasure,onMeasure测量宽度、高度然后调用setMeasureDimension保存测量结果,measure,setMeasureDimension是final类型,view的子类不需要重写,onMeasure在view的子类中重写。
关于MeasureSpec:
(1) UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.
(2) EXACTLY父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.
(3) AT_MOST子容器可以是声明大小内的任意大小.
2.)布局-Layout过程用于设置视图在屏幕中显示的位置,View layout过程相关方法主要要三个:
protected boolean setFrame(int left, int top, int right, int bottom)
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用
3.)绘制-draw过程主要用于利用前两步得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。
protected void onDraw(Canvas canvas)
通过调用draw函数进行视图绘制,在View类中onDraw函数是个空函数,最终的绘制需求需要在自定义的onDraw函数中进行实现,比如ImageView完成图片的绘制,如果自定义ViewGroup这个函数则不需要重载。
自定义控件示例:
这里先介绍继承View的方式为例,其实ViewGroup最终的继承的也是View。这里 模拟一个需求场景,需要一个圆形显示百分比。
private final static String TAG = PercentView.class.getSimpleName();
private Paint mPaint;
private RectF oval;
public PercentView(Context context) {
super(context);
init();
}
public PercentView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PercentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
oval=new RectF();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Log.e(TAG, "onMeasure--widthMode-->" + widthMode);
switch (widthMode) {
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
break;
case MeasureSpec.UNSPECIFIED:
break;
}
Log.e(TAG, "onMeasure--widthSize-->" + widthSize);
Log.e(TAG, "onMeasure--heightMode-->" + heightMode);
Log.e(TAG, "onMeasure--heightSize-->" + heightSize);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.e(TAG, "onLayout");
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.GRAY);
// FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
int with = getWidth();
int height = getHeight();
Log.e(TAG, "onDraw---->" + with + "*" + height);
float radius = with / 4;
canvas.drawCircle(with / 2, with / 2, radius, mPaint);
mPaint.setColor(Color.BLUE);
oval.set(with / 2 - radius, with / 2 - radius, with / 2
+ radius, with / 2 + radius);//用于定义的圆弧的形状和大小的界限
canvas.drawArc(oval, 270, 120, true, mPaint); //根据进度画圆弧
}
}
在布局中如何使用
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_margin="10dp" />
总结:
本篇主要介绍Android自定义控件的基本绘制原理,后面会介绍如何自定义属性。
android自定义view实现原理,android随笔之自定义View基本原理相关推荐
- android动画的实现原理,Android动画的实现原理 .
1.动画运行模式 独行模式 中断模式 2.Animation类 每个动画都重载了父类的applyTransformation方法这个方法的主要作用是把一些属性组装成一个Transformation类, ...
- android qq功能实现原理,Android QQ、微信聊天消息界面设计原理与实现
Android QQ.微信聊天消息界面设计原理与实现 原理:Android平台上,典型的以腾讯的QQ.微信这些聊天消息界面通常可以采用ListView设计与实现,需要使用ListView 适配器 ...
- View工作原理(二)导致View重建原因
导致View重建的原因有三个: 1.视图本身内部状态变化引起重绘: 2.view树内部添加或者删除子view: 3.View本身的大小及可见性发生变化. 这三种情况最后都直接或者间接的调用到了三个方法 ...
- Android病毒查杀原理,Android编程之杀毒的实现原理及具体实例
本文实例讲述了Android杀毒的实现原理.分享给大家供大家参考,具体如下: 一个杀毒软甲最核心的部分一个是病毒库一个是杀毒引擎,病毒库从服务器中获得,杀毒引擎实际上是判断程序中的包名和签名是否匹配病 ...
- Android中AMS工作原理,Android AMS启动详解
启动 在Android系统启动流程中中我们提到过,AMS是在system_service中启动的, //frameworks/base/services/java/corri/android/serv ...
- android群聊红包原理,Android之微信抢红包实现原理分析
微信抢红包主要用到AccessibilityService,该服务需要用户手动到辅助功能里面授权,下面直接粘贴源码,先看Activity,主要是跳转到辅助功能界面,让用户开启辅助功能的服务: publ ...
- android护眼程序原理,Android 护眼模式的实现
思路:获取content根布局,在上面添加一层浮层,默认透明,开启护眼模式设置护眼色值. 实现:在BaseActivity的onCreate方法中,添加浮层,所有的Activity继承BaseActi ...
- android 系统截屏原理,Android 系统副屏截屏功能
收到一个客户需求,要求对双屏设备的副屏进行截图.查询资料后发现,系统截图有两种方法,一种是通过SurfaceControl.screenshot提供的接口调用,还有一种是通过screencap 命令获 ...
- android省电模式 原理,Android省电模式侦听器?
所以你只需要接受它: 的AndroidManifest.xml: PowerSaveModeReceiver.java: public class PowerSaveModeReceiver exte ...
最新文章
- 特征值和特征向量的实际意义
- android小程序源代码_我从 Android 转到微信小程序的思考
- rpm卸载mysql和php_Linux系统中自带Mysql、Apache、Php卸载
- python爬虫如何从一个页面进入另一个页面-爬虫入门(一)——如何打开一个网页...
- ORG.SPRINGFRAMEWORK.HTTP.CONVERTER.HTTPMESSAGENOTREADABLEEXCEPTION: COULD NOT READ JSON: UNRECOGNIZE
- nginx学习十 ngx_cycle_t 、ngx_connection_t 和ngx_listening_t
- php url地址 怎么写,php url地址重写
- LeetCode 1814. 统计一个数组中好对子的数目(哈希)
- kafka集群下载、启动、部署、测试
- 2022年百度新能源汽车行业洞察
- Bootstrap3.0 栅格系统背后的精妙魔法(Bootstrap3.0的栅格布局系统实现原理) - willian12345...
- linux安装qq_体验一下,看看 Linux 系统中的 QQ 是什么样子的
- springboot集成oauth2和JWT(授权码模式)
- 互利的关系方能长久,可惜大部分人就是不懂
- [Visual Studio] 重置默认设置 还原默认设置
- vivado之FFT ip核的入门学习
- Mysql中select into from用法
- 利用Python爬虫爬取淘宝商品做数据挖掘分析实战篇,超详细教程!
- 后台管理系统(第一天)
- [cocos2d-iphone]ios6截图问题
热门文章
- 牛客网--蘑菇街2016研发工程师编程题
- Oracle中如何判断字符串是否全为数字
- [转载]Java数组扩容算法及Java对它的应用
- 软件工程学习进度06
- 中文字体字号和磅数的转化
- python 字符集编码设置(精华)
- 计算机学院科技活动策划,计算机学院科技创新活动策划书(7页)-原创力文档...
- pix4d无人机影像处理_让无人机创造更大价值?你还差一个Pix4D培训会!
- C++静态数据成员与静态函数(案例分析)
- Python之进程+线程+协程(multiprocessing多进程模块)