*
* 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 for widgets, which are * used to create interactive UI components (buttons, text fields, etc.). The * {@link android.view.ViewGroup} subclass is the base class for layouts, which * are invisible containers that hold other Views (or other ViewGroups) and define * their layout properties. *
该段文字说明View是1、一个占有矩形屏幕区域的视图 2、负责视图的绘制以及事件处理。 ViewGroup作为View的子类,是进行layout的基类。它是一个不可见容器,它可以包含其它的视图(View)以及视图组(ViewGroup),并且定义这些视图和视图组的Layout属性
*
* All of the views in a window are arranged in a single tree. You can add views * either from code or by specifying a tree of views in one or more XML layout * files. There are many specialized subclasses of views that act as controls or * are capable of displaying text, images, or other content. *
所有的view都被指定在Window窗口内,并且以单个树结构存在,我们添加View通过代码添加 或者在一个或多个XML的Layout文件里面添加一个视图树。系统提供了很多子类视图用于控制或者显示文字、图片或者其他内容。
*
* Once you have created a tree of views, there are typically a few types of * common operations you may wish to perform: *
*
*- Set properties: for example setting the text of a * {@link android.widget.TextView}. The available properties and the methods * that set them will vary among the different subclasses of views. Note that * properties that are known at build time can be set in the XML layout * files.
*- Set focus: The framework will handle moving focus in * response to user input. To force focus to a specific view, call * {@link #requestFocus}.
*- Set up listeners: Views allow clients to set listeners * that will be notified when something interesting happens to the view. For * example, all views will let you set a listener to be notified when the view * gains or loses focus. You can register such a listener using * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. * Other view subclasses offer more specialized listeners. For example, a Button * exposes a listener to notify clients when the button is clicked.
*- Set visibility: You can hide or show views using * {@link #setVisibility(int)}.
*
一旦创建了一个视图树,便会有一些我们希望执行的共有的操作:
1、设置属性;这些可使用的属性,可以在不同的子类视图中产生不同的效果,这些属性在XML的layout布局文件里面被设置,在编译器被系统识别出来后进行加载
2、设置焦点;framework层将处理焦点的移动来响应用户的输入,如果要强制聚焦一个指定视图,可以使用requestFocus()方法
3、建立监听器;视图允许客户端设置监听器进行通知,当有些事件发生时,来告知视图。
4、设置可见性;使用setVisibility()方法进行视图的显示与不显示或者隐藏
*
* Note: The Android framework is responsible for measuring, laying out and * drawing views. You should not call methods that perform these actions on * views yourself unless you are actually implementing a * {@link android.view.ViewGroup}. *
视图的布局、测量、绘制是Android的framework层进行执行的,我们不应该回调布局、测量、绘制操作,在我们自己的视图上,除非我们继承的是ViewGroup类。
To implement a custom view, you will usually begin by providing overrides for * some of the standard methods that the framework calls on all views. You do * not need to override all of these methods. In fact, you can start by just * overriding {@link #onDraw(android.graphics.Canvas)}.
当我们需要自定义视图时,只需要使用系统提供的重载方法即可。,不需要全部使用,如上图提供的这些方法,是使用最多的
IDs
Views may have an integer id associated with them. These ids are typically assigned in the layout XML files, and are used to find specific views within the view tree. A common pattern is to:
Define a Button in the layout file and assign it a unique ID.
From the onCreate method of an Activity, find the Button
Button myButton = findViewById(R.id.my_button);
View IDs need not be unique throughout the tree, but it is good practice to ensure that they are at least unique within the part of the tree you are searching.
视图可以使用一个integer类型的id关联他们,这个id被指定在XML布局文件中,通过使用他们,可以在视图树内,找到他们指定的视图
Position
The geometry of a view is that of a rectangle. A view has a location, expressed as a pair of left and top coordinates, and two dimensions, expressed as a width and a height. The unit for location and dimensions is the pixel.
It is possible to retrieve the location of a view by invoking the methods {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent.
In addition, several convenience methods are offered to avoid unnecessary computations, namely {@link #getRight()} and {@link #getBottom()}. These methods return the coordinates of the right and bottom edges of the rectangle representing the view. For instance, calling {@link #getRight()} is similar to the following computation: getLeft() + getWidth()
视图是一个矩形图,视图都有位置, 表示为一对左坐标和一对右坐标,和2个尺寸。表示为一个宽和一个高。位置和尺寸的单位是像素
我们可以通过getLeft和getTop方法获取到视图的位置,getLeft()方法返回的是矩形视图左边或X的坐标,getTop()方法返回的是矩形视图顶部或Y的坐标,这些方法返回的视图是相对于父视图的位置。
除此之外,还有一些方便的方法被提供,以避免不必要的计算,getRight()、getBottom()。这些方法返回坐标的右和底边缘的矩形坐标,其中getRight()方法和 getLeft()+getWidth()的值是一样的
Size, padding and margins
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling {@link #getMeasuredWidth()} and {@link #getMeasuredHeight()}.
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling {@link #getWidth()} and {@link #getHeight()}.
To measure its dimensions, a view takes into account its padding. The padding is expressed in pixels for the left, top, right and bottom parts of the view. Padding can be used to offset the content of the view by a specific amount of pixels. For instance, a left padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding can be set using the {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, {@link #getPaddingEnd()}.
Even though a view can define a padding, it does not provide any support for margins. However, view groups provide such a support. Refer to {@link android.view.ViewGroup} and {@link android.view.ViewGroup.MarginLayoutParams} for further information.
大小,内边距和外边距
大小:一个视图的大小表示为一个宽和高,一个视图准确的说占有2对宽高值。 第一对:测量的宽和测量的高,这个尺寸定义了一个视图在父视图中的大小,他们获取的方法为getMeasuredWidth()和getMeasuredHeight()
第二对:仅仅是宽和高,有时也被称为绘制宽和绘制高,这个尺寸定义了视图在屏幕上准确的大小,在绘制时和布局完之后,这些值是有的,但是却是不必要的,他们不同于测量宽和测量高,他们获取的方式为getWidth()和getHeight()方法
内边距:测量视图尺寸时,我们会考虑他的内边距,内边距用像素表示,是视图的左、上、右、下的一部分。内边距可以用来偏移视图内容,通过一个指定大小的像数值例如setPadding(int, int, int, int)、setPaddingRelative(int, int, int, int)、getPaddingLeft()等等
外边距:即使一个视图能够定义一个内边距,但是它不能提供任何外边距的支持,然而视图组提供了这样的引用,详情需要看ViewGroup类以及android.view.ViewGroup.MarginLayoutParams的内容。
Layout
Layout is a two pass process: a measure pass and a layout pass. The measuring pass is implemented in {@link #measure(int, int)} and is a top-down traversal of the view tree. Each view pushes dimension specifications down the tree during the recursion. At the end of the measure pass, every view has stored its measurements. The second pass happens in {@link #layout(int,int,int,int)} and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass.
When a view's measure() method returns, its {@link #getMeasuredWidth()} and {@link #getMeasuredHeight()} values must be set, along with those for all of that view's descendants. A view's measured width and measured height values must respect the constraints imposed by the view's parents. This guarantees that at the end of the measure pass, all parents accept all of their children's measurements. A parent view may call measure() more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call measure() on them again with actual numbers if the sum of all the children's unconstrained sizes is too big or too small.
The measure pass uses two classes to communicate dimensions. The {@link MeasureSpec} class is used by views to tell their parents how they want to be measured and positioned. The base LayoutParams class just describes how big the view wants to be for both width and height. For each dimension, it can specify one of:
an exact number
MATCH_PARENT, which means the view wants to be as big as its parent (minus padding)
WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding).
There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.
MeasureSpecs are used to push requirements down the tree from parent to child. A MeasureSpec can be in one of three modes:
UNSPECIFIED: This is used by a parent to determine the desired dimension of a child view. For example, a LinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how tall the child view wants to be given a width of 240 pixels.
EXACTLY: This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
AT_MOST: This is used by the parent to impose a maximum size on the child. The child must guarantee that it and all of its descendants will fit within this size.
To initiate a layout, call {@link #requestLayout}. This method is typically called by a view on itself when it believes that is can no longer fit within its current bounds.
布局是一个双传递过程:测量传递过程与布局传递过程。测量传递过程的实现使用 measure(int,int)方法,他是一个自上而下的视图树的遍历,在递归期间,每个视图都将尺寸规范向下推送到视图树中,在测量过程完成时,每一个视图就都存储了他们的测量值 第二个传递过程发生在 布局(layout(int,int,int,int))方法中,也是一个自上而下的视图树遍历。在传递期间,每一个父视图的职责是对他们自己所有的子视图布局,其中视图大小使用的是在测量传递过程中计算出来的尺寸大小。
当一个视图的measure()方法返回时,它的getMeasuredWidth()和getMeasuredHeight()的值必须被设置,同时被设置的还有子节点中的视图。一个视图的测量宽和测量高的值必须遵循父视图的约束,这保证了在测量传递结束时,所有的父视图接受了他们子视图的测量。一个父视图可能会在他们的子视图上measure()超过一次,例如:父视图可能测量了他的每一个子视图通过unspecified尺寸,以便于找出他们想要的尺寸,随后再次回调measure()方法使用准确的数值。
测量传递使用2个类去传递尺寸: MeasureSpec和LayoutParams
MeasureSpec:被视图用来告诉他们的父视图,他们想要测量的值和位置是怎样的,
LayoutParams:仅仅描述他想要的视图的宽和高想要多大
对于每一个尺寸来说,视图能够指定的值为:
1、一个确定的值
2、MATCH_PARENT 意味着这个视图想要找父视图要最大的尺寸
3、WRAP_CONTENT 表明这个视图仅仅想要足够大的尺寸去包裹住他的内容就可以了
ViewGroup的子类有不同的LayoutParams子类。
MeasureSpecs被用来将需求由父类推向子类,一个MeasureSpec有3种模式:
1、UNSPECIFIED 被父类用来决定子视图所期望的尺寸,例如:LinearLayout 回调measure(),在他的子类,使用UNSPECIFIED高度和一个EXACTLY 240 宽度用于找出子视图在宽度为240像素时的高度需要多少
2、EXACTLY 被父类用来强制指定一个准确的大小。子类必须使用这个大小,以保证所有他的子节点都符合这个大小
3、AT_MOST 被父类用来强制指定一个最大尺寸给子类,这个子类必须保证它和他的子节点都符合这个大小
去初始化一个布局,调用requestLayout(),这个方法在认为它不在适合它当前的布局边界时被它自身调用。
Drawing
Drawing is handled by walking the tree and recording the drawing commands of any View that needs to update. After this, the drawing commands of the entire tree are issued to screen, clipped to the newly damaged area.
The tree is largely recorded and drawn in order, with parents drawn before (i.e., behind) their children, with siblings drawn in the order they appear in the tree. If you set a background drawable for a View, then the View will draw it before calling back to its onDraw() method. The child drawing order can be overridden with {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order} in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
To force a view to draw, call {@link #invalidate()}.
绘图是通过遍历树并记录需要更新的任何视图的绘图命令来处理的,在此之后,整棵树的绘图命令被发送到屏幕上,剪贴到新损坏的区域
这棵视图树大部分是按顺序来纪录和绘制,在父节点绘制之后,他们的子节点与同级节点绘制是按照他们出现在视图树上的顺序来进行绘制。如果你设置一个背景图片给一个视图,随后在回调onDraw()方法之前,将绘制背景。子节点绘制顺序会被覆盖{通过 ViewGroup#setChildrenDrawingOrderEnabled(boolean) 自定义子节点的绘制顺序}在视图组中,以及设置 {通过 #setZ(float) 设置Z轴数值} 在视图上
如果要强制一个视图去绘制,可以调用 invalidate();
Event Handling and Threading
The basic cycle of a view is as follows:
1、An event comes in and is dispatched to the appropriate view. The view handles the event and notifies any listeners.
2、If in the course of processing the event, the view's bounds may need to be changed, the view will call {@link #requestLayout()}.
3、Similarly, if in the course of processing the event the view's appearance may need to be changed, the view will call {@link #invalidate()}.
4、If either {@link #requestLayout()} or {@link #invalidate()} were called, the framework will take care of measuring, laying out, and drawing the tree as appropriate.
Note: The entire view tree is single threaded. You must always be on the UI thread when calling any method on any view. If you are doing work on other threads and want to update the state of a view from that thread, you should use a {@link Handler}.
事件处理和线程
视图的基本循环如下:
1、一个事件带有和被分配到合适的视图,这个视图会处理这个事件并通知监听者
2、如果在处理事件的过程中,这个视图的边界被改变了,这个视图将调用 requestLayout()
3、同样的,如果在处理事件的过程中,视图的外观可能需要更改,这个视图将调用 invalidate()
4、如果调用了requestLayout或者invalidate,framework将负责测量,布局,和绘制视图树在适当的时候
注意:如果整棵视图树是单一线程,必须保证一直都在主线程中,在回调任何视图的任何方法时。如果你在其他线程上做了操作,并且想在这个线程中更新视图状态,必须使用 Handler类操作
Focus Handling
The framework will handle routine focus movement in response to user input. This includes changing the focus as views are removed or hidden, or as new views become available. Views indicate their willingness to take focus through the {@link #isFocusable} method. To change whether a view can take focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) views indicate whether they still would like focus via {@link #isFocusableInTouchMode} and can change this via {@link #setFocusableInTouchMode(boolean)}.
Focus movement is based on an algorithm which finds the nearest neighbor in a given direction. In rare cases, the default algorithm may not match the intended behavior of the developer. In these situations, you can provide explicit overrides by using these XML attributes in the layout file:
nextFocusDown
nextFocusLeft
nextFocusRight
nextFocusUp
To get a particular view to take focus, call {@link #requestFocus()}.
集中处理
franework将处理日常焦点移动以实现用户的输入,这里面包含视图的移除、隐藏、或新视图可用时 导致的焦点变更 视图表示他们愿意通过isFocusable()方法获取焦点,一个视图是否能够获取焦点并进行更改,通过调用setFocusable(boolean)方法。在触摸模式下,视图表明是否他们仍然希望通过isFocusableInTouchMode来获取焦点和通过setFocusableInTouchMode(boolean)来修改焦点
焦点的移动是基于 在给定的方向上找到最近邻居的算法。在罕见情况下,这种默认的算法可能与开发者的预期行为不匹配,在这种情形下, 通过在这个布局文件中使用这些XML属性,你能够提供显示重写。
下一个下边的焦点
下一个左边的焦点
下一个右边的焦点
下一个上边的焦点
要获取指定视图的焦点,调用requestFocus()
Touch Mode
When a user is navigating a user interface via directional keys such as a D-pad, it is necessary to give focus to actionable items such as buttons so the user can see what will take input. If the device has touch capabilities, however, and the user begins interacting with the interface by touching it, it is no longer necessary to always highlight, or give focus to, a particular view. This motivates a mode for interaction named 'touch mode'.
For a touch capable device, once the user touches the screen, the device will enter touch mode. From this point onward, only views for which {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. Other views that are touchable, like buttons, will not take focus when touched; they will only fire the on click listeners.
Any time a user hits a directional key, such as a D-pad direction, the view device will exit touch mode, and find a view to take focus, so that the user may resume interacting with the user interface without touching the screen again.
The touch mode state is maintained across {@link android.app.Activity}s. Call {@link #isInTouchMode} to see whether the device is currently in touch mode.
当用户通过D-pad等方向键导航用户界面时,如果设备有触摸功能的话,有必要将焦点放在可操作的条目上,比如按钮,这样用户就可以看到输入的内容,然而,用户通过触摸界面开始与之交互,不再需要总是高亮,或者给焦点,一个指定的视图,这激发了一种名为“触摸模式”的交互模式。
对于一个有触摸功能的设备,一旦用户触摸了屏幕,这个设备将进入触摸模式,从这个点开始,只有View的isFocusableInTouchMode()方法为真时,才是可调焦的,比如文本编辑控件其他可触摸的视图,比如button,在触摸时无法获取焦点,他们只会出发点击监听器
任何时候,用户点击了一个方向键,比如D-pad方向,视图设备将退出触摸模式,并且找到一个视图去获取焦点,这样用户可以在不接触屏幕的情况下继续与用户界面进行交互。
触摸模式的状态是通过Activity进行维持的,调用 isInTouchMode()去获取是否设备当前处于触摸模式下。
Scrolling
The framework provides basic support for views that wish to internally scroll their content. This includes keeping track of the X and Y scroll offset as well as mechanisms for drawing scrollbars. See {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and {@link #awakenScrollBars()} for more details.
滚动
framework为希望内部滚动他们内容的视图提供了基本支持,这包括跟踪X和Y滚动偏移量以及绘制滚动条的机制。具体可以看 scrollBy(int,int)方法、scrollTo(int,int)方法、awakenScrollBars() 方法。
Tags
Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure.
Tags may be specified with character sequence values in layout XML as either a single tag using the {@link android.R.styleable#View_tag android:tag} attribute or multiple tags using the {@code } child element:
android:tag="@string/mytag_value" /> android:value="@string/mytag_value" />
Tags may also be specified with arbitrary objects from code using {@link #setTag(Object)} or {@link #setTag(int, Object)}.
不像IDs,标签不是用来定义视图的,标签本质上是能够关联到视图的一条额外的信息,他们常常被用来在视图中存放有关视图的数据,而不是将他们放在单独的结构当中
标签可以使用layout的XML中的字符序列值来指定,也可以使用单个{android.R.styleable#View_tag android:tag}属性,多个标签使用下面这段代码:
android:tag="@string/mytag_value" /> android:value="@string/mytag_value" />
标签也可以使用代码中任意的object来指定 setTag(Object) 或者setTag(int ,Object).
Themes
By default, Views are created using the theme of the Context object supplied to their constructor; however, a different theme may be specified by using the {@link android.R.styleable#View_theme android:theme} attribute in layout XML or by passing a {@link ContextThemeWrapper} to the constructor from code.
When the {@link android.R.styleable#View_theme android:theme} attribute is used in XML, the specified theme is applied on top of the inflation context's theme (see {@link LayoutInflater}) and used for the view itself as well as any child elements.
In the following example, both views will be created using the Material dark color scheme; however, because an overlay theme is used which only defines a subset of attributes, the value of {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on the inflation context's theme (e.g. the Activity theme) will be preserved.
... android:theme="@android:theme/ThemeOverlay.Material.Dark">
主题
默认情况下, 视图使用上下文类提供给他们的构造方法的主题来创建,然而,一个不同的主题可以在布局XML通过使用{android.R.styleable#View_theme android:theme}属性指定或者通过{@link ContextThemeWrapper} 的构造方法使用代码进行指定
当使用第一种方式时,指定的主题应用于顶部填充的上下文主题中(LayoutInflater) 和 用于视图本身以及任何子元素
在下面的例子中,2个视图将使用 Material dark 颜色方案进行创建,然而,因为覆盖主题只定义了属性的子集,定义在inflation上下文的主题 android.R.styleable#Theme_colorAccent android:colorAccent的值将被保留
Properties
The View class exposes an {@link #ALPHA} property, as well as several transform-related properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are available both in the {@link Property} form as well as in similarly-named setter/getter methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can be used to set persistent state associated with these rendering-related properties on the view. The properties and methods can also be used in conjunction with {@link android.animation.Animator Animator}-based animations, described more in the Animation section.
属性
视图类公开一个ALPHA属性,以及几个与转换相关的属性,例如{TRANSLATION_X}和{TRANSLATION_Y}。这些属性既可以在{Property}表单中使用,也可以在名称类似的setter/getter方法中使用(例如{setAlpha(float)}用于{ALPHA})。这些属性可用于在视图中设置与这些呈现相关属性相关联的持久状态。属性和方法也可以与{android.animation结合使用。基于Animator}的动画,更多介绍在Anim中
Animation
Starting with Android 3.0, the preferred way of animating views is to use the {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 {@link android.view.animation.Animation Animation}-based classes, which instead animate only how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class makes animating these View properties particularly easy and efficient.
Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. You can attach an {@link Animation} object to a view using {@link #setAnimation(Animation)} or {@link #startAnimation(Animation)}. The animation can alter the scale, rotation, translation and alpha of a view over time. If the animation is attached to a view that has children, the animation will affect the entire subtree rooted by that node. When an animation is started, the framework will take care of redrawing the appropriate views until the animation completes.
动画
从3.0开始,优先使用的视图动画是 android.animation包里面的API,这些 android.animation.Animator Animator ,基于更改视图类的实际属性,比如{setAlpha(float) alpha} 和 { setTranslationX(float) translationX},这个行为与3.0{android.view.animation.Animation Animation}形成了对比,3.0之前它只对视图在显示器上的绘制方式进行动画。特别是 ViewPropertyAnimator 类使动画这些视图属性特别容易和有效。
作为选择,你能使用3.0之前的动画类来动画视图的渲染。你能绑定一个Animation类给视图使用setAnimation(Animation)或者startAnimation(Animation)这个动画随时间的推移能改变大小,旋转、位移、和透明度。如果动画绑定到一个有子类的视图中时,这个动画将影响整个子视图树通过那个节点。当一个动画开始后,framework层将负责重新绘制适当的视图,直到动画完成
Security
Sometimes it is essential that an application be able to verify that an action is being performed with the full knowledge and consent of the user, such as granting a permission request, making a purchase or clicking on an advertisement. Unfortunately, a malicious application could try to spoof the user into performing these actions, unaware, by concealing the intended purpose of the view. As a remedy, the framework offers a touch filtering mechanism that can be used to improve the security of views that provide access to sensitive functionality.
To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework will discard touches that are received whenever the view's window is obscured by another visible window. As a result, the view will not receive touches whenever a toast, dialog or other window appears above the view's window.
For more fine-grained control over security, consider overriding the {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
安全
有时,应用程序必须能够在用户完全知情和同意的情况下验证正在执行的操作,比如授予权限请求,购买或点击广告。不幸的是,恶意应用程序可能试图欺骗用户来执行这些操作,不知道的,通过隐藏视图的预期目的。作为补救措施,该框架提供了一种触摸过滤机制,可用于改进提供敏感功能访问的视图的安全性。
启用触摸过滤,调用setFilterTouchesWhenObscured(boolean)或者设置 android:filterTouchesWhenObscured 布局属性为true。启用时,当视图窗口被另一个可见窗口遮挡时,框架将丢弃接收到的触摸。因此,当吐司、对话框或其他窗口出现在视图窗口上方时,视图将不会接收触摸。
为了对安全性进行更细粒度的控制,考虑重载onFilterTouchEventForSecurity(MotionEvent) 方法去实现你自己的安全策略,具体看MotionEvent#FLAG_WINDOW_IS_OBSCURED