Android开发ScrollView 事件冲突问题 .
2012-12-26 15:11
337 查看
Android开发ScrollView上下左右滑动事件冲突整理一(根据事件)
主要通过重写 onInterceptTouchEvent 事件来解决,代码如下:
package com.cm.android.pad.view.itemView;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.ScrollView;
import android.widget.Scroller;
public class MultiScroll extends ScrollView {
private static final int ANIMATION_SCREEN_SET_DURATION_MILLIS = 500;
// What fraction (1/x) of the screen the user must swipe to indicate a page change
private static final int FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE = 4;
private static final int INVALID_SCREEN = -1;
/*
* Velocity of a swipe (in density-independent pixels per second) to force a swipe to the
* next/previous screen. Adjusted into mDensityAdjustedSnapVelocity on init.
*/
private static final int SNAP_VELOCITY_DIP_PER_SECOND = 600;
// Argument to getVelocity for units to give pixels per second (1 = pixels per millisecond).
private static final int VELOCITY_UNIT_PIXELS_PER_SECOND = 1000;
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_HORIZONTAL_SCROLLING = 1;
private static final int TOUCH_STATE_VERTICAL_SCROLLING = -1;
private int mCurrentScreen;
private int mDensityAdjustedSnapVelocity;
private boolean mFirstLayout = true;
private float mLastMotionX;
private float mLastMotionY;
//private OnScreenSwitchListener mOnScreenSwitchListener;
private int mMaximumVelocity;
private int mNextScreen = INVALID_SCREEN;
private Scroller mScroller;
private int mTouchSlop;
private int mTouchState = TOUCH_STATE_REST;
private VelocityTracker mVelocityTracker;
private int mLastSeenLayoutWidth = -1;
public MultiScroll(Context context) {
super(context);
init();
}
public MultiScroll(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MultiScroll(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mScroller = new Scroller(getContext());
// Calculate the density-dependent snap velocity in pixels
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getMetrics(displayMetrics);
mDensityAdjustedSnapVelocity =
(int) (displayMetrics.density * SNAP_VELOCITY_DIP_PER_SECOND);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
@Override
public boolean onInterceptTouchEvent(final MotionEvent ev) {
/*
* By Yoni Samlan: Modified onInterceptTouchEvent based on standard ScrollView's
* onIntercept. The logic is designed to support a nested vertically scrolling view inside
* this one; once a scroll registers for X-wise scrolling, handle it in this view and don't
* let the children, but once a scroll registers for y-wise scrolling, let the children
* handle it exclusively.
*/
final int action = ev.getAction();
boolean intercept = false;
switch (action) {
case MotionEvent.ACTION_MOVE:
/*
* If we're in a horizontal scroll event, take it (intercept further events). But if
* we're mid-vertical-scroll, don't even try; let the children deal with it. If we
* haven't found a scroll event yet, check for one.
*/
if (mTouchState == TOUCH_STATE_HORIZONTAL_SCROLLING) {
// Let children handle the events for the duration of the scroll event.
intercept = false;
} else if (mTouchState == TOUCH_STATE_VERTICAL_SCROLLING) {
/*
* We've already started a horizontal scroll; set intercept to true so we can
* take the remainder of all touch events in onTouchEvent.
*/
intercept = true;
} else { // We haven't picked up a scroll event yet; check for one.
/*
* If we detected a horizontal scroll event, start stealing touch events (mark
* as scrolling). Otherwise, see if we had a vertical scroll event -- if so, let
* the children handle it and don't look to intercept again until the motion is
* done.
*/
final float x = ev.getX();
final int xDiff = (int) Math.abs(x - mLastMotionX);
boolean xMoved = xDiff > mTouchSlop;
final float y = ev.getY();
final int yDiff = (int) Math.abs(y - mLastMotionY);
boolean yMoved = yDiff > mTouchSlop;
if (xMoved) {
// Scroll if the user moved far enough along the X axis
if(xDiff>=yDiff)
mTouchState = TOUCH_STATE_HORIZONTAL_SCROLLING;
mLastMotionX = x;
}
if (yMoved) {
if(yDiff>xDiff)
mTouchState = TOUCH_STATE_VERTICAL_SCROLLING;
mLastMotionY = y;
}
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Release the drag.
mTouchState = TOUCH_STATE_REST;
intercept = false;
break;
case MotionEvent.ACTION_DOWN:
/*
* No motion yet, but register the coordinates so we can check for intercept at the
* next MOVE event.
*/
//Log.i("ViewPager-->", "Action_Down");
mTouchState = TOUCH_STATE_REST;
mLastMotionY = ev.getY();
mLastMotionX = ev.getX();
break;
default:
break;
}
Log.i("MultiScroll-->", intercept+"");
return intercept;
}
}
Android开发ScrollView上下左右滑动事件冲突整理二(根据角度)
Android的ScrollView滑动获得角度实例:
package com.cm.android.pad.view.itemView;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;
public class TestScroll extends ScrollView {
private GestureDetector mGestureDetector;
private static double SCROLL_ANGLE = 90;
public TestScroll(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(new YScrollDetecotr());
setFadingEdgeLength(0);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev)
&& mGestureDetector.onTouchEvent(ev);
}
class YScrollDetecotr extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// if(distanceY != 0 && distanceX != 0){
//
// }
// if(Math.abs(distanceY) >= Math.abs(distanceX)){
// System.out.println("distanceX = " + distanceX + " , distanceY = "
// + distanceY);
// return true;
// }
// return false;
double angle = Math.atan2(Math.abs(distanceY), Math.abs(distanceX));
// System.out.println("angle-->" + (180 * angle) / Math.PI);
if ((180 * angle) / Math.PI < 180) {
return false;
}
return false;
}
}
}
主要通过重写 onInterceptTouchEvent 事件来解决,代码如下:
package com.cm.android.pad.view.itemView;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.ScrollView;
import android.widget.Scroller;
public class MultiScroll extends ScrollView {
private static final int ANIMATION_SCREEN_SET_DURATION_MILLIS = 500;
// What fraction (1/x) of the screen the user must swipe to indicate a page change
private static final int FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE = 4;
private static final int INVALID_SCREEN = -1;
/*
* Velocity of a swipe (in density-independent pixels per second) to force a swipe to the
* next/previous screen. Adjusted into mDensityAdjustedSnapVelocity on init.
*/
private static final int SNAP_VELOCITY_DIP_PER_SECOND = 600;
// Argument to getVelocity for units to give pixels per second (1 = pixels per millisecond).
private static final int VELOCITY_UNIT_PIXELS_PER_SECOND = 1000;
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_HORIZONTAL_SCROLLING = 1;
private static final int TOUCH_STATE_VERTICAL_SCROLLING = -1;
private int mCurrentScreen;
private int mDensityAdjustedSnapVelocity;
private boolean mFirstLayout = true;
private float mLastMotionX;
private float mLastMotionY;
//private OnScreenSwitchListener mOnScreenSwitchListener;
private int mMaximumVelocity;
private int mNextScreen = INVALID_SCREEN;
private Scroller mScroller;
private int mTouchSlop;
private int mTouchState = TOUCH_STATE_REST;
private VelocityTracker mVelocityTracker;
private int mLastSeenLayoutWidth = -1;
public MultiScroll(Context context) {
super(context);
init();
}
public MultiScroll(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MultiScroll(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mScroller = new Scroller(getContext());
// Calculate the density-dependent snap velocity in pixels
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getMetrics(displayMetrics);
mDensityAdjustedSnapVelocity =
(int) (displayMetrics.density * SNAP_VELOCITY_DIP_PER_SECOND);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
@Override
public boolean onInterceptTouchEvent(final MotionEvent ev) {
/*
* By Yoni Samlan: Modified onInterceptTouchEvent based on standard ScrollView's
* onIntercept. The logic is designed to support a nested vertically scrolling view inside
* this one; once a scroll registers for X-wise scrolling, handle it in this view and don't
* let the children, but once a scroll registers for y-wise scrolling, let the children
* handle it exclusively.
*/
final int action = ev.getAction();
boolean intercept = false;
switch (action) {
case MotionEvent.ACTION_MOVE:
/*
* If we're in a horizontal scroll event, take it (intercept further events). But if
* we're mid-vertical-scroll, don't even try; let the children deal with it. If we
* haven't found a scroll event yet, check for one.
*/
if (mTouchState == TOUCH_STATE_HORIZONTAL_SCROLLING) {
// Let children handle the events for the duration of the scroll event.
intercept = false;
} else if (mTouchState == TOUCH_STATE_VERTICAL_SCROLLING) {
/*
* We've already started a horizontal scroll; set intercept to true so we can
* take the remainder of all touch events in onTouchEvent.
*/
intercept = true;
} else { // We haven't picked up a scroll event yet; check for one.
/*
* If we detected a horizontal scroll event, start stealing touch events (mark
* as scrolling). Otherwise, see if we had a vertical scroll event -- if so, let
* the children handle it and don't look to intercept again until the motion is
* done.
*/
final float x = ev.getX();
final int xDiff = (int) Math.abs(x - mLastMotionX);
boolean xMoved = xDiff > mTouchSlop;
final float y = ev.getY();
final int yDiff = (int) Math.abs(y - mLastMotionY);
boolean yMoved = yDiff > mTouchSlop;
if (xMoved) {
// Scroll if the user moved far enough along the X axis
if(xDiff>=yDiff)
mTouchState = TOUCH_STATE_HORIZONTAL_SCROLLING;
mLastMotionX = x;
}
if (yMoved) {
if(yDiff>xDiff)
mTouchState = TOUCH_STATE_VERTICAL_SCROLLING;
mLastMotionY = y;
}
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Release the drag.
mTouchState = TOUCH_STATE_REST;
intercept = false;
break;
case MotionEvent.ACTION_DOWN:
/*
* No motion yet, but register the coordinates so we can check for intercept at the
* next MOVE event.
*/
//Log.i("ViewPager-->", "Action_Down");
mTouchState = TOUCH_STATE_REST;
mLastMotionY = ev.getY();
mLastMotionX = ev.getX();
break;
default:
break;
}
Log.i("MultiScroll-->", intercept+"");
return intercept;
}
}
Android开发ScrollView上下左右滑动事件冲突整理二(根据角度)
Android的ScrollView滑动获得角度实例:
package com.cm.android.pad.view.itemView;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;
public class TestScroll extends ScrollView {
private GestureDetector mGestureDetector;
private static double SCROLL_ANGLE = 90;
public TestScroll(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(new YScrollDetecotr());
setFadingEdgeLength(0);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev)
&& mGestureDetector.onTouchEvent(ev);
}
class YScrollDetecotr extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// if(distanceY != 0 && distanceX != 0){
//
// }
// if(Math.abs(distanceY) >= Math.abs(distanceX)){
// System.out.println("distanceX = " + distanceX + " , distanceY = "
// + distanceY);
// return true;
// }
// return false;
double angle = Math.atan2(Math.abs(distanceY), Math.abs(distanceX));
// System.out.println("angle-->" + (180 * angle) / Math.PI);
if ((180 * angle) / Math.PI < 180) {
return false;
}
return false;
}
}
}
相关文章推荐
- android开发步步为营之65:解决ScrollView和ListView触摸事件onInterceptTouchEvent相互冲突问题
- android开发步步为营之65:解决ScrollView和ListView触摸事件onInterceptTouchEvent相互冲突问题
- Android开发之解决ListView和ScrollView滑动冲突的问题
- Android开发ScrollView上下左右滑动事件冲突整理一(根据事件)
- android 开发-ListView与ScrollView事件冲突处理(事件分发机制处理)
- Android ScrollView和ListView事件冲突问题解决方法
- android开发中百度地图和ScrollView冲突的问题
- android clickspan点击富文本与本身点击事件冲突问题
- Android 解决ListView 和 ScrollView 共存冲突的问题
- Android-解决ViewFlipper与ScrollView滑动响应事件拦截的问题
- (四十九)android解决同一个界面上ScrollView和 ListView等可滚动控件滚动冲突问题
- Android中Scrollview、ViewPager冲突问题汇总
- android 解决ScrollView和高德地图MapView滚动冲突问题
- Android长按事件和点击事件问题处理,OnItemLongClickListener和OnItemClickListener冲突问题
- 解决ScrollView嵌套viewpager滑动事件冲突问题
- Android开发遇到一个问题,怎么拦截键盘的input事件
- Android中Scrollview、ViewPager冲突问题汇总(已解决)
- Android之 如何解决ScrollView 和ListView滑动冲突的问题如何解决ScrollView can host only one direct child
- achartengine与Android中ScrollView的冲突问题
- Android 解决ListView 和 ScrollView 共存冲突的问题