blob: 4b76bea950c4119182f821745260366834da4cb3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.weex.ui.view.gesture;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewParent;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.weex.bridge.EventResult;
import org.apache.weex.common.Constants;
import org.apache.weex.dom.WXEvent;
import org.apache.weex.ui.component.Scrollable;
import org.apache.weex.ui.component.WXComponent;
import org.apache.weex.ui.view.gesture.WXGestureType.GestureInfo;
import org.apache.weex.ui.view.gesture.WXGestureType.HighLevelGesture;
import org.apache.weex.ui.view.gesture.WXGestureType.LowLevelGesture;
import org.apache.weex.utils.WXLogUtils;
import org.apache.weex.utils.WXUtils;
import org.apache.weex.utils.WXViewUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.weex.WXSDKInstance;
import org.apache.weex.common.Constants.Event;
public class WXGesture extends GestureDetector.SimpleOnGestureListener implements OnTouchListener {
private final static String TAG = "Gesture";
private static final int CUR_EVENT = -1;
public static final String START = "start";
public static final String MOVE = "move";
public static final String END = "end";
public static final String UNKNOWN = "unknown";
public static final String LEFT = "left";
public static final String RIGHT = "right";
public static final String UP = "up";
public static final String DOWN = "down";
private WXComponent component;
private GestureDetector mGestureDetector;
private Rect globalRect;
private Point globalOffset;
private Point globalEventOffset;
private PointF locEventOffset;
private PointF locLeftTop;
private long swipeDownTime = -1;
private long panDownTime = -1;
private WXGestureType mPendingPan = null;//event type to notify when action_up or action_cancel
private int mParentOrientation =-1;
private boolean mIsPreventMoveEvent = false;
private boolean mIsTouchEventConsumed = false; //Reset to false when first touch event, set to true when gesture event fired.
private boolean requestDisallowInterceptTouchEvent = false;
private boolean shouldBubbleResult = true;
private int shouldBubbleInterval = 0; //every times try
private int shouldBubbleCallRemainTimes = 0;
private final List<OnTouchListener> mTouchListeners = new LinkedList<>();
public WXGesture(WXComponent wxComponent, Context context) {
this.component = wxComponent;
globalRect = new Rect();
globalOffset = new Point();
globalEventOffset = new Point();
locEventOffset = new PointF();
locLeftTop = new PointF();
mGestureDetector = new GestureDetector(context, this, new GestureHandler());
Scrollable parentScrollable = wxComponent.getParentScroller();
if(parentScrollable != null) {
mParentOrientation = parentScrollable.getOrientation();
}
shouldBubbleResult = WXUtils.getBoolean(wxComponent.getAttrs().get(Constants.Name.SHOULD_STOP_PROPAGATION_INIT_RESULT), true);
shouldBubbleInterval = WXUtils.getNumberInt(wxComponent.getAttrs().get(Constants.Name.SHOULD_STOP_PROPAGATION_INTERVAL), 0);
}
private boolean isParentScrollable() {
if(component == null) {
return true;
}
Scrollable parentScrollable = component.getParentScroller();
return parentScrollable == null || parentScrollable.isScrollable();
}
private boolean hasSameOrientationWithParent(){
return (mParentOrientation == Constants.Orientation.HORIZONTAL && component.containsGesture(
HighLevelGesture.HORIZONTALPAN))
|| (mParentOrientation == Constants.Orientation.VERTICAL && component.containsGesture(HighLevelGesture.VERTICALPAN));
}
public void setPreventMoveEvent(boolean preventMoveEvent) {
mIsPreventMoveEvent = preventMoveEvent;
}
/**
*
* @return true if current touch event is already consumed by gesture.
* Reset to false when next first touch event, set to true when gesture event fired.
*/
public boolean isTouchEventConsumedByAdvancedGesture(){
return mIsTouchEventConsumed;
}
/**
* stoppropagation
* */
public static boolean isStopPropagation(String type){
return Constants.Event.STOP_PROPAGATION.equals(type) || Constants.Event.STOP_PROPAGATION_RAX.equals(type);
}
public static boolean hasStopPropagation(WXComponent component){
WXEvent event = component.getEvents();
if(event == null){
return false;
}
int size = event.size();
for (int i=0; i<size; i++) {
if(i >= event.size()){
break;
}
String type = event.get(i);
if(isStopPropagation(type)){
return true;
}
}
return false;
}
/**
* shouldBubbleEvent default true
* */
private boolean shouldBubbleTouchEvent(MotionEvent event){
if(hasStopPropagation(component)){
if(shouldBubbleInterval > 0 && shouldBubbleCallRemainTimes > 0){
shouldBubbleCallRemainTimes--;
return shouldBubbleResult;
}
Map<String, Object> eventMap = createFireEventParam(event, CUR_EVENT, null);
eventMap.put("type", "touch");
if(event.getAction() == MotionEvent.ACTION_DOWN){
eventMap.put("action", START);
}else if(event.getAction() == MotionEvent.ACTION_CANCEL
|| event.getAction() == MotionEvent.ACTION_UP){
eventMap.put("action", END);
}else{
eventMap.put("action", MOVE);
}
String name = Event.STOP_PROPAGATION;
if(!component.getEvents().contains(Event.STOP_PROPAGATION)){
name = Event.STOP_PROPAGATION_RAX;
}
EventResult result = component.fireEventWait(name, eventMap);
if(result.isSuccess() && result.getResult() != null){
boolean stopPropagation = WXUtils.getBoolean(result.getResult(), !shouldBubbleResult);
shouldBubbleResult = !stopPropagation;
}
shouldBubbleCallRemainTimes = shouldBubbleInterval;
return shouldBubbleResult;
}
return true;
}
@SuppressWarnings("unused")
public void addOnTouchListener(OnTouchListener listener) {
if(listener != null) {
mTouchListeners.add(listener);
}
}
@SuppressWarnings("unused")
public boolean removeTouchListener(OnTouchListener listener) {
if(listener != null) {
return mTouchListeners.remove(listener);
}
return false;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if(requestDisallowInterceptTouchEvent){
requestDisallowInterceptTouchEvent = false;
return false;
}
try {
boolean result = mGestureDetector.onTouchEvent(event);
if(mTouchListeners != null && !mTouchListeners.isEmpty()) {
for(OnTouchListener listener : mTouchListeners) {
result |= listener.onTouch(v, event);
}
}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_DOWN:
mIsTouchEventConsumed = false;
/**
* If component has same scroll orientation with it's parent and it's parent not scrollable
* , we should disallow parent in DOWN.
*/
if(hasSameOrientationWithParent() && !isParentScrollable()){
ViewParent p;
if ((p = component.getRealView().getParent()) != null) {
p.requestDisallowInterceptTouchEvent(true);
}
}
result |= handleMotionEvent(LowLevelGesture.ACTION_DOWN, event);
break;
case MotionEvent.ACTION_MOVE:
result |= handleMotionEvent(LowLevelGesture.ACTION_MOVE, event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
finishDisallowInterceptTouchEvent(v);
result |= handleMotionEvent(LowLevelGesture.ACTION_UP, event);
result |= handlePanMotionEvent(event);
break;
case MotionEvent.ACTION_CANCEL:
finishDisallowInterceptTouchEvent(v);
result |= handleMotionEvent(LowLevelGesture.ACTION_CANCEL, event);
result |= handlePanMotionEvent(event);
break;
}
if(hasStopPropagation(component)){
ViewGroup parent = (ViewGroup) v.getParent();
boolean requestDisallowInterceptTouchEvent = false;
if(parent != null){
if(!shouldBubbleTouchEvent(event)){
requestDisallowInterceptTouchEvent = true;
}
parent.requestDisallowInterceptTouchEvent(requestDisallowInterceptTouchEvent);
}
if(component.getParent() != null){
component.getParent().requestDisallowInterceptTouchEvent(requestDisallowInterceptTouchEvent);
}
if(mIsTouchEventConsumed && WXUtils.getBoolean(component.getAttrs().get("cancelTouchOnConsume"), false)){//when touch event consumed by one gesture, other component should not consumed
event.setAction(MotionEvent.ACTION_CANCEL);
}
}
return result;
} catch (Exception e) {
WXLogUtils.e("Gesture RunTime Error ", e);
return false;
}
}
private String getPanEventAction(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return START;
case MotionEvent.ACTION_MOVE:
return MOVE;
case MotionEvent.ACTION_UP:
return END;
case MotionEvent.ACTION_CANCEL:
return END;
default:
return UNKNOWN;
}
}
private void finishDisallowInterceptTouchEvent(View v){
if(v.getParent() != null){
v.getParent().requestDisallowInterceptTouchEvent(false);
}
}
private boolean handlePanMotionEvent(MotionEvent motionEvent) {
if (mPendingPan == null) {
return false;
}
String state = null;
if (mPendingPan == HighLevelGesture.HORIZONTALPAN || mPendingPan == HighLevelGesture.VERTICALPAN) {
state = getPanEventAction(motionEvent);
}
if (component.containsGesture(mPendingPan)) {
if(mIsPreventMoveEvent && MOVE.equals(state)){
return true;
}
List<Map<String, Object>> list = createMultipleFireEventParam(motionEvent, state);
for (Map<String, Object> map : list) {
component.fireEvent(mPendingPan.toString(), map);
}
//action is finish, clean pending pan
if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
mPendingPan = null;
}
return true;
} else {
return false;
}
}
/**
*
* @param WXGestureType possible low-level gesture, defined in {@link Event}
* @param motionEvent motionEvent, which contains all pointers event in a period of time
* @return true if this event is handled, otherwise false.
*/
private boolean handleMotionEvent(WXGestureType WXGestureType, MotionEvent motionEvent) {
if (component.containsGesture(WXGestureType)) {
List<Map<String, Object>> list = createMultipleFireEventParam(motionEvent, null);
for (Map<String, Object> map : list) {
component.fireEvent(WXGestureType.toString(), map);
}
return true;
} else {
return false;
}
}
/**
* Create a list of event for {@link WXSDKInstance#fireEvent(String, String, Map, Map)}.
* As there is a batch mechanism in MotionEvent, so this method returns a list.
* @param motionEvent motionEvent, which contains all pointers event in a period of time
* @return List of Map, which contains touch object.
*/
private List<Map<String, Object>> createMultipleFireEventParam(MotionEvent motionEvent,String state) {
List<Map<String, Object>> list = new ArrayList<>(motionEvent.getHistorySize() + 1);
//list.addAll(getHistoricalEvents(motionEvent));
list.add(createFireEventParam(motionEvent, CUR_EVENT, state));
return list;
}
/**
* Get historical event. This is only applied to {@link MotionEvent#ACTION_MOVE}.
* For other types of motionEvent, historical event is meaningless.
* @param motionEvent motionEvent, which contains all pointers event in a period of time
* @return If motionEvent.getActionMasked()!=MotionEvent.ACTION_MOVE,
* this method will return an empty list.
* Otherwise this method will return the historical motionEvent, which may also be empty.
*/
private List<Map<String, Object>> getHistoricalEvents(MotionEvent motionEvent) {
List<Map<String, Object>> list = new ArrayList<>(motionEvent.getHistorySize());
if (motionEvent.getActionMasked() == MotionEvent.ACTION_MOVE) {
Map<String, Object> param;
for (int i = 0; i < motionEvent.getHistorySize(); i++) {
param = createFireEventParam(motionEvent, i,null);
list.add(param);
}
}
return list;
}
/**
* Create a map represented touch event at a certain moment.
* @param motionEvent motionEvent, which contains all pointers event in a period of time
* @param pos index used to retrieve a certain moment in a period of time.
* @return touchEvent
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent">touchEvent</a>
*/
private Map<String, Object> createFireEventParam(MotionEvent motionEvent, int pos, String state) {
JSONArray jsonArray = new JSONArray(motionEvent.getPointerCount());
if (motionEvent.getActionMasked() == MotionEvent.ACTION_MOVE) {
for (int i = 0; i < motionEvent.getPointerCount(); i++) {
jsonArray.add(createJSONObject(motionEvent, pos, i));
}
} else if (isPointerNumChanged(motionEvent)) {
int pointerIndex = motionEvent.getActionIndex();
jsonArray.add(createJSONObject(motionEvent, CUR_EVENT, pointerIndex));
}
Map<String, Object> map = new HashMap<>();
map.put(GestureInfo.HISTORICAL_XY, jsonArray);
if (state != null) {
map.put(GestureInfo.STATE, state);
}
return map;
}
/**
* Tell whether the number of motion event's pointer changed.
* @param event the current motion event
* @return true for number of motion event's pointer changed, otherwise false.
*/
private boolean isPointerNumChanged(MotionEvent event) {
return event.getActionMasked() == MotionEvent.ACTION_DOWN ||
event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN ||
event.getActionMasked() == MotionEvent.ACTION_UP ||
event.getActionMasked() == MotionEvent.ACTION_POINTER_UP ||
event.getActionMasked() == MotionEvent.ACTION_CANCEL;
}
/**
* Tell whether component contains pan gesture
* @return true for contains pan gesture, otherwise false.
*/
private boolean containsSimplePan() {
return component.containsGesture(HighLevelGesture.PAN_START) ||
component.containsGesture(HighLevelGesture.PAN_MOVE) ||
component.containsGesture(HighLevelGesture.PAN_END);
}
/**
* Create a touchObject for a pointer at a certain moment.
* @param motionEvent motionEvent, which contains all pointers event in a period of time
* @param pos index used to retrieve a certain moment in a period of time.
* @param pointerIndex pointerIndex
* @return JSONObject represent a touch event
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch">touch</a>
*/
private JSONObject createJSONObject(MotionEvent motionEvent, int pos, int pointerIndex) {
PointF screenXY, pageXY;
if (pos == CUR_EVENT) {
pageXY = getEventLocInPageCoordinate(motionEvent, pointerIndex);
screenXY = getEventLocInScreenCoordinate(motionEvent, pointerIndex);
} else {
pageXY = getEventLocInPageCoordinate(motionEvent, pointerIndex, pos);
screenXY = getEventLocInScreenCoordinate(motionEvent, pointerIndex, pos);
}
JSONObject map = createJSONObject(screenXY, pageXY, (float) motionEvent.getPointerId(pointerIndex));
float force = motionEvent.getPressure();
if(force > 0 && force < 1) {
map.put("force", motionEvent.getPressure());
}
return map;
}
/**
* Create a touchObject for a pointer at a certain moment.
* @param screenXY the point of event happened in screen coordinate
* @param pageXY the point of event happened in page coorindate
* @param pointerId pointerIndex pointerIndex
* @return JSONObject represent a touch event
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch">touch</a>
*/
@NonNull
private JSONObject createJSONObject(PointF screenXY, PointF pageXY, float pointerId) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(GestureInfo.PAGE_X, pageXY.x);
jsonObject.put(GestureInfo.PAGE_Y, pageXY.y);
jsonObject.put(GestureInfo.SCREEN_X, screenXY.x);
jsonObject.put(GestureInfo.SCREEN_Y, screenXY.y);
jsonObject.put(GestureInfo.POINTER_ID, pointerId);
return jsonObject;
}
/**
* @see {@link #getEventLocInScreenCoordinate(MotionEvent, int, int)}
*/
private PointF getEventLocInScreenCoordinate(MotionEvent motionEvent, int pointerIndex) {
return getEventLocInScreenCoordinate(motionEvent, pointerIndex, CUR_EVENT);
}
/**
* Get event location in Screen's coordinate, e.g. root(global) coordinate.
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch/screenX">screenX</a>
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch/screenY">screenY</a>
* @param motionEvent the original motionEvent
* @param pointerIndex pointerIndex
* @param position if motionEvent.getHistoricalSize()!=0, the is the index of historical event,
* otherwise this is {@link #CUR_EVENT} which indicates historicalSize is zero
* @return the eventLocation in screen's coordinate
*/
private PointF getEventLocInScreenCoordinate(MotionEvent motionEvent, int pointerIndex, int position) {
float eventX, eventY;
if (position == CUR_EVENT) {
eventX = motionEvent.getX(pointerIndex);
eventY = motionEvent.getY(pointerIndex);
} else {
eventX = motionEvent.getHistoricalX(pointerIndex, position);
eventY = motionEvent.getHistoricalY(pointerIndex, position);
}
return getEventLocInScreenCoordinate(eventX, eventY);
}
/**
* Get event location in Screen's coordinate, e.g. root(global) coordinate.
* @param eventX {@link MotionEvent#getX()} or {@link MotionEvent#getHistoricalX(int, int)}
* @param eventY {@link MotionEvent#getX()} or {@link MotionEvent#getHistoricalX(int, int)}
* @return the eventLocation in screen's coordinate
* @see {@link #getEventLocInScreenCoordinate(MotionEvent, int, int)}
*/
@NonNull
private PointF getEventLocInScreenCoordinate(float eventX, float eventY) {
globalRect.set(0, 0, 0, 0);
globalOffset.set(0, 0);
globalEventOffset.set((int) eventX, (int) eventY);
component.getRealView().getGlobalVisibleRect(globalRect, globalOffset);
globalEventOffset.offset(globalOffset.x, globalOffset.y);
return new PointF(WXViewUtils.getWebPxByWidth(globalEventOffset.x,component.getInstance().getInstanceViewPortWidth()),
WXViewUtils.getWebPxByWidth(globalEventOffset.y,component.getInstance().getInstanceViewPortWidth()));
}
/**
* @see {@link #getEventLocInPageCoordinate(MotionEvent, int, int)}
*/
private PointF getEventLocInPageCoordinate(MotionEvent motionEvent, int pointerIndex) {
return getEventLocInPageCoordinate(motionEvent, pointerIndex, CUR_EVENT);
}
/**
* Get event's location in Document's (Page) coordinate.
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch/pageX">pageX</a>
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch/pageY">pageY</a>
* @param motionEvent the original motionEvent
* @param pointerIndex pointerIndex
* @param position if motionEvent.getHistoricalSize()!=0, the is the index of historical event,
* otherwise this is {@link #CUR_EVENT} which indicates historicalSize is zero
* @return the event location in page's coordinate.
*/
private PointF getEventLocInPageCoordinate(MotionEvent motionEvent, int pointerIndex, int position) {
float eventX, eventY;
if (position == CUR_EVENT) {
eventX = motionEvent.getX(pointerIndex);
eventY = motionEvent.getY(pointerIndex);
} else {
eventX = motionEvent.getHistoricalX(pointerIndex, position);
eventY = motionEvent.getHistoricalY(pointerIndex, position);
}
return getEventLocInPageCoordinate(eventX, eventY);
}
/**
* Get event's location in Document's (Page) coordinate.
* @param eventX {@link MotionEvent#getX()} or {@link MotionEvent#getHistoricalX(int, int)}
* @param eventY {@link MotionEvent#getX()} or {@link MotionEvent#getHistoricalX(int, int)}
* @return the event location in page's coordinate.
* @see {@link #getEventLocInPageCoordinate(MotionEvent, int, int)}
*/
@NonNull
private PointF getEventLocInPageCoordinate(float eventX, float eventY) {
locEventOffset.set(eventX, eventY);
locLeftTop.set(0, 0);
component.computeVisiblePointInViewCoordinate(locLeftTop);
locEventOffset.offset(locLeftTop.x, locLeftTop.y);
return new PointF(WXViewUtils.getWebPxByWidth(locEventOffset.x,component.getInstance().getInstanceViewPortWidth()),
WXViewUtils.getWebPxByWidth(locEventOffset.y,component.getInstance().getInstanceViewPortWidth()));
}
private static class GestureHandler extends android.os.Handler {
public GestureHandler() {
super(Looper.getMainLooper());
}
}
/***************** OnGestureListener ****************/
@Override
public void onLongPress(MotionEvent e) {
if (component.containsGesture(HighLevelGesture.LONG_PRESS)) {
List<Map<String, Object>> list = createMultipleFireEventParam(e,null);
component.getInstance().fireEvent(
component.getRef(),
HighLevelGesture.LONG_PRESS.toString(),
list.get(list.size() - 1));
mIsTouchEventConsumed = true;
}
}
/**
* Gesture priority:horizontalPan & verticalPan > pan > swipe
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
boolean result = false;
if (e1 == null || e2 == null) {
return false;
}
float dx = Math.abs(e2.getX() - e1.getX());
float dy = Math.abs(e2.getY() - e1.getY());
WXGestureType possiblePan;
if (dx > dy) {
possiblePan = HighLevelGesture.HORIZONTALPAN;
} else {
possiblePan = HighLevelGesture.VERTICALPAN;
}
if (mPendingPan == HighLevelGesture.HORIZONTALPAN || mPendingPan == HighLevelGesture.VERTICALPAN) {
//already during directional-pan
result = handlePanMotionEvent(e2);
} else if (component.containsGesture(possiblePan)) {
ViewParent p;
if ((p = component.getRealView().getParent()) != null) {
p.requestDisallowInterceptTouchEvent(true);
}
if (mPendingPan != null) {
handleMotionEvent(mPendingPan, e2);//finish pan if exist
}
mPendingPan = possiblePan;
component.fireEvent(possiblePan.toString(), createFireEventParam(e2, CUR_EVENT, START));
result = true;
} else if (containsSimplePan()) {
if (panDownTime != e1.getEventTime()) {
panDownTime = e1.getEventTime();
mPendingPan = HighLevelGesture.PAN_END;
component.fireEvent(HighLevelGesture.PAN_START.toString(),
createFireEventParam(e1, CUR_EVENT, null));
} else {
component.fireEvent(HighLevelGesture.PAN_MOVE.toString(),
createFireEventParam(e2, CUR_EVENT, null));
}
result = true;
} else if (component.containsGesture(HighLevelGesture.SWIPE)) {
if (swipeDownTime != e1.getEventTime()) {
swipeDownTime = e1.getEventTime();
List<Map<String, Object>> list = createMultipleFireEventParam(e2, null);
Map<String, Object> param = list.get(list.size() - 1);
if (Math.abs(distanceX) > Math.abs(distanceY)) {
param.put(GestureInfo.DIRECTION, distanceX > 0 ? LEFT : RIGHT);
} else {
param.put(GestureInfo.DIRECTION, distanceY > 0 ? UP : DOWN);
}
component.getInstance().fireEvent(component.getRef(),
HighLevelGesture.SWIPE.toString(), param);
result = true;
}
}
mIsTouchEventConsumed = mIsTouchEventConsumed || result;
return result;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
public boolean isRequestDisallowInterceptTouchEvent() {
return requestDisallowInterceptTouchEvent;
}
public void setRequestDisallowInterceptTouchEvent(boolean requestDisallowInterceptTouchEvent) {
this.requestDisallowInterceptTouchEvent = requestDisallowInterceptTouchEvent;
}
}