JAVA自定义一个Button,重写了onTouchEvent 方法,出现的问题。

JAVA自定义一个Button,重写了onTouchEvent 方法,出现的问题。,第1张

因为你重写了ontouchevent,而click或者longclick都是根据touch的motion来判断的

所以longclick不生效

基本思路:

1,自行判断,例如action down开始计时,当action up到来时,如果持续超过一定时间(比如1秒),并且move的范围小于一定阈值,认定为一次long click

2,使用gesture detector类判断手势

这里只针对lua

1为每个关心的事件注册回调函数

具体分为以下几种

1>单点触摸

注册函数为

ccHandlerEVENT_TOUCH_BEGAN = 40

ccHandlerEVENT_TOUCH_MOVED = 41

ccHandlerEVENT_TOUCH_ENDED = 42

ccHandlerEVENT_TOUCH_CANCELLED = 43

注册的时候必须通过

ccEventListenerTouchOneByOne:create() 创建listener

onTouchBegin/onTouchMove/onTouchEnd为自己注册的回调函数

代码如下:

local listener = ccEventListenerTouchOneByOne:create();

listener:registerScriptHandler(onTouchBegin,ccHandlerEVENT_TOUCH_BEGAN);

listener:registerScriptHandler(onTouchMove,ccHandlerEVENT_TOUCH_MOVED);

listener:registerScriptHandler(onTouchEnd,ccHandlerEVENT_TOUCH_ENDED);

2>多点点触摸

ccHandlerEVENT_TOUCHES_BEGAN = 44

ccHandlerEVENT_TOUCHES_MOVED = 45

ccHandlerEVENT_TOUCHES_ENDED = 46

ccHandlerEVENT_TOUCHES_CANCELLED = 47

注册的时候必须通过

ccEventListenerTouchAllAtOnce:create() 创建listener

onTouchesBegin/onTouchesMove/onTouchesEnd为自己注册的回调函数

代码如下:

local listener = ccEventListenerTouchAllAtOnce:create();

listener:registerScriptHandler(onTouchesBegin,ccHandlerEVENT_TOUCHES_BEGAN);

listener:registerScriptHandler(onTouchesMove,ccHandlerEVENT_TOUCHES_MOVED);

listener:registerScriptHandler(onTouchesEnd,ccHandlerEVENT_TOUCHES_ENDED);

最后通过下面的代码绑定listener

ccDirector:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener,_layer);

其中_layer是要需要事件的对象

前面 ccDirector:getInstance() 也可用换成_layer 或者 _layer的父节点的对象

这里有几点需要注意:

1onTouchesBegin/onTouchBegin 里面需要 return true,表示需要处理这个事件,不然不会掉用onTouchMove/onTouchEnd

2每个触摸函数都包含2个参数 以onTouchMove为例:

local function onTouchMove(touch,event)

end

touch / event 都是userdata(可以理解为C/LUA共有的数据 只要实现了对应的方法 C/Lua可以直接访问/赋值/调用函数 由C管理这块内存)

touch 是当前的触摸点 以下是它的方法

/ Returns the current touch location in OpenGL coordinates

@return The current touch location in OpenGL coordinates

/

Vec2 getLocation() const;

/ Returns the previous touch location in OpenGL coordinates

@return The previous touch location in OpenGL coordinates

/

Vec2 getPreviousLocation() const;

/ Returns the start touch location in OpenGL coordinates

@return The start touch location in OpenGL coordinates

/

Vec2 getStartLocation() const;

/ Returns the delta of 2 current touches locations in screen coordinates

@return The delta of 2 current touches locations in screen coordinates

/

Vec2 getDelta() const;

/ Returns the current touch location in screen coordinates

@return The current touch location in screen coordinates

/

Vec2 getLocationInView() const;

/ Returns the previous touch location in screen coordinates

@return The previous touch location in screen coordinates

/

Vec2 getPreviousLocationInView() const;

/ Returns the start touch location in screen coordinates

@return The start touch location in screen coordinates

/

如下面的代码可以在onTouchMove中直接获取 用户手指的移动距离

local dis = touch:getDelta()

print(disx,disy);

如果是多点触摸 touch是一个table

touch[1] touch[2] touch[3]…是触摸的对应点

event 可以表明表明

1当前用户点击了那个object (event:getCurrentTarget())

2当前是press/move/release的那个状态 (event:getEventCode())

ccEventCode =

{

BEGAN = 0,

MOVED = 1,

ENDED = 2,

CANCELLED = 3,

}

所以我们可以通过一个回调函数来判断当前是那个 *** 作 而不用写3个函数

示例代码

local function onTouchBegin(touch,event)

local p = touch:getLocation();

p = _layer:convertToNodeSpace(p);

print(px,py)

return true;

end

local function onTouchMove(touch,event)

end

local function onTouchEnd(touch,event)

end

local function onTouchesBegin(touch,event)

return true;

end

local function onTouchesMove(touch,event)

