View的三大流程之View的测量

1、
public class

View

extends Object
implements Drawable.Callback KeyEvent.Callback AccessibilityEventSource
java.lang.Object
   ↳android.view.View

Class Overview

This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class forwidgets, which are used to create interactive UI components (buttons, text fields, etc.).

public abstract class
View是Android中所有控件的基类,Button/TextView/RelativeLayout/ListView等,其共同基类都是View。View是界面层的控件的一种抽象,待变一个控件。

ViewGroup

extends View
implements ViewManager ViewParent

java.lang.Object
   ↳android.view.View
    ↳android.view.ViewGroup

 

Class Overview

A ViewGroup is a special view that can contain other views (called children.) The view group is the base class for layouts and views containers.

ViewGroup内部包含一组View,ViewGroup也继承自View,这就说明View本身就可以使单个控件或多个控件组成的一组控件。

UI界面架构图:

每个Activity都包含一个Window对象,Window对象通常由PhoneWindow来实现。PhoneWindow将一个DecorWindow设置为整个窗口的根View。DecView里有所有View的监听事件,通过WindowManagerService进行接收,并通过Activity对象回调相应的onClickListener。显示界面上,将屏幕分为两部分,分别为TitleView和ContentView。ContentView是一个ID为content的FrameLayout,布局文件activity_main.xml就是设置在这样一个FrameLayout中。

2、

View的位置参数:

View根据上图得到View的宽高和坐标(相对于ViewGroup,而不是原点)的关系:

width = right - left;

height = bottom - top;

获取这几个参数的方法如下:

mLeft = getLeft();
mRight = getRight();
mTop = getTop();
mBottom = getBottpm();

Android3.0开始View增加了几个参数:x,y,translationX,translationY,其中x,y是View左上角的坐标,translationX,translationY是View左上角相对于父容器的偏移量:

x = left + translationX;

y = top + translationY;

需要注意:View在平移过程中,top/left表示的是原始左上角的位置信息,其值在移动期间不会发生改变,变化的是x,y,translationX,translationY.


3、View的三大流程(measure,layout,draw)之View的测量

View的绘制流程从ViewRoot的performTraversals方法开始,ViewRoot对应于ViewRootImpl类,是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成。在ActivityThread中,当Activity对象被创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象与DecorView相关联:

root = new ViewRootImpl(view.getContext(),display);
root.setView(view,wparams,panelParentView);

View的绘制流程从ViewRoot的performTraversals方法开始,经过measure,layout,draw三个过程将一个View绘制出来。

performTraversals会依次调用performMeasure,performLayout,performDraw三个方法,分别完成顶级View的measure,layout,draw三大流程,其中performMeasure中会调用measure方法,在measure方法中又调用onMeasure方法,在inMeasure方法中会对所有子元素进行measure过程,此时measure流程就从父元素传到子元素了,这样完成了一次measure过程。接着子元素会重复父容器的measure过程,如此反复完成整个View树的遍历。performLayout与performDraw与之类似,不同的是performDraw的传递过程是在draw方法中通过dispatchDraw来实现。

测量过程在onMeasure()方法中进行。

Android提供了一个功能强大的类--MeasureSpec类。

public static class

View.MeasureSpec

extends Object
java.lang.Object
   ↳android.view.View.MeasureSpec
Added in API level 1

public static class

View.MeasureSpec

extends Object
java.lang.Object
   ↳android.view.View.MeasureSpec

Class Overview

A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes:

UNSPECIFIED
The parent has not imposed any constraint on the child. It can be whatever size it wants.
EXACTLY
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.
AT_MOST
The child can be as large as it wants up to the specified size.

MeasureSpec是一个32位的int值,高2位为测量模式(SpecMode),低30位是测量大小(SpecSize).

View默认的onMeasure()方法只支持EXACTLY模式,因此如果让自定义View支持wrap_content属性,就必须重写onMeasure()方法来指定wrap_content大小(进一步说明,由源码得出,wrap_content下的SpecMode是AT_MOST,此时的specSize是parentSize,即如果不指定wrap_content,在布局中使用wrap_content就相当于使用match_parent).

解决方法:

protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){setMeasureDimension(mWidth,mHeight);}else if(widthSpecMode == MeasureSpec.AT_MOST){setMeasureDimension(mWidth,heightSpecSize);}else if(heightSpecMode == MeasureSpec.AT_MOST){setMeasureDimension(widthSoecSize,mHeight)}
}

在上面代码中指定View的默认宽高(mWidth/mHeight),并在wrap_content时设置此宽高。
Demo:

MeasureView.java


 

package sunny.example.ahthreeviewmeasure;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;public class MeasureView extends View{public MeasureView(Context context) {super(context);// TODO Auto-generated constructor stub}public MeasureView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}public MeasureView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// TODO Auto-generated constructor stub}@Overrideprotected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){setMeasuredDimension(400,400);//指定宽高}else if(widthSpecMode == MeasureSpec.AT_MOST){setMeasuredDimension(400,heightSpecSize);}else if(heightSpecMode == MeasureSpec.AT_MOST){setMeasuredDimension(widthSpecSize,400);}}}

 

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="sunny.example.ahthreeviewmeasure.MainActivity" ><sunny.example.ahthreeviewmeasure.MeasureViewandroid:id="@+id/measureView"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#09acda" /></RelativeLayout>


MainActivity.java

 

package sunny.example.ahthreeviewmeasure;import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//MeasureView mView = (MeasureView)findViewById(R.id.measureView);}}

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用LayoutParams设置布局

1、public static class ViewGroup.LayoutParams extends Objectjava.lang.Object ↳android.view.ViewGroup.LayoutParams Class Overview LayoutParams are used by views to tell their parents how they want to be laid out. LayoutParams是ViewGroup的一个内部类, 每个…

记录意外的开关选项

Java开发人员可以做很多事情来使自己的生活以及维护该代码的其他人的生活更加轻松。 在本文中&#xff0c;我将探讨开发人员可以采用的一种非常简单的方法&#xff0c;以使每个人都更轻松。 这篇文章的要点对于每个阅读它的人来说似乎都是显而易见的&#xff0c;但是我发现这样…

View的绘制

1、当测量好一个View后就可以重写onDraw()方法&#xff0c;并在Canvas对象上绘制所需的图形。 public class Canvas extends Objectjava.lang.Object ↳android.graphics.Canvas Public ConstructorsCanvas()Construct an empty raster canvas.Canvas(Bitmap bitmap)Construc…

ViewGroup的测量及绘制

1、ViewGroup的测量public abstract class ViewGroup extends Viewimplements ViewManager ViewParent java.lang.Object ↳android.view.View ↳android.view.ViewGroup Class Overview A ViewGroup is a special view that can contain other views (called children.)…

ejb 2.0 3.0_定义EJB 3.1视图(本地,远程,无接口)

ejb 2.0 3.0这篇文章将讨论使用批注定义EJB视图的可能方法&#xff08;最后我将只提到使用EJB部署描述符&#xff09;。我将重点介绍最新的EJB 3.1视图&#xff0c;这些视图将省略旧的本地&#xff0c;远程和本地接口。 因此&#xff0c;我们可以选择&#xff1a; 远程业务界面…

View的事件分发机制简述

要分析的对象就是MotionEvent&#xff0c;点击事件的事件分发其实就是对MotionEvent事件的分发过程&#xff0c;当MotionEvent产生后&#xff0c;系统需要把这个事件传递给一个具体的View&#xff0c;这个传递过程就是分发过程。这个过程由三个很重要的方法共同完成&#xff1a…

ListView的使用用ViewHolder提升效率

public class ListView extends AbsListViewjava.lang.Object ↳android.view.View ↳android.view.ViewGroup ↳android.widget.AdapterView<T extends android.widget.Adapter> ↳android.widget.AbsListView ↳android.widget.ListView Class Ove…

通过投影增强数据模型

介绍 数据模型可能很棘手。 建模可能会更加困难。 有时候&#xff0c;应该放入数据库表中的信息不一定是我们要在每段代码中使用的信息。 和其他许多次一样&#xff0c;Spring来了。 一个称为投影的小功能可以帮助我们在普通界面中仅用几行数据映射数据。 在本文中&#xff0…

ListView常用属性、方法

1、设置item间分割线&#xff0c;分割线高度 android:divider"android:color/darker_gray" android:dividerHeight"10dp" 分割线不仅仅可以设置为一个颜色&#xff0c;也可以设置为一个图片资源。 分割线设置为透明&#xff1a; android:divider"…

具有弹性效果的ListView

Android默认的ListView在滚动到顶端或底端&#xff0c;没有很好的提示&#xff0c;下面通过源码来实现弹性效果。 ListView中有一个控制滑动到边缘的处理方法&#xff1a; protected boolean overScrollBy(int deltaX, int deltaY,int scrollX, int scrollY,int scrollRangeX,…

rememberme多久_使用Spring Security添加RememberMe身份验证

rememberme多久我在“ 向Jiwhiz博客添加社交登录”一文中提到&#xff0c;RememberMe功能不适用于Spring Social Security。 好吧&#xff0c;这是因为该应用程序现在不通过用户名和密码对用户进行身份验证&#xff0c;并且完全依靠社交网站&#xff08;例如Google&#xff0c;…

Java 9:对可选的增强

之前 &#xff0c;我写过Java 8中引入的Optional类&#xff0c;该类用于对可能不存在的值进行建模并减少可能引发NullPointerException的位置的数量。 Java 9向Optional添加了三个新方法&#xff1a; 1. ifPresentOrElse 新ifPresentOrElse方法允许你执行一个动作&#xff0c…

电脑还原Mac地址

之前修改过电脑Mac&#xff0c;现在与手机Mac冲突&#xff0c;导致手机无法连接校园网。 控制面板——》打开网络和共享中心——》选择更改适配器设置 本地连接——》右键选择属性 上图选择配置 高级——》在下拉菜单中选择网络地址——》右边选为“不存在” 之后本地连接会自…

聊天ListView使用ViewHolder

聊天界面会展示至少两种布局&#xff0c;即收到消息和发送消息。这样一个ListView与平时使用的ListView的最大不同&#xff0c;在于它有两个不同的布局&#xff1a;收到的布局和发送的布局。需要利用Adapter实现这样的效果。即需要在获取布局的时候判断该获取哪个布局。 public…

动态改变ListView布局

在getView()时&#xff0c;通过判断选择加载不同的布局。 点击某个item的时候&#xff0c;变为foucus状态&#xff0c;其他的items还原。 下面用两个方法给item设置两个不同的布局。 //foucus状态&#xff0c;显示一个ImageViewprivate View addFocusView(int i) {ImageView…

jpa 关系拥有方_JPA:确定关系的归属方

jpa 关系拥有方使用Java Persistence API&#xff08;JPA&#xff09;时&#xff0c;通常需要在两个实体之间创建关系。 这些关系是通过使用外键在数据模型&#xff08;例如数据库&#xff09;中定义的&#xff0c;而在我们的对象模型&#xff08;例如Java&#xff09;中则使用…

JDBC连接备忘单

抽象 这是常见数据库的JDBC连接的快速参考。 我似乎必须大量查找此信息&#xff0c;因此我认为最好将所有参考资料放在一个地方。 德比 <dependency><groupId>org.apache.derby</groupId><artifactId>derbyclient</artifactId><version>1…

获取View坐标

滑动一个View&#xff0c;即移动一个View&#xff0c;改变其当前所处的位置&#xff0c;通过不断改变View的坐标实现滑动的效果。 1、Android坐标系&#xff1a;坐标原点在屏幕左上角。 public void getLocationOnScreen(int[] location) Computes the coordinates of this vi…

李宏毅 课程打包_按功能而不是按层打包课程

李宏毅 课程打包大多数企业Java应用程序在设计上都有一些相似之处。 这些应用程序的打包通常由它们使用的框架&#xff08;如Spring&#xff0c;EJB或Hibernate等&#xff09;驱动。或者&#xff0c;您可以按功能对打包进行分组。 像任何其他有关建模的项目一样&#xff0c;这也…

error inflating class binaryXML LayoutParams addRule()

报出异常的原因是由于少添加了构造方法&#xff0c;三个构造方法需要写完整&#xff0c;不能只写一个。参数为(Context, AttributeSet)&#xff0c;其中第二个参数用来将xml文件中的属性初始化。 自定义控件若需要在xml文件中使用&#xff0c;就必须重写带如上两个参数的构造方…