【移动应用开发技术】怎么在Android中捕获点击事件范围_第1页
【移动应用开发技术】怎么在Android中捕获点击事件范围_第2页
【移动应用开发技术】怎么在Android中捕获点击事件范围_第3页
【移动应用开发技术】怎么在Android中捕获点击事件范围_第4页
【移动应用开发技术】怎么在Android中捕获点击事件范围_第5页
免费预览已结束,剩余2页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么在Android中捕获点击事件范围

今天就跟大家聊聊有关怎么在Android中捕获点击事件范围,可能很多人都不太了解,为了让大家更加了解,在下给大家总结了以下内容,希望大家根据这篇文章可以有所收获。View的Tween动画过程中点击事件的位置并不会因为动画位置的改变而改变,是因为在动画过程中layout的位置实际上没有变,因此曾经一度认为View的点击事件(其实不仅仅是点击事件,包括所有的触摸事件)触发的范围是该View在layout的时候指定的left,top,right,bottom。今天才发现不完全是这样的。一切都是因为平时看代码没有仔细一点所造成了对问题理解不全面。在这里记录一下发现问题到处理问题的过程。自定义这样一个ViewGroup,layout两个线性布局,左边的LinearLayout覆盖全屏幕,右面的LinearLayout在屏幕外面隐藏。然后观察在想做滑动的过程中,第二个LinearLayout显示出来的过程中,按钮Button和第二个线性布局的位置信息:可以看到,在向左滑第二个线性布显示出来的过程中,他的位置并没有变,这里指的是通过getLeft(),getTop(),getRight(),getBottom()获得的位置,也就是由layout决定的位置。既然位置并没有改变,那么这时候点击第二个线性布局和按钮点击事件也被响应了,就说明捕获点击事件的位置并不完全是在layout的位置。因为并没有将手伸到屏幕外面去点击…回头来看ViewGroup#dispatchTouchEvent方法在分发触摸事件的时候:for

(int

i

=

count

-

1;

i

>=

0;

i--)

{

final

View

child

=

children[i];

if

((child.mViewFlags

&

VISIBILITY_MASK)

==

VISIBLE

||

child.getAnimation()

!=

null)

{

child.getHitRect(frame);

if

(frame.contains(scrolledXInt,

scrolledYInt))

{

//

offset

the

event

to

the

view's

coordinate

system

final

float

xc

=

scrolledXFloat

-

child.mLeft;

final

float

yc

=

scrolledYFloat

-

child.mTop;

ev.setLocation(xc,

yc);

child.mPrivateFlags

&=

~CANCEL_NEXT_UP_EVENT;

if

(child.dispatchTouchEvent(ev))

{

//

Event

handled,

we

have

a

target

now.

mMotionTarget

=

child;

return

true;

}

}

}其中frame.contains(scrolledXInt,scrolledYInt)函数就是判断点(scrolledXInt,scrolledYInt)是不是在frame矩形里面。这个矩形frame是由child.getHitRect(frame);获得的:public

void

getHitRect(Rect

outRect)

{

outRect.set(mLeft,

mTop,

mRight,

mBottom);

}显然这个矩形就是由该子View的Layout的布局参数所决定的。但是scrolledXInt和scrolledYInt参数,并不是我们手指点击的位置:final

int

action

=

ev.getAction();

final

float

xf

=

ev.getX();

final

float

yf

=

ev.getY();

final

float

scrolledXFloat

=

xf

+

mScrollX;

final

float

scrolledYFloat

=

yf

+

mScrollY;

……

final

int

scrolledXInt

=

(int)

scrolledXFloat;

final

int

scrolledYInt

=

(int)

scrolledYFloat;可以看出,在判断这个点是否包含在子View内的时候,这个点不是手指所点击的坐标,而是手指点击的坐标加上了mScrollX和mScrollY,然后在判断是否在该子View的范围里面。现在思考向左滑动的过程中,虽然第二个线性布局的位置没有变,还是layout的参数位置,是:mLeft:720,mTop:0,mRight:1440,mBottom:1134。但是他的父View的mScrollX改变了,向左滑mScrollX大于0,这是用手点击第二个线性布局,手所点击的位置再加上mScrollX的值,这时就会落在了第二个线性布局的layout的范围里面。

测试代码:自定义MyViewGroup:public

class

MyViewGroup

extends

ViewGroup

{

public

static

final

String

TAG

=

"MyViewGroup";

private

int

childCount;

private

GestureDetector

detector;

private

Button

btn;

private

LinearLayout

ll2;

public

MyViewGroup(Context

context,

AttributeSet

attrs,

int

defStyle)

{

super(context,

attrs,

defStyle);

init(context);

}

public

MyViewGroup(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

init(context);

}

public

MyViewGroup(Context

context)

{

super(context);

init(context);

}

private

void

init(final

Context

context)

{

detector

=

new

GestureDetector(context,

new

MyOnGestureListener());

LinearLayout

ll1

=

new

LinearLayout(context);

ll1.setBackgroundColor(Color.BLUE);

ll2

=

new

LinearLayout(context);

ll2.setBackgroundColor(Color.RED);

btn

=

new

Button(context);

btn.setText("点击按钮");

ll2.addView(btn);

addView(ll1);

addView(ll2);

setOnTouchListener(new

MyTouchEvent());

ll2.setOnClickListener(new

OnClickListener()

{

@Override

public

void

onClick(View

v)

{

Toast.makeText(context,

"点击了线性布局2",

0).show();

}

});

btn.setOnClickListener(new

OnClickListener()

{

@Override

public

void

onClick(View

v)

{

Toast.makeText(context,

"点击了Button",

0).show();

}

});

}

@Override

protected

void

onMeasure(int

widthMeasureSpec,

int

heightMeasureSpec)

{

super.onMeasure(widthMeasureSpec,

heightMeasureSpec);

childCount

=

getChildCount();

for

(int

i

=

0;

i

<

childCount;

i++)

{

View

child

=

getChildAt(i);

child.measure(widthMeasureSpec,heightMeasureSpec);

}

}

@Override

protected

void

onLayout(boolean

changed,

int

l,

int

t,

int

r,

int

b)

{

for

(int

i

=

0;

i

<

childCount;

i++)

{

View

child

=

getChildAt(i);

child.layout(0+i*getWidth(),

0,

(i+1)*getWidth(),

getHeight());

}

}

private

class

MyTouchEvent

implements

View.OnTouchListener{

@Override

public

boolean

onTouch(View

v,

MotionEvent

event)

{

detector.onTouchEvent(event);

return

true;

}

}

private

class

MyOnGestureListener

extends

SimpleOnGestureListener{

@Override

public

boolean

onScroll(MotionEvent

e1,

MotionEvent

e2,

float

distanceX,

float

distanceY)

{

scrollBy((int)

distanceX,

0);

if

(getScrollX()%

10

==

0)

{

Log.i(TAG,

"Button左上右下位置:"

+

btn.getLeft()

+

"/"

+

btn.getTop()

+

"/"

+

btn.getRight()

+

"/"

+

btn.getBottom());

Log.i(TAG,

"线性布局2的左上右下位置:"

+

ll2.getLeft()

+

"/"

+

ll2.getTop()

+

"/"

+

ll2.getRight()

+

"/"

+

ll2.getBottom());

Log.i(TAG,

"MyViewGroup的mScrollX:"

+

getScrollX());

}

return

super.onScroll(e1,

e2,

distanceX,

distanceY);

}

}

}然后在Activity里面:public

class

MainAc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论