-
Android UI 架构图
Android中每一个控件都会占据一个矩形区域,控件大致可以分为View和ViewGroup,ViewGroup控件作为父类控件可以包含多个View。
- Android UI界面显示逻辑流程
Activity setContentView—>Window setContentView—>PhoneWindow setContentView—->PhoneWindow installDecor—–>PhoneWindow generateLayout——>PhoneWindow mLayoutInflater.inflate(layoutResID, mContentParent)。
Activity 类中有一个Window抽象类的实现PhoneWindow类,该类中有个内部类DecorView,继承自FrameLayout,在DecorView容器中添加了根布局,根布局中包含了一个id为 contnet的FrameLayout 内容布局,我们的Activity加载的布局xml最后添加到 id为content的FrameLayout布局当中了。用一个图来描述,如下:
- 坐标
getX、getY、getTranslationX、getTranslationY、getTop、getBottom、getLeft、getRight
getTop |
获取相对于父控件的左上角的X坐标 |
getBottom |
获取相对于父控件的左上角的Y坐标 |
getLeft |
获取相对于父控件的右下角的X坐标 |
getRight |
获取相对于父控件的右下角的Y轴坐标 |
getX |
获取相对于父控件左上角的X坐标(不是相对于屏幕) |
getY |
获取相对于父控件左上角的Y坐标(不是相对于屏幕) |
getTranslationX |
相对于自己,动画后相对于动画前X轴偏移量 |
getTranslationY |
相对于自己,动画后相对于动画前Y轴偏移量 |
注意:当view在平移的过程中,top/bottom/left/right表示原始左上角的位置坐标,其值不会改变。此时改变的是: x/y/translationX/translationY
Demo:
tv.postDelayed(new Runnable() {
@SuppressLint("NewApi")
@Override
public void run() {
Log.i(TAG, "动画前: "+tv.getTranslationX());
Log.i(TAG, "动画前: "+tv.getTranslationY());
Log.i(TAG, "动画前: "+tv.getX());
Log.i(TAG, "动画前: "+tv.getY());
Log.i(TAG, "动画前: "+tv.getTop());
Log.i(TAG, "动画前: "+tv.getBottom());
Log.i(TAG, "动画前: "+tv.getLeft());
Log.i(TAG, "动画前: "+tv.getRight());
}
}, 1000);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator.ofFloat(tv,"translationX",100f).setDuration(1000).start();
ObjectAnimator.ofFloat(tv,"translationY",100f).setDuration(1000).start();
tv.postDelayed(new Runnable() {
@Override
public void run() {
Log.i(TAG, "动画后: "+tv.getTranslationX());
Log.i(TAG, "动画后: "+tv.getTranslationY());
Log.i(TAG, "动画后: "+tv.getX());
Log.i(TAG, "动画后: "+tv.getY());
Log.i(TAG, "动画后: "+tv.getTop());
Log.i(TAG, "动画后: "+tv.getBottom());
Log.i(TAG, "动画后: "+tv.getLeft());
Log.i(TAG, "动画后: "+tv.getRight());
}
}, 1000);
}
});
日志:
CustomViewTag: 动画前: 0.0 没有做动画之前相对于自己值为0
CustomViewTag: 动画前: 0.0 没有做动画之前相对于自己值为0
CustomViewTag: 动画前: 100.0 相对于父控件的左边距为100
CustomViewTag: 动画前: 150.0 相对于父控件的上边距为150
CustomViewTag: 动画前: 150
CustomViewTag: 动画前: 650
CustomViewTag: 动画前: 100
CustomViewTag: 动画前: 400
CustomViewTag: 动画后: 99.92871
CustomViewTag: 动画后: 99.92871
CustomViewTag: 动画后: 199.92871
CustomViewTag: 动画后: 249.92871
CustomViewTag: 动画后: 150
CustomViewTag: 动画后: 650
CustomViewTag: 动画后: 100
CustomViewTag: 动画后: 400
- 三种测量模式
- EXACTLY精准模式,分为两种情况:控件的layout_width,layout_height设置指定数值时,例如layout_width = "100dp"、
控件的layout_width,layout_height设置为match_parent
- AT_MOST最大值模式:控件的layout_width,layout_height设置为wrap_parent时
- UNSPECIFIED未指明模式:不指定View大小,想多大就多大
注意:View的onMeasure方法只支持EXACTLY模式。自定义View时,需要重写onMeasure方法才能支持其他模式。例如:自定义View layout_height想要设置为wrap_parent,就要在onMeasure方法中告诉系统自定义View的wrap_parent的大小。
- 绘制方法
方法 |
作用 |
drawRect |
画矩形 |
drawCircle |
画圆 |
drawArc |
画弧形 |
drawRoundRect |
画圆角矩形 |
drawBitmap |
画Bitmap |
drawVoal |
画椭圆 |
drawText |
画文字 |
- 常用属性
绘制文字:
方法 |
作用 |
setColor |
设置画笔颜色 |
setStrokeWidth |
设置画笔粗细 |
setTextSkewX |
设置字体倾斜,负为右、正为左 |
setARGB(int a,int r,int g,int b) |
a为透明度 |
setTextSize |
设置字体大小 |
setFakeboldText |
设置是否粗体 |
setTextAlign |
设置字体对齐方式,LEFT/CENTER/RIGHT |
setUnderLineText |
设置下划线 |
setStyle |
设置画笔样式,FILL,STROKE,FILL_AND_STROKE |
setTypeFace |
设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等 |
绘制图片:
方法 |
作用 |
setDither |
设置抖动处理 |
setAlpha |
设置透明度 |
setAntiAlias(boolean aa) |
是否开启抗锯齿 |
setFilterBitmap() |
是否开启优化Bitmap |
setColorFilter(ColorFilter filter) |
设置颜色过滤 |
setMaskFilter(MaskFilter maskfilter) |
设置滤镜的效果 |
setShader(Shader shader) |
设置图像渐变效果 |
setSrokeJoin(Paint.Join join) |
设置图像结合方式 |
setXfermode(Xfermode xfermode) |
设置图像重叠效果 |
setPathEffect(PathEffect effect) |
设置路径效果 |
reset() |
恢复默认设置 |
学习参考:
https://www.jianshu.com/p/ba6db48fd2b9
https://blog.csdn.net/forwardto9/article/details/79770618