揭开Android视图制作的神秘面纱
在Android的UI中,View是至关重要的一个组件,它是用户界面的根本构建块。在View的制作进程中,涉及到许多重要的概念和技能。本文将具体介绍Android View的制作进程,让你能够更好地了解和把握Android的UI开发。
什么是View?
View是Android体系中的一个根本组件,它是用户界面上的一个矩形区域,能够用来展现文本、图片、按钮等等。View能够呼应用户的交互事情,比方点击、滑动等等。在Android中,一切的UI组件都是继承自View类。
View的制作进程
View的制作进程能够分为三个阶段:丈量、布局和制作。下面咱们将逐一介绍这三个阶段。
丈量阶段(Measure)
丈量阶段是View制作进程的第一个重要阶段。在丈量阶段,体系会调用View的onMeasure
办法,丈量View的宽度和高度。在这个进程中,体系会依据View的LayoutParams和父容器的巨细来核算出View的巨细。
例:下面代码是一个自定义View的onMeasure办法例程。在丈量进程中,咱们设定了View的巨细。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 获取宽度的Size和Mode
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
// 如果Mode是精确的,直接返回
if (widthMode == MeasureSpec.EXACTLY) {
setMeasuredDimension(widthSize, heightMeasureSpec);
return;
}
// 核算View的宽度
int desiredWidth = getPaddingLeft() + getPaddingRight() + defaultWidth;
int measuredWidth;
if (desiredWidth < widthSize) {
measuredWidth = desiredWidth;
} else {
measuredWidth = widthSize;
}
// 设置宽度和高度的Size和Mode
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int measuredHeight = defaultHeight;
if (heightMode == MeasureSpec.EXACTLY) {
measuredHeight = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
measuredHeight = Math.min(defaultHeight, heightSize);
}
setMeasuredDimension(measuredWidth, measuredHeight);
}
在丈量阶段结束后,体系会将核算好的宽度和高度传递给布局阶段。
布局阶段(Layout)
布局阶段是View制作进程的第二个重要阶段。在布局阶段,体系会调用View的onLayout
办法,将View放置在父容器中的正确方位。在这个进程中,体系会依据View的LayoutParams和父容器的方位来确认View的方位。
例:下面代码是一个自定义ViewGroup的onLayout办法例程。在布局进程中,咱们遍历子View,并依据LayoutParams确认子View的方位和巨细。
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
int left = getPaddingLeft();
int top = getPaddingTop();
int right = getMeasuredWidth() - getPaddingRight();
int bottom = getMeasuredHeight() - getPaddingBottom();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childLeft = left + lp.leftMargin;
int childTop = top + lp.topMargin;
int childRight = right - lp.rightMargin;
int childBottom = bottom - lp.bottomMargin;
child.layout(childLeft, childTop, childRight, childBottom);
}
}
制作阶段(Draw)
制作阶段是View制作进程的最终一个重要阶段。在制作阶段,体系会调用View的onDraw
办法,制作View的内容。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。
例:下面代码是一个自定义View的onDraw办法例程。在制作进程中,咱们使用Paint目标制作了一段文本。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//制作文本
String text = "Hello World";
Paint paint = new Paint();
paint.setTextSize(50);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
canvas.drawText(text, 0, getHeight() / 2, paint);
}
除了制作内容,咱们还能够在制作阶段制作View的布景和远景。体系会调用drawBackground
和drawForeground
办法来制作布景和远景。值得注意的是,View的制作次序是:先制作布景,再制作内容,最终制作远景。
View的制作流程
View的制作流程能够看作是一个递归调用的进程,下面咱们将具体介绍这个进程。
Step 1:创立View
在View制作进程的开始阶段,咱们需要创立一个View目标,并将它添加到父容器中。在这个进程中,体系会调用View的结构函数,并将View的LayoutParams传递给它。
Step 2:丈量View
接下来,体系会调用View的measure
办法,丈量View的宽度和高度。在这个进程中,View会依据自身的LayoutParams和父容器的巨细来核算出自己的宽度和高度。
Step 3:布局View
在丈量完结后,体系会调用View的layout
办法,将View放置在父容器中的正确方位。在这个进程中,View会依据自身的LayoutParams和父容器的方位来确认自己的方位。
Step 4:制作布景
在布局完结后,体系会调用View的drawBackground
办法,制作View的布景。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。
Step 5:制作内容
接下来,体系会调用View的onDraw
办法,制作View的内容。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。
Step 6:制作远景
在制作内容完结后,体系会调用View的drawForeground
办法,制作View的远景。在这个进程中,咱们同样能够使用Canvas目标来制作各种形状、文本和图片等等。
Step 7:制作子View
接着,体系会递归调用ViewGroup的dispatchDraw
办法,制作一切子View的内容。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。
Step 8:完结制作
最终,一切的View制作完结,整个View树也就制作完结。
例:下面代码是一个自定义ViewGroup的制作流程例程。在制作进程中,咱们先画布景,再制作每个子View的内容。
public class MyViewGroup extends ViewGroup {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 丈量子View的宽高
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 获取ViewGroup的宽高巨细
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// 设置ViewGroup的宽高
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 遍历一切子View,设置它们的方位和巨细
int childCount = getChildCount();
int left, top, right, bottom;
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
left = childView.getLeft();
top = childView.getTop();
right = childView.getRight();
bottom = childView.getBottom();
childView.layout(left, top, right, bottom);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画布景
canvas.drawColor(Color.WHITE);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// 制作每个子View的内容
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
childView.draw(canvas);
}
}
}
在ViewGroup的制作流程中,体系会先调用ViewGroup的draw
办法,然后依次调用dispatchDraw
办法和制作每个子View的draw
办法。ViewGroup的制作次序是先制作自己的布景,再制作每个子View的内容和布景,最终制作自己的远景。
总结
本文具体介绍了Android View的制作进程,包含丈量阶段、布局阶段和制作阶段。一起,咱们还在代码完成的视点,具体说明了Android ViewGroup的制作流程,帮助你更好地了解和把握Android的UI开发。
引荐
android_startup: 供给一种在应用发动时能够愈加简略、高效的方法来初始化组件,优化发动速度。不只支撑Jetpack App Startup的全部功用,还供给额外的同步与异步等候、线程控制与多进程支撑等功用。
AwesomeGithub: 根据Github的客户端,纯操练项目,支撑组件化开发,支撑账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是根据JetPack&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等盛行开源技能。
flutter_github: 根据Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。
android-api-analysis: 结合具体的Demo来全面解析Android相关的知识点, 帮助读者能够更快的把握与了解所阐述的要点。
daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。