for i = 1,tablegetn(touch) do

local location = touch[i]:getLocation()

print(i,locationx,locationy)

end

end

local function onTouchesEnd(touch,event)

print("onTouchesEnd");

end

_layer = ccLayer:create();

_layer:setTouchEnabled(true)

local listener1 = ccEventListenerTouchOneByOne:create();

listener1:registerScriptHandler(onTouchBegin,ccHandlerEVENT_TOUCH_BEGAN);

listener1:registerScriptHandler(onTouchMove,ccHandlerEVENT_TOUCH_MOVED);

listener1:registerScriptHandler(onTouchEnd,ccHandlerEVENT_TOUCH_ENDED);

--多点触摸

-- local listener2 = ccEventListenerTouchAllAtOnce:create()

--listener2:registerScriptHandler(onTouchesBegin,ccHandlerEVENT_TOUCHES_BEGAN )

-- listener2:registerScriptHandler(onTouchesMove,ccHandlerEVENT_TOUCHES_MOVED )

-- listener2:registerScriptHandler(onTouchesEnd,ccHandlerEVENT_TOUCHES_MOVED )

local eventDispatcher = _layer:getEventDispatcher()

eventDispatcher:addEventListenerWithSceneGraphPriority(listener1, _layer)

--eventDispatcher:addEventListenerWithSceneGraphPriority(listener2, _layer)

2直接看代码

local function onTouchEvent(state , )

local args = {};

print(state);

for k,v in pairs(args[1]) do

print(k,v)

end

end

_layer:registerScriptTouchHandler(onTouchEvent,true,0,false);

@onTouchEvent 回调

@ture表示捕获要捕获多点触摸

@0优先级

@false 是否吞没触摸事件

如果是单点触摸 args[1] ->x,y,id

如果是多点触摸 args[1] ->x1,y1,id1,x2,y2,id2

这里cocos2dx-lua封装了 Layer:onTouch(callback, isMultiTouches, swallowTouches)

建议直接使用

这里如果你用cocos2dx-lua 的 lua-empty-test 做模板建立工程 有个bug

需要在 didFinishLaunchingWithOptions 添加代码

[eaglView setMultipleTouchEnabled:YES];

来打开多点触摸 这里我浪费了半天事件调试 FUCK

Android的事件处理的三种方法:

setOnClickListener,setOnLongClickListener、setOnTouchListener

注意:如果onTouchEvent方法return true,则单击事件和长摁事件不再执行;若onLongClick方法返回true,则单击事件不再处理。

需要定义继承组件的类,重写回调方法Touch方法执行时,先被Activity捕获,DispatchTouchEvent方法处理。return false,交给上层的onTouchEvent方法处理;return superdispatchTouchEvent(ev),则传递给最外层的View。

View用Dispatch方法处理,return false,由上层的onTouchEvent方法处理。如果返回superdispatchTouchEvent(ev),则本层的onInterceptTouchEvent拦截,如果拦截true,则拦截,false不拦截,传递给子View的DispatchTouchEvent处理。

常用的回调方法:onKeyDown,onKeyLongPress,onKeyUp,onTouchEvent,onTrackballEvent(轨迹球事件)监听和回调同时存在时,先调用监听。

流程模型图:

Event source 事件源

Event 事件

Event Listener 事件监听器

下面我们来看一下点击事件和触摸事件的监听三要素具体是那部分:

由于点击事件比较简单,系统已经帮我们处理了,并没有找到具体事件是哪个。

ViewOnClickListener 单击事件监听器必须实现的接⼝

ViewOnCreateContextMenuListener 创建上下⽂菜单事件

ViewOnFocusChangeListener 焦点改变事件

ViewOnKeyListener 按键事件监听器

ViewOnLongClickListener 长按事件监听器

ViewOnTouchListener 触摸屏事件监听器

⾸先,事件监听机制中由事件源,事件,事件监听器三类对象组成。

事件监听器处理流程:

在此以OnClickListener单击事件为例使用intent来实现页面的跳转

监听事件处理是事件源与事件监听器分开的而基于回调的事件处理UI组件不但是事件源,而且还是事件监听器,通过组件的相关回调方法处理对应的事件。

Ⅰ 自定义View类,继承自需要的View UI类。ex :自定义 MyButton按钮类 extends 基础Button类

Ⅱ 复写回调函数。ex:public boolean onTouchEvent(MotionEvent event)

每一个事件回调方法都会返回一个boolean值,①如果返回true:表示该事件已被处理,不再继续向外扩散,②如果返回false:表示事件继续向外扩散

而说到基于回调就离不开监听机制

几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于表示该处理方法是否能完全处理该事件。

如果处理事件的回调方法返回true,表明该处理方法已经完全处理改事件,该事件不会传播出去。

如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件会传播出去。

对于基于回调的时间传播而言,某组件上所发生的事件不仅会激发该组件上的回调方法,也会触发该组件所在Activity的回调方法——只要事件能传播到该Activity。

这里是在模拟器里进行的测试,这里按下键盘(而不是点击),会看到 logcat 中的输出,如下:

View类实现了KeyEventCallback接口中的一系列回调函数,因此,基于回调的事件处理机制通过自定义View来实现,自定义View时重写这些事件处理方法即可。

Handler是一个消息分发对象。

Handler是Android系统提供的一套用来更新UI的机制,也是一套消息处理机制,可以通过Handler发消息,也可以通过Handler处理消息。

在下面介绍Handler机制前,首先得了解以下几个概念:

在子线程执行完耗时 *** 作,当Handler发送消息时,将会调用 MessageQueueenqueueMessage ,向消息队列中添加消息。 当通过 Looperloop 开启循环后,会不断地从消息池中读取消息,即调用 MessageQueuenext , 然后调用目标Handler(即发送该消息的Handler)的 dispatchMessage 方法传递消息, 然后返回到Handler所在线程,目标Handler收到消息,调用 handleMessage 方法,接收消息,处理消息。

从上面可以看出,在子线程中创建Handler之前,要调用 Looperprepare() 方法,Handler创建后,还要调用 Looperloop() 方法。而前面我们在主线程创建Handler却不要这两个步骤,因为系统帮我们做了。

初始化Looper

从上可以看出,不能重复创建Looper,每个线程只能创建一个。创建Looper,并保存在 ThreadLocal 。其中ThreadLocal是线程本地存储区(Thread Local Storage,简称TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。

开启Looper

发送消息

post方法:

send方法:

在子线程中,进行耗时 *** 作,执行完 *** 作后,发送消息,通知主线程更新UI。

本文讲解了三个方面;Android事件机制;基于监听、基于回调以及Handler消息处理。还有许多没有讲解到的知识点,我总结在了整理的一套Android进阶笔记里面;需要学习进阶的同学可以前往获取: Frame Work源码解析手册 、 Android核心技术进阶手册、实战笔记、面试题纲资料

这说明你的onTouchEvent没跑到,一般都是先跑onTouchEvent,更具返回值确定是手势滑动还是,点击按下 *** 作

public boolean onTouch(View v, MotionEvent event) {// surfaceWidth = vgetWidth();// surfaceHeight = vgetHeight(); int pointCount = eventgetPointerCount();

if (pointCount == 1) { float x = eventgetX(); float y = eventgetY(); switch (eventgetAction()) {

case MotionEventACTION_DOWN:// mMode = ModeDOUBLE_CLICK; eventLoop(x, y, CommonCONTROL_MSG_DOWN); initX = x; initY = y; break; case MotionEventACTION_UP: // eventLoop(x, y, CommonCONTROL_MSG_UP);// historyX = x;// historyY = y; initX = 0; initY = 0;// mMode = ModeUNDEFINED; break; } return mGestureDetectoronTouchEvent(event); } else { return false; } }

public void eventLoop(float x, float y, int action) { if (action == CommonCONTROL_MSG_MOVE) { mViewDraw(x, y, initX, initY); } else if (action == CommonCONTROL_MSG_DOWN) { mViewClick(x, y); } }}

这个我以前写的一个方法,一直在用,里面有返回值的情况,你照着把对应的 *** 作写下就行

onTouch是View中OnTouchListener接口中的方法,处理View及其子类被touch是的事件处理。当然,前提是touch时间能够传递到指定的view。

onTouchEvent同样也是在view中定义的一个方法。处理传递到view 的手势事件。手势事件类型包括ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL四种事件。

一旦onTouchEvent方法被调用,并返回true则这个手势事件就结束了,并不会向下传递到子控件。

此方法返回false,则手势事件会向子控件传递;返回true,则调用onTouchEvent方法。

onTouchListener的接口的优先级是要高于onTouchEvent的,假若onTouchListener中的onTouch方法返回true,

表示此次事件已经被消费了,那onTouchEvent是接收不到消息的。

因为Button的performClick是利用onTouchEvent实现,假若onTouchEvent没有被调用到,那么Button的Click事件也无法响应。

onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。

假如onTouch方法返回false会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。

内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。

buttonsetOnTouchListener(new ViewOnTouchListener() {

    @Override

    public boolean onTouch(View view, MotionEvent motionEvent) {

        //按下 *** 作

        if(motionEventgetAction()==MotionEventACTION_UP){

            

        }

        //抬起 *** 作

        if(motionEventgetAction()==MotionEventACTION_UP){

            

        }

        //移动 *** 作

        if(motionEventgetAction()==MotionEventACTION_MOVE){

            

        }

        return false;

    }

});

以上就是关于JAVA自定义一个Button,重写了onTouchEvent 方法,出现的问题。全部的内容,包括:JAVA自定义一个Button,重写了onTouchEvent 方法,出现的问题。、用eventlistenertouchonebyone 创建的按钮在哪儿、Framework事件机制——手撕Android事件处理的三种方法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9485009.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存