[Android分享] 使用触摸手势(六)
来源:互联网 发布:表格文字识别软件 编辑:程序博客网 时间:2024/05/20 16:40
原文链接:http://developer.android.com/training/gestures/viewgroup.html
在ViewGroup中处理触摸事件
在一个ViewGroup中处理事件必须要非常小心,因为通常一个ViewGroup都有子View,它们都是不同触摸事件的的对象。为了确保每一个View都能正确接收意图作用于它的触摸事件,覆盖onInterceptTouchEvent()方法。
在一个ViewGroup中拦截触摸事件
每当在ViewGroup表面上监听到一个触摸事件时,onInterceptTouchEvent()方法就会被调用,包括他子View的表面。如果onInterceptTouchEvent()返回true, MotionEvents将被拦截,意味着这些事件将不会被传递到其子View,而是父View的onTouchEvent()方法。
onInterceptTouchEvent()方法使得父View在其子View之前接收触摸事件。如果在父View的onInterceptTouchEvent()方法中返回true,之前处理触摸事件的子View将会收到一个ACTION_CANCEL,从那一个时刻开始,之后的事件将会发送到父View的onTouchEvent方法来处理。onInterceptTouchEvent()也能返回false,触摸事件将会顺着view层级到通常接收并处理这些触摸事件的目标view。
在下面的代码中,MyViewGroup类继承于ViewGroup。MyViewGroup包含大量的子view。如果你在一个子view上水平拖动手指,子view将不会再获得触摸事件,MyViewGroup将会处理这些触摸事件,是它的内容滑动。然而,如果你点击子view中的一个Button,或者在垂直方向滑动子view,父view将不会拦截这些触摸事件。在这些情况下,onInterceptTouchEvent()将返回false,MyViewGroup的onTouchEvent()方法将不会被调用。
代码片段,双击复制
注意ViewGroup也提供了一个requestDisallowInterceptTouchEvent()方法,当一个子View不想让其父View和祖先View在onInterceptTouchEvent()中拦截触摸事件时,会调用这个方法。
使用ViewConfiguration常量
能够使用ViewConfiguration类来访问一些Android系统使用的常量,例如距离、速度和时间。
“Touch slop”是当用户的触摸事件被解释为滑动需要移动的最小距离。
两个被ViewConfiguration常用的方法是getScaledMinimumFlingVelocity()和getScaledMaximumFlingVelocity()。这两个方法返回最小和最大速度来启动一个fling,单位是像素每秒。
代码片段,双击复制
扩展子视图的可触摸区域
Android提供了TouchDelegate类,使得父View能够扩展子View的触摸区域。当一个子View所占区域非常小,需要一个大的区域让用户操作时,这是非常有用的。如果需要缩小子View的触摸区域,也可以使用这种方式。
代码片段,双击复制
下面的代码做了以下一些事情:
1.获取父view,并在UI线程上post一个Runnable。这保证了父view在调用getHitRect()方法之前布局它的子视图。getHitRect()方法在父视图坐标系中获得子视图的矩形区域。
2.找到ImageButton子view并调用getHitRect()来获取子视图的可触摸区域。
3.扩展ImageButton的矩形边界。
4.实例化一个TouchDelegate,并将矩形区域和ImageButton子视图作为传递参数。
5.在父view上面设置TouchDelegate,则在扩咱区域上的触摸动作会传递到子视图。
父view将会代表ImageButton子view接受所有的触摸事件,如果触摸事件在子视图的扩展矩形中,则父view将会把触摸事件传递给子view去处理。
代码片段,双击复制
在ViewGroup中处理触摸事件
在一个ViewGroup中处理事件必须要非常小心,因为通常一个ViewGroup都有子View,它们都是不同触摸事件的的对象。为了确保每一个View都能正确接收意图作用于它的触摸事件,覆盖onInterceptTouchEvent()方法。
在一个ViewGroup中拦截触摸事件
每当在ViewGroup表面上监听到一个触摸事件时,onInterceptTouchEvent()方法就会被调用,包括他子View的表面。如果onInterceptTouchEvent()返回true, MotionEvents将被拦截,意味着这些事件将不会被传递到其子View,而是父View的onTouchEvent()方法。
onInterceptTouchEvent()方法使得父View在其子View之前接收触摸事件。如果在父View的onInterceptTouchEvent()方法中返回true,之前处理触摸事件的子View将会收到一个ACTION_CANCEL,从那一个时刻开始,之后的事件将会发送到父View的onTouchEvent方法来处理。onInterceptTouchEvent()也能返回false,触摸事件将会顺着view层级到通常接收并处理这些触摸事件的目标view。
在下面的代码中,MyViewGroup类继承于ViewGroup。MyViewGroup包含大量的子view。如果你在一个子view上水平拖动手指,子view将不会再获得触摸事件,MyViewGroup将会处理这些触摸事件,是它的内容滑动。然而,如果你点击子view中的一个Button,或者在垂直方向滑动子view,父view将不会拦截这些触摸事件。在这些情况下,onInterceptTouchEvent()将返回false,MyViewGroup的onTouchEvent()方法将不会被调用。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public
class
MyViewGroup
extends
ViewGroup {
private
int
mTouchSlop;
...
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
mTouchSlop = vc.getScaledTouchSlop();
...
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* scrolling there.
*/
final
int
action = MotionEventCompat.getActionMasked(ev);
// Always handle the case of the touch gesture being complete.
if
(action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
// Release the scroll.
mIsScrolling =
false
;
return
false
;
// Do not intercept touch event, let the child handle it
}
switch
(action) {
case
MotionEvent.ACTION_MOVE: {
if
(mIsScrolling) {
// We're currently scrolling, so yes, intercept the
// touch event!
return
true
;
}
// If the user has dragged her finger horizontally more than
// the touch slop, start the scroll
// left as an exercise for the reader
final
int
xDiff = calculateDistanceX(ev);
// Touch slop should be calculated using ViewConfiguration
// constants.
if
(xDiff > mTouchSlop) {
// Start scrolling!
mIsScrolling =
true
;
return
true
;
}
break
;
}
...
}
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
return
false
;
}
@Override
public
boolean
onTouchEvent(MotionEvent ev) {
// Here we actually handle the touch event (e.g. if the action is ACTION_MOVE,
// scroll this container).
// This method will only be called if the touch event was intercepted in
// onInterceptTouchEvent
...
}
}
注意ViewGroup也提供了一个requestDisallowInterceptTouchEvent()方法,当一个子View不想让其父View和祖先View在onInterceptTouchEvent()中拦截触摸事件时,会调用这个方法。
使用ViewConfiguration常量
能够使用ViewConfiguration类来访问一些Android系统使用的常量,例如距离、速度和时间。
“Touch slop”是当用户的触摸事件被解释为滑动需要移动的最小距离。
两个被ViewConfiguration常用的方法是getScaledMinimumFlingVelocity()和getScaledMaximumFlingVelocity()。这两个方法返回最小和最大速度来启动一个fling,单位是像素每秒。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
private
int
mSlop = vc.getScaledTouchSlop();
private
int
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
private
int
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
...
case
MotionEvent.ACTION_MOVE: {
...
float
deltaX = motionEvent.getRawX() - mDownX;
if
(Math.abs(deltaX) > mSlop) {
// A swipe occurred, do something
}
...
case
MotionEvent.ACTION_UP: {
...
}
if
(mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity
&& velocityY < velocityX) {
// The criteria have been satisfied, do something
}
}
扩展子视图的可触摸区域
Android提供了TouchDelegate类,使得父View能够扩展子View的触摸区域。当一个子View所占区域非常小,需要一个大的区域让用户操作时,这是非常有用的。如果需要缩小子View的触摸区域,也可以使用这种方式。
01
02
03
04
05
06
07
08
09
10
11
12
<RelativeLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/parent_layout"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
tools:context=
".MainActivity"
>
<ImageButton android:id=
"@+id/button"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:background=
"@null"
android:src=
"@drawable/icon"
/>
</RelativeLayout>
下面的代码做了以下一些事情:
1.获取父view,并在UI线程上post一个Runnable。这保证了父view在调用getHitRect()方法之前布局它的子视图。getHitRect()方法在父视图坐标系中获得子视图的矩形区域。
2.找到ImageButton子view并调用getHitRect()来获取子视图的可触摸区域。
3.扩展ImageButton的矩形边界。
4.实例化一个TouchDelegate,并将矩形区域和ImageButton子视图作为传递参数。
5.在父view上面设置TouchDelegate,则在扩咱区域上的触摸动作会传递到子视图。
父view将会代表ImageButton子view接受所有的触摸事件,如果触摸事件在子视图的扩展矩形中,则父view将会把触摸事件传递给子view去处理。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public
class
MainActivity
extends
Activity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the parent view
View parentView = findViewById(R.id.parent_layout);
parentView.post(
new
Runnable() {
// Post in the parent's message queue to make sure the parent
// lays out its children before you call getHitRect()
@Override
public
void
run() {
// The bounds for the delegate view (an ImageButton
// in this example)
Rect delegateArea =
new
Rect();
ImageButton myButton = (ImageButton) findViewById(R.id.button);
myButton.setEnabled(
true
);
myButton.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View view) {
Toast.makeText(MainActivity.
this
,
"Touch occurred within ImageButton touch region."
,
Toast.LENGTH_SHORT).show();
}
});
// The hit rectangle for the ImageButton
myButton.getHitRect(delegateArea);
// Extend the touch area of the ImageButton beyond its bounds
// on the right and bottom.
delegateArea.right +=
100
;
delegateArea.bottom +=
100
;
// Instantiate a TouchDelegate.
// "delegateArea" is the bounds in local coordinates of
// the containing view to be mapped to the delegate view.
// "myButton" is the child view that should receive motion
// events.
TouchDelegate touchDelegate =
new
TouchDelegate(delegateArea,
myButton);
// Sets the TouchDelegate on the parent view, such that touches
// within the touch delegate bounds are routed to the child.
if
(View.
class
.isInstance(myButton.getParent())) {
((View) myButton.getParent()).setTouchDelegate(touchDelegate);
}
}
});
}
}
- [Android分享] 使用触摸手势(六)
- [Android分享] 使用触摸手势(一)
- [Android分享] 使用触摸手势(二)
- [Android分享] 使用触摸手势(四)
- [Android分享] 使用触摸手势(五)
- 手势识别(六)调节触摸到视图的传递
- Android 手势&触摸事件
- Android 手势&触摸事件
- android 触摸手势 OnGestureListener
- Android 手势&触摸事件
- Android 手势&触摸事件
- Android 手势&触摸事件
- Android 手势&触摸事件
- Android触摸手势
- Android之触摸手势检测GestureDetector使用详解
- Android 手势&触摸事件。手势各种状态
- Android ViewFlipper 手势触摸案例
- Android ViewFlipper 手势触摸案例
- Android程序的安全系统 apk获得root权限
- linux下tar.gz、tar、bz2、zip等解压缩、压缩命令小结
- 怎么查看使用80端口的进程
- 坐标下降与梯度下降
- 二叉查找树(二叉排序树)的详细实现
- [Android分享] 使用触摸手势(六)
- poj3621 Sightseeing Cows bellman-ford 判负权环
- Youzi2D推出开源HTML5游戏加速引擎
- 本地queue的使用
- 新浪 、优酷视频代码自动播放
- 认识smack中的基本对象 - PacketCollector对象
- 推荐一个制作ios图标的网站
- 设置UIButton上字体的对齐方式
- mysql select into使用