关于cocos2dx2.2.6hitWidget->onTouchEnded(pTouch,pEvent);异常和checked异常的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Andr
关于cocos2dx 2.2.6 hitWidget->onTouchEnded(pTouch, pEvent); 异常和checked异常的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android onInterceptTouchEvent 和 onTouchEvent、Android onTouchEvent事件中onTouch方法返回值(介绍)、Android Touch系统简介(二):实例详解onInterceptTouchEvent与onT、android – 处理触摸事件 – onInterceptTouchEvent和onTouchEvent等相关知识的信息别忘了在本站进行查找喔。
本文目录一览:- cocos2dx 2.2.6 hitWidget->onTouchEnded(pTouch, pEvent); 异常(checked异常)
- Android onInterceptTouchEvent 和 onTouchEvent
- Android onTouchEvent事件中onTouch方法返回值(介绍)
- Android Touch系统简介(二):实例详解onInterceptTouchEvent与onT
- android – 处理触摸事件 – onInterceptTouchEvent和onTouchEvent
cocos2dx 2.2.6 hitWidget->onTouchEnded(pTouch, pEvent); 异常(checked异常)
今天在调试控件A处于TOUCH_EVENT_BEGAN状态下的时候,控件A被删除或是主动删除,报hitWidget->onTouchEnded(pTouch,pEvent); 异常的问题。
查看源代码如下:
void TouchGroup::ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent) { ccArray* selectedWidgetArray = m_pSelectedWidgets->data; int length = selectedWidgetArray->num; for (int i=0; i<length; ++i) { Widget* hitWidget = (Widget*)(selectedWidgetArray->arr[0]); m_pSelectedWidgets->removeObject(hitWidget); hitWidget->onTouchEnded(pTouch,pEvent); } }
在使用hitWidget 的时候,被removeObject了,也就是说对象已经被释放了,
hitWidget的释放方式是autorelease,若没有其他的地方用到,也就会被彻底释放了。
使用retain 和 release把m_pSelectedWidgets->removeObject(hitWidget);
hitWidget->onTouchEnded(pTouch,pEvent);
包含起来,已保证在使用onTouchEnded的时候,hitWidget没有被释放。
包含起来,已保证在使用onTouchEnded的时候,hitWidget没有被释放。
void TouchGroup::ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent) { ccArray* selectedWidgetArray = m_pSelectedWidgets->data; int length = selectedWidgetArray->num; for (int i=0; i<length; ++i) { Widget* hitWidget = (Widget*)(selectedWidgetArray->arr[0]); hitWidget->retain(); <span>// add m_pSelectedWidgets->removeObject(hitWidget); hitWidget->onTouchEnded(pTouch,pEvent); hitWidget->release(); <span>// add } }
第二种方式(二)
把onTouchEnded和removeObject换一下位置
void TouchGroup::ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent) { ccArray* selectedWidgetArray = m_pSelectedWidgets->data; int length = selectedWidgetArray->num; for (int i=0; i<length; ++i) { Widget* hitWidget = (Widget*)(selectedWidgetArray->arr[0]); <span> </span> hitWidget->onTouchEnded(pTouch,pEvent); // modify m_pSelectedWidgets->removeObject(hitWidget); // modify } }
经过验证两种方式都能解决以上问题。
Android onInterceptTouchEvent 和 onTouchEvent
onInterceptTouchEvent方法是ViewGroup的方法,也就是所有的容器都将继承该方法。此方法设计的意图是为了在父容器将touch事件传递给子控件的时候可以统一控制。比如button就没有该方法,很明显,button不可能拥有子控件。
onTouchEvent方法是view的方法,当该控件接收到touch事件时,此方法会被执行。每一个touch事件总是从ACTION_DOWN事件开始,ACTION_UP结束。Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去
Touch事件几大原则:
1.如果在某个层级没有处理ACTION_DOWN事件,那么该层就再也收不到后续的Touch事件了直到下一次ACTION_DOWN事件。
说明:a.某个层级没有处理某个事件指的是它以及它的子View都没有处理该事件。
b.这条规则不适用于Activity层(它是顶层),它们可以收到每一个Touch事件。
c.如果没有处理ACTION_MOVE这类事件,不会有任何影响。
2.如果ACTION_DOWN事件发生在某个View的范围之内,则后续的ACTION_MOVE,ACTION_UP和ACTION_CANCEL等事件都将被发往该View,即使事件已经出界了。
3.第一根按下的手指触发ACTION_DOWN事件,之后按下的手指触发ACTION_POINTER_DOWN事件,中间起来的手指触发ACTION_POINTER_UP事件,最后起来的手指触发ACTION_UP事件(即使它不是触发ACTION_DOWN事件的那根手指)。
4.pointer id可以用于跟踪手指,从按下的那个时刻起pointer id生效,直至起来的那一刻失效,这之间维持不变。
5.如果一个ACTION_DOWN事件被父View拦截了,则任何子View不会再收到任何Touch事件了(这符合第1点的要求)。
6.如果一个非ACTION_DOWN事件被父View拦截了,则那些上次处理了ACTION_DOWN事件的子View会收到一个ACTION_CANCEL事件,之后不会再收到任何Touch事件了,即使父View不再拦截后续的Touch事件。
7.如果父View决定处理Touch事件或者子View没有处理Touch事件,则父View按照普通View的处理方式处理Touch事件,否则它根本不处理Touch事件(它只负责分发)。
8.如果父View在onInterceptTouchEvent中拦截了事件,则onInterceptTouchEvent中不会再收到Touch事件了,事件被直接交给它自己处理(按照普通View的处理方式)。
从手指开始触摸屏幕开始,首先得到touch事件的必然是最外层的容器,此时作为父容器,其首先触发的是onInterceptTouchEvent,该方法提供一次可以拦截子控件的触摸事件的机会。同样的返回true表示消费了该事件,此时该事件会传递至该容器的onTouchEvent方法。
如果返回false,那么则继续传递给在该触摸位置的子控件(比如一个RelativeLayout),如果子控件也不处理则继续传递给最后一个子控件,当最后一个子控件依然返回false,那么该事件则冒泡传递给父控件,(冒泡想必写过js的同学很熟悉)。
More:
1. 一个事件必然从ACTION_DOWN开始,所以当某一个控件处理了一个ACTION_DOWN事件,可以理解直到下一个ACTION_DOWN之前所有的触摸事件都应当由该控件(target)进行处理。
2. 对于各种listener,显然是由android系统进行处理的。所以Super.onTouchEvent()应当放在子类的该函数的第一行,可以优先保证系统的方法不会被自定义的操作截取而导致没有机会执行。
3. 牢记一个原则,所有的touch事件都是从父容器开始向下传递的,呈U字形
(1) 父容器(类型为 <? Extends ViewGroup>) onInterceptTouchEvent接收到事件,如果return false,转步骤(2),否则转 步骤(3)
(2) 父容器在该位置(ACTION_DOWN发生的位置)存在子控件,如果子控件类型为
<? Extends ViewGroup>,此时该子控件成为父容器,转步骤(1),如果子控件为普通view,即 不是viewgroup的子类,使用子控件转步骤(3),如果不存在子控件,使用父容器转步骤(3)
(3) 该touch事件交给该控件的onTouchEvent进行响应,如果return false,当其存在父容器时,事件传递给父容器,转步骤(3)。当不存在父容器时,该事件被丢弃。如果return true,表示事件被消费了,此touch事件终止。
Android onTouchEvent事件中onTouch方法返回值(介绍)
1、若return false说明没有成功执行onTouch事件,在执行完onTouch里面的代码之后,onTouch事件并没有结束。因此某些组件如gallery会自动执行它所在view里onTouch方法的代码。若在onTouch方法里面增加你的代码并且最后return false就会执行你在OnTouch方法中的处理操作了。
2、若return true说明你已经成功执行onTouch方法了,在执行完onTouch中的代码之后,这个onTouch事件就结束了。也不会再调用组件如gallery默认的onTouch方法了。在onTouch方法中,我们可以做很多操作,如move,down,up等等,若我们在move里面return false,那么接着的fling,up等后面的事件也不会处理。
gallery.setonTouchListener(new OnTouchListener(){ //@Override public boolean onTouch(View v,MotionEvent event) { System.out.println("gallery onTouch"); if(event.getAction()==MotionEvent.ACTION_MOVE){ mdismiss.removeMessages(1); System.out.println("ACTION_MOVE "); }else if(event.getAction()==MotionEvent.ACTION_UP){ mdismiss.sendEmptyMessageDelayed(1,10000); System.out.println("ACTION_UP "); } return false; } });
注意:
1、在ViewGroup中onInterceptTouchEvent方法若反回false,那么触屏事件会继续向下传递,但如果没有子View去处理这个事件,即子view的onTouchEvent没有返回True,则最后还是由ViewGroup去处理这个事件,也就又执行了自己的onTouchEvent。
2、onTouch调用前会自动调用onInterceptTouchEvent 如果onInterceptTouchEvent返回的false,则不会调用onTouchEvent,若重写onInterceptTouchEvent让它在需要调用onTouchEvent时返回true
以上这篇Android onTouchEvent事件中onTouch方法返回值(介绍)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。
Android Touch系统简介(二):实例详解onInterceptTouchEvent与onT
上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑。onInterceptTouchEvent的定义为于ViewGroup中,默认返回值为false,表示不拦截TouchEvent。onTouchEvent的定义位于View中,当ViewGroup要调用onTouchEvent时,会利用super.onTouchEvent。ViewGroup调用onTouchEvent默认返回false,表示不消耗touch事件,View调用onTouchEvent默认返回true,表示消耗了touch事件。考虑到onInterceptTouchEvent与onTouchEven在写UI的时候经常会用到,下面以一个例子来讲解一下。
先创建一个类MyView,继承自View
[java] view plaincopy
public class MyView extends Button {
private static final String TAG = MyView.class.getName();
public MyView(Context context){
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
创建类MyLayout,继承自ViewGroup
[java] view plaincopy
public class MyLayout extends FrameLayout{
private static final String TAG = MyLayout.class.getName();
public MyLayout(Context context) {
super(context);
}
public MyLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
LogUtil.logAction()函数是用来打印MotionEvent的动作类型,代码如下:
[java] view plaincopy
public class LogUtil {
public static void logAction(MotionEvent event, final String tag) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
Log.d(tag, "action down");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(tag, "action cancel");
break;
case MotionEvent.ACTION_UP:
Log.d(tag, "action up");
break;
case MotionEvent.ACTION_MOVE:
Log.d(tag, "action move");
break;
default:
Log.d(tag, "unknow action");
}
}
}
布局文件main.xml将MyView嵌套在MyLayout中,代码如下:
[html] view plaincopy
<view android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.example.AndroidTest.MyLayout" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view">
<com.example.AndroidTest.MyView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello" />
</view>
MainActivity的代码如下:
[java] view plaincopy
public class MainActivity extends Activity {
public static final String TAG = "TouchDemoActivity";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
程序启动后,截图如下。
下面分情况讨论程序的运行结果。
1、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回true
情况1:当点击蓝色框内的任意位置,只有MyLayout会接收事件,输出的Log如下:
可以看出,touch事件最后会被MyLayout的onTouchEvent接收到。
情况2: 点击红色框内的黑色区域,由于onInterceptTouchEvent()返回false,故MyView也能接收到touchEvent事件,输出的Log如下:
可以看出,由于MyView的onTOuchEvent默认返回True,消耗了touch事件,MyLayout中的onTOuchEvent将不会被调用。
当我们的手指按下黑色区域,停留几秒再抬起,得到的Log如下图:
可以看出,第一个事件的类型为action down,最后一个为action up,中间的都是action move的类型,这正好符合上一篇文章介绍的Android的手势定义。
2、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回false
改写MyView中onTouchEvent的代码,令其返回false
[java] view plaincopy
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return false;
}
由于MyView没有消耗touch事件,MyLayout的onTouchEvent将会被调用,打印的log如下:
可以看出,touch的类型只为action down。
3、MyLayout的onInterceptTouchEvent返回true
改写MyLayout中的onInterceptTouchEvent代码,令其返回true
[java] view plaincopy
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return true;
}
由于MyLayout拦截了touch事件,MyView中的onTouchEvent将不会被调用,log如下:
以上对Android的onInterceptTouchEvent和onTouchEvent的描述若有不妥之处,欢迎指正。
本文参考的代码出自:两分钟彻底让你明白Android中onInterceptTouchEvent与onTouchEvent(图文)!,感谢作者的无私分享。
android – 处理触摸事件 – onInterceptTouchEvent和onTouchEvent
但是当我尝试实现onInterceptTouchEvent时,我遇到了错误.
这是我的代码:
public class Game extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game_activity); //other code.... } } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: swipeScreen(); //if action recognized as swipe then swipe break; case MotionEvent.ACTION_MOVE: float x = event.getX(); float y = event.getY(); float xDelta = Math.abs(x - mLastX); float yDelta = Math.abs(y - mLastY); if (yDelta > xDelta) { return true; } break; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { ButtonOnClick(); //if not a swipe,then button click return true; }
首先错误说明:Game类型的onInterceptTouchEvent(MotionEvent)方法必须覆盖或实现超类型方法
然后,而不是返回true我将代码更改为:return super.onInterceptTouchEvent(event)但后来我得到一个错误说:对于类型Activity,未定义onInterceptTouchEvent(MotionEvent)方法
有人可以帮忙吗?
解决方法
onInterceptTouchEvent()
是ViewGroup类中的方法,而不是来自Activity.
您可以通过将逻辑从onInterceptTouchEvent()移动到dispatchTouchEvent(MotionEvent ev)
来实现所需的行为.请记住调用dispatchTouchEvent(MotionEvent ev)的超类实现来处理应该正常处理的事件.
另请注意,只有在delta大于system constant for touch slop时才应考虑移动.我建议用户通过测试yDelta / 2>确保用户正在按照您想要的方向滑动. xDelta而不是yDelta> xDelta.
public class Game extends Activity { private int mSlop; private float mDownX; private float mDownY; private boolean mSwiping; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game_activity); ViewConfiguration vc = ViewConfiguration.get(this) mSlop = vc.getScaledTouchSlop(); //other code.... } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mDownX = ev.getX(); mDownY = ev.getY(); mSwiping = false; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if(mSwiping) { swipeScreen(); //if action recognized as swipe then swipe } break; case MotionEvent.ACTION_MOVE: float x = ev.getX(); float y = ev.getY(); float xDelta = Math.abs(x - mDownX); float yDelta = Math.abs(y - mDownY); if (yDelta > mSlop && yDelta / 2 > xDelta) { mSwiping = true; return true; } break; } return super.dispatchTouchEvent(ev); } }
今天关于cocos2dx 2.2.6 hitWidget->onTouchEnded(pTouch, pEvent); 异常和checked异常的介绍到此结束,谢谢您的阅读,有关Android onInterceptTouchEvent 和 onTouchEvent、Android onTouchEvent事件中onTouch方法返回值(介绍)、Android Touch系统简介(二):实例详解onInterceptTouchEvent与onT、android – 处理触摸事件 – onInterceptTouchEvent和onTouchEvent等更多相关知识的信息可以在本站进行查询。
本文标签: