Android中不同方向嵌套滑动的解决方案(ListView为例子)

Android中不同方向嵌套滑动的解决方案(ListView为例子)

分类:Android中级进阶

嵌套触摸android

</pre>前言:<p></p><p></p><p><span style="white-space:pre"></span>就像手机QQ<span style="white-space:pre"> </span>的聊天消息列表,一个纵向滑动的ListView列举所有消息,但每一条消息可以横向滑动。</p><p>        是否觉得很分裂?其实实现起来也不复杂。</p><p>        理解了以后,可以方便延伸到GridView,ViewPager,ScrollView等等滑动控件。</p><p>        图片来源网络,侵删。</p><p>                                                                         <img src="?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></p><p></p><p></p><p>        以一个LinearLayout为ListView的Item,里面放了消息的TextView,和一个删除按钮。布局为:item_layout.xml</p><p></p><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?><ex.oyyj.listviewfulldemo.VerticalSlideLayout xmlns:android=""android:layout_width="match_parent"android:orientation="horizontal"android:layout_height="match_parent"><TextViewandroid:id="@+id/item"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:minHeight="80dp"android:textColor="#202020"android:textSize="22sp" /><TextViewandroid:id="@+id/delete"android:layout_width="100dp"android:layout_height="match_parent"android:background="#888888"android:textSize="22sp"android:gravity="center"android:text="删除"/></ex.oyyj.listviewfulldemo.VerticalSlideLayout> 主要的思路是:

重写ListView中的Item,也就是LinearLayout的onTouchEvent方法,,以监听横向滑动和纵向滑动:

1)纵向滑动时,不管

2)横向滑动时,请求父容器,也即是ListView不要拦截触摸事件,自己在子View(也就是LinearLayout)里面处理就好了,

当横向触摸时间结束(MotionEvent.Action_UP)或者划出边界(MotionEvent.Action_CANCEL)时,恢复允许父容器拦截触摸事件。

先上效果图

重写的LinearLayout如下:为了突出重点,不重要的代码部分我用浅灰色显示了。

<span style="color:#999999;">package ex.oyyj.listviewfulldemo;import android.animation.Animator;import android.animation.ObjectAnimator;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.MotionEvent;import android.view.ViewParent;import android.widget.LinearLayout;/** * Created by oyyj on 2015/8/6. */public class HorizontalSlideLayout extends LinearLayout {private static String TAG = "VerticalSlideLayout";private int DRAG_X_THROD = 0;private int SCROLL_X = 0;private final int ANIM_DURATION = 300;private static final int SLIDE_TO_LEFT = -1;private static final int SLIDE_TO_RIGHT = 1;private int mSlideDirection = 0;public HorizontalSlideLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);//判断横划的阈值,为了兼容不同尺寸的设备,以dp为单位DRAG_X_THROD = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, context.getResources().getDisplayMetrics());SCROLL_X = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, context.getResources().getDisplayMetrics());}public HorizontalSlideLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public HorizontalSlideLayout(Context context) {this(context, null, 0);}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();}int downX, downY;boolean isNeedToGoBack;private ObjectAnimator mAnimator;@Overridepublic boolean onTouchEvent(MotionEvent ev) {boolean isInterceptHere = false;try {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:downX = (int) ev.getX();downY = (int) ev.getY();isInterceptHere = true;if (mAnimator != null) {mAnimator.cancel();}break;case MotionEvent.ACTION_MOVE:int dx = (int) Math.abs(ev.getX() – downX);int dy = (int) Math.abs(ev.getY() – downY);if (dx > dy && dx > DRAG_X_THROD) {Log.i(TAG, "横划!拦截它");</span><strong> setParentInterceptTouchEvent(true);</strong><span style="color:#999999;">isInterceptHere = true;mSlideDirection = (ev.getX() – downX) > 0 ? SLIDE_TO_RIGHT : SLIDE_TO_LEFT;if (mSlideDirection == SLIDE_TO_LEFT) {isNeedToGoBack = true;playAnimation(SCROLL_X, ANIM_DURATION);} else if (mSlideDirection == SLIDE_TO_RIGHT && isNeedToGoBack) {playAnimation(0, ANIM_DURATION);}} else if (dy > dx) {Log.i(TAG, "竖划!不拦截");}break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:</span><strong>setParentInterceptTouchEvent(false);</strong><span style="color:#999999;">isInterceptHere = false;downX = 0;downY = 0;break;}} catch (Exception e) {e.printStackTrace();}return isInterceptHere;}private void playAnimation(int translationX, int duration) {if (mAnimator != null) {mAnimator.cancel();}mAnimator = ObjectAnimator.ofInt(this, "scrollX", translationX);mAnimator.setDuration(duration);mAnimator.start();mAnimator.addListener(listener);}</span><strong> /* 这个函数很重要,请求禁止父容器拦截触摸事件 */public void setParentInterceptTouchEvent(boolean disallow) {ViewParent parent = getParent();if (parent != null) {parent.requestDisallowInterceptTouchEvent(disallow);}}</strong><span style="color:#999999;">Animator.AnimatorListener listener = new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animator) {}@Overridepublic void onAnimationEnd(Animator animator) {mAnimator = null;}@Overridepublic void onAnimationCancel(Animator animator) {mAnimator = null;}@Overridepublic void onAnimationRepeat(Animator animator) {}};}</span>

贴上详细调用代码:每一发奋美文努力的背后,必有加倍的赏赐。

Android中不同方向嵌套滑动的解决方案(ListView为例子)

相关文章:

你感兴趣的文章:

标签云: