android View基本知识
来源:互联网 发布:淘宝九一一正品折扣店 编辑:程序博客网 时间:2024/06/11 21:43
本文参考了博客
https://www.zybuluo.com/TryLoveCatch/note/722664
View 获取坐标方法
- getTop(): 获取View顶部相对父布局的距离
- getLeft(): 获取View左侧相对父布局的距离
- getBottom():获取View底部相对父布局的距离
- getRight(): 获取View右侧相对父布局的距离
- getTranslationX(): View相对于X轴的偏移量
- getTranslationY(): View相对于Y轴的偏移量
- getX(): View的虚拟x坐标,=getLeft()+getTranslationX()
- getY(): View的虚拟y坐标,=getTop()+getTranslationY()
- getScrollX(): View 内容在x轴上的滚动偏移量
- getScrollY(): View 内容在y轴上的滚动偏移量
MotionEvent 获取坐标方法
- getX(): 获取触摸点距离当前控件左边的距离
- getY(): 获取触摸点距离当前控件上边的距离
// todo: 这里画个图,解释各个方法
View 的setTranslationX()和setTranslationY()会改变translationX和translationY的值,但不会改变margin的值,所以,getLeft()和getTop()不会改变,setTranslationX(0)会恢复translationX的值。
这里可以得出结论,View的宽高由left, top, right和bottom这几个参数决定,而X, Y, translationX和translationY则影响View的位置,如果想要实现更加平滑的View移动效果,可以使用属性动画,直接修改View的属性值。
measuredWidth和width的区别
一般情况下,我们通过getWidth()方法和getMeasuredWidth()方法得到的View宽度是一样的,但其实,这两个方法从字面意思上理解,再结合源码分析,发现measuredWidth值是在View的measure阶段决定的,由方法setMeasuredWidthDimension()方法赋值,而width是在View的layout阶段,由layout()方法决定的。通常layout()方法在parent中被调用,来确定child views在父容器中的位置,一般在自定义ViewGroup的onLayout()方法中调用。
需要注意的是,通常View的width和height是由View本身和parent容器共同决定的,比如,View通过自身measure()方法向parent的请求100*100的宽高,那么这个宽高就是measuredWidth和measuredHeight的值,但是,在parent的onLayout()方法中,通过调用childView.layout()方法只分配给childView50*50的宽高,那么这个50*50就是childView实际绘制并显示到屏幕的宽高,也就是width和height的值。
举个栗子:
import android.app.Activity;import android.content.Context;import android.graphics.Canvas;import android.os.Bundle;import android.support.annotation.Nullable;import android.util.Log;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;public class LearnViewWidthActivity extends Activity{ private LinearLayout mLayout; private TextView mView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLayout = new MyLinearLayout(this); mLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); mView = new MyTextView(this); mLayout.addView(mView); setContentView(mLayout); } private class MyLinearLayout extends LinearLayout{ public MyLinearLayout(Context context) { super(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); View v = getChildAt(0); v.layout(0,0,50,50); } } private class MyTextView extends android.support.v7.widget.AppCompatTextView{ public MyTextView(Context context) { super(context); setText("test"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); measure(0,0); Log.i("===>","width="+getWidth()+",height="+getHeight()); Log.i("===>","measuredWidth="+getMeasuredWidth()+",measuredHeight="+getMeasuredHeight()); } }}
Log输出:
width=50,height=50measuredWidth=214,measuredHeight=38
正确获取measuredWidth的方法
- onWindowFocusChanged()
onWindowFocusChanged()方法表示View已经绘制完了,宽高已经准备好了,此时可以获取View的宽高值了。通过打印Activity的生命周期执行情况发现,这个方法会执行多次,每当Activity onResume()或者onPause()都会执行该方法。
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus){ int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); Log.i("===>","onWindowFocusChanged, width="+width+",height="+height); } }
- View.post(Runnable)
我们有时会通过该方法使用主线程刷新UI,刷新UI后当然说明View已经绘制完成,此时获取View的宽高肯定是没有问题的。
mView.post(new Runnable() { @Override public void run() { int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); Log.i("===>","post, width="+width+",height="+height); } });
- ViewTreeObserver
这个几乎没用过,纯参考,记录学习一下
ViewTreeObserver的众多接口和相应回调方法可以完成此功能。如onGlobalLayoutListener接口,官方解释:当View树的layout状态发生改变或者其子View可见性发生改变时,onGlobalLayout()方法会被回调。随着View树的变化,这个方法也会被执行多次。
ViewTreeObserver viewTreeObserver = mView.getViewTreeObserver(); viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); Log.i("===>","onGlobalLayout, width="+width+",height="+height); } });
- View.measure()
View的绘制流程:measure->layout->draw。最常见的用法就是measure(0,0),在上面的例子中就是这样用的,这里的0,0表示的意思是View测量中的常量View.MeasureSpec.UNSPECIFIED,View向parent请求的宽高保存在MeasureSpec中,由size和mode组成,其中mode共三个int值,这是源码定义:
/** * Measure specification mode: The parent has not imposed any constraint * on the child. It can be whatever size it wants. */ public static final int UNSPECIFIED = 0 << MODE_SHIFT; /** * Measure specification mode: The parent has determined an exact size * for the child. The child is going to be given those bounds regardless * of how big it wants to be. */ public static final int EXACTLY = 1 << MODE_SHIFT; /** * Measure specification mode: The child can be as large as it wants up * to the specified size. */ public static final int AT_MOST = 2 << MODE_SHIFT;
再看size与mode的关系:
public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
所以measure(0,0)返回的就是mMinWidth, 或者mBackground.getMinimumWidth().
- android View基本知识
- View基本知识
- View基本知识
- Android自定义View研究(二) -- 绘图的基本知识
- Android自定义View研究(二) -- 绘图的基本知识
- Android中继承View的研究(二) -- 绘图的基本知识
- Android 自定义View(2) -- 绘图的基本知识
- Android开发艺术探索学习-View的基本知识
- Android开发艺术探索(连载)之View 的事件体系(一)view的基本知识
- Android基本知识
- android基本知识
- Android基本知识
- android基本知识
- Android基本知识
- View的滑动的基本知识
- Android 开发基本知识备忘
- android AIDL的基本知识
- Android MediaPlayer基本知识
- 移动端google浏览器默认事件
- 高级软件工程 实验三
- 信息安全工程师 学习笔记(四)
- 无法读取本地图片的错误(运行时权限的添加)
- 【Pivot Stickfigure Animator】——PeppaPig
- android View基本知识
- 9. Palindrome Number
- 赛后总结(Codeforces Round #399 Div. 1)
- maven初学
- CSS3 修改和去除移动端点击事件出现的背景框 (tap-highlight-color)
- 关于form表单中使用ajax提交表单,ajax无法success的问题
- [编程之美-10]字符串的包含问题
- Apache的下载安装(主要说的 64位)及问题
- 信息安全工程师 学习笔记(五)