View滑动冲突解决方案

作者: Tom_Ji | 来源:发表于2019-01-08 23:16 被阅读26次

滑动冲突产生的原因:只要在界面中存在内外两层可以同时滑动,就会产生滑动冲突。
解决方案:根据实际情况,判断到底需要谁去响应滑动事件。

1.外部为左右滑动,内部为上下滑动

滑动冲突1.png

首先看已经解决过滑动冲突的情况,是可以很顺利的实现左右滑动和上下滑动的。

外部水平滑动,内部垂直滑动.gif

而没有处理滑动冲突的情况下,是不能够响应外部的左右滑动的。

存在滑动冲突.gif

这两种情况的根本区别在于左右滑动布局的onInterceptTouchEvent方法,添加了判断逻辑是否需要进行拦截滑动事件。

            case MotionEvent.ACTION_MOVE:
                int deltaX = x - mLastXIntercept;
                int deltaY = y - mLastYIntercept;
                //判断是否为水平滑动,水平滑动则拦截处理
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                }
                else {
                    intercepted = false;
                }
                break;

主要的判断逻辑是,水平方向滑动的距离大于竖直方向,则认为是水平滑动,需要拦截事件,否则认为是竖直滑动,不需要拦截事件,即交由listview去处理。虽然任玉刚老师的git上有随书的代码,但是很多童鞋也是比较忙,没有时间去下载,我这里就附上用到的代码,其中自己添加了一些注释,也是便于我自己的学习。

自定义左右滑动的类,这里叫做MyViewPage.java


package com.tom.viewdemo.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * <p>Title: MyViewPage</p>
 * <p>Description: </p>
 *
 * @author tom
 * @date 2018/12/29 08:38
 **/
public class MyViewPage extends ViewGroup {

    public static final String TAG = "MyViewPage";

    //子view的数量
    private int mChildrenCount;
    //子View的宽度
    private int mChildWidth;
    private int mChildIndex;

    // 分别记录上次滑动的坐标
    private int mLastX = 0;
    private int mLastY = 0;
    // 分别记录上次滑动的坐标(onInterceptTouchEvent)
    private int mLastXIntercept = 0;
    private int mLastYIntercept = 0;

    private Scroller mScroller;
    //追踪屏幕触摸事件的速度
    private VelocityTracker mVelocityTracker;

    public MyViewPage(Context context) {
        super(context);
        init();
    }

    public MyViewPage(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyViewPage(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * <p>初始化相关参数</p>
     */
    private void init() {
        mScroller = new Scroller(getContext());
        mVelocityTracker = VelocityTracker.obtain();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                intercepted = false;
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                    intercepted = true;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - mLastXIntercept;
                int deltaY = y - mLastYIntercept;
                //判断是否为水平滑动,水平滑动则拦截处理
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                }
                else {
                    intercepted = false;
                }
                break;
            default:
                break;

        }

        Log.d(TAG, "intercepted = " + intercepted);
        mLastX = x;
        mLastY = y;
        mLastXIntercept = x;
        mLastYIntercept = y;

        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mVelocityTracker.addMovement(event);
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    //停止动画
                    mScroller.abortAnimation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - mLastX;
                scrollBy(-deltaX, 0);

                break;
            case MotionEvent.ACTION_UP:
                int scrollX = getScrollX();
                mVelocityTracker.computeCurrentVelocity(1000);
                float xVelocity = mVelocityTracker.getXVelocity();
                if (Math.abs(xVelocity) >= 50) {
                    mChildIndex = xVelocity > 0 ? mChildIndex - 1 : mChildIndex + 1;
                }
                else {
                    mChildIndex = (scrollX + mChildWidth / 2) / mChildWidth;
                }
                mChildIndex = Math.max(0, Math.min(mChildIndex, mChildrenCount - 1));
                int dx = mChildIndex * mChildWidth - scrollX;
                smoothScrollBy(dx, 0);
                mVelocityTracker.clear();
                break;
            default:
                break;
        }

        mLastX = x;
        mLastY = y;
        return true;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int measuredWidth = 0;
        int measuredHeight = 0;
        final int childCount = getChildCount();
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        int widthSpaceSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSpaceSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

        //没有子View
        if (childCount == 0) {
            setMeasuredDimension(0, 0);
        }
        else if (heightSpecMode == MeasureSpec.AT_MOST) {
            final View childView = getChildAt(0);
            measuredHeight = childView.getMeasuredHeight();
            setMeasuredDimension(widthSpaceSize, measuredHeight);
        }
        else if (widthSpecMode == MeasureSpec.AT_MOST) {
            final View childView = getChildAt(0);
            measuredWidth = childView.getMeasuredWidth() * childCount;
            setMeasuredDimension(measuredWidth, heightSpaceSize);
        }
        else {
            final View childView = getChildAt(0);
            measuredHeight = childView.getMeasuredHeight();
            measuredWidth = childView.getMeasuredWidth() * childCount;
            setMeasuredDimension(measuredWidth, measuredHeight);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childLeft = 0;
        //获取子 View 的数量
        final int childCount = getChildCount();
        mChildrenCount = childCount;

        for (int i = 0; i < childCount; i++) {
            final View childView = getChildAt(i);
            //判断可见性不为GONE
            if (childView.getVisibility() != View.GONE) {
                final int childWidth = childView.getMeasuredWidth();
                mChildWidth = childWidth;
                childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight());
                childLeft += childWidth;
            }

        }
    }

    private void smoothScrollBy(int dx, int dy) {
        mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }

    }

    @Override
    protected void onDetachedFromWindow() {
        mVelocityTracker.recycle();
        super.onDetachedFromWindow();
    }
}

这部分代码我也没有仔细的去研读,只是把和滑动冲突有关的看了下,后面学习到《View的工作原理》这一章,再好好过一遍代码。

布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.tom.viewdemo.ui.MyViewPage
        android:id="@+id/container"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"/>

</android.support.constraint.ConstraintLayout>

布局文件content_layout.xml 这个文件就定义了一个title和一个listview,title用来显示是第几页,listview用来竖直方向的滑动。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:gravity="center"
        />

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#fff4f7f9"
        android:cacheColorHint="#00000000"
        android:divider="#dddbdb"
        android:dividerHeight="1.0px"
        android:listSelector="@android:color/transparent" />

</LinearLayout>


布局文件content_list_item.xml 用于listview每一行的展示。也可以使用系统自带的布局文件,只是一个demo,用什么都ok。


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="50dp"
              android:gravity="center_vertical"
              android:orientation="vertical">

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

主文件MainActivity.java 这里使用了ButterKnife插件,基本用法可以在仿QQ未读消息的动画效果中找到,也可以自行搜索。


package com.tom.viewdemo;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.tom.viewdemo.ui.MyViewPage;

import java.util.ArrayList;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

public class MainActivity extends AppCompatActivity {

    Unbinder mBinder;

    @BindView(R.id.container)
    MyViewPage mContainer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBinder = ButterKnife.bind(this);
        initViews();
    }

    private void initViews() {

        LayoutInflater inflater = getLayoutInflater();
        //获取屏幕的宽度,因为这两个值为固定值(同一设备),所以使用final关键字
        final int screenWidth = getScreenMetrics(this).widthPixels;

        //添加3页
        for (int i = 0; i < 3; i++) {
            ViewGroup layout;
            layout = (ViewGroup) inflater.inflate(
                    R.layout.content_layout, mContainer, false);
            //设置宽度为屏幕宽度
            layout.getLayoutParams().width = screenWidth;
            TextView textView = layout.findViewById(R.id.title);
            textView.setText("第 " + (i + 1) + " 页");
            layout.setBackgroundColor(Color.rgb(255 / (i + 1), 255 / (i + 1), 0));
            createList(layout);
            mContainer.addView(layout);
        }



    }

    /**
     * <p>创建 listView </p>
     * @param layout 父布局
     */
    private void createList(ViewGroup layout) {
        ListView listView = layout.findViewById(R.id.list);
        ArrayList<String> datas = new ArrayList<>();
        //填充测试数据
        for (int i = 0; i < 50; i++) {
            datas.add("name " + i);
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                R.layout.content_list_item, R.id.name, datas);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                Toast.makeText(MainActivity.this, "click item",
                        Toast.LENGTH_SHORT).show();

            }
        });

    }

    /**
     * <p>获取设备屏幕信息</p>
     * @param context
     * @return
     */
    private DisplayMetrics getScreenMetrics(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        return dm;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBinder.unbind();
    }


}

2.滑动方向一致,以竖直方向为例

滑动冲突2.png

这种情况的产生其实还是比较常见的,比如外部是一个竖直方向的scrollView,里面嵌套了一个listView等,处理的原则也是,根据实际需要,判断父容器是否需要拦截事件即可。

在布局文件中使用如下布局activity_demo.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main3Activity"
    >


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >


        <TextView
            android:id="@+id/top"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#00da00"
            android:gravity="center"
            android:text="头部"
            />

        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:layout_below="@id/top"
            />


        <TextView
            android:id="@+id/bottom"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_below="@id/list"
            android:background="#00da00"
            android:gravity="center"
            android:text="底部"/>
    </RelativeLayout>


</ScrollView>

这时的运行结果如图所示:

scrollView显示问题.png

可以看到,并没有按照布局文件的预期结果,显示“头部”,并且listView是无法滑动的。要让布局文件显示正确,只需要在Activity中添加如下代码。

mScrollView.smoothScrollTo(0,0);

接下来处理滑动冲突,需求是点击的如果是listView,则让listView滑动。需要重写ScrollViewonInterceptTouchEvent方法。这里给出重写后的MyScrollView.java文件。

package com.tom.viewdemo.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
import android.widget.ScrollView;

/**
 * <p>Title: MyScrollView</p>
 * <p>Description: </p>
 *
 * @author tom
 * @date 2019/1/8 10:56
 **/
public class MyScrollView extends ScrollView {

    private ListView mListView;

    public ListView getListView() {
        return mListView;
    }

    public void setListView(ListView listView) {
        mListView = listView;
    }

    public MyScrollView(Context context) {
        super(context);
    }

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //如果点击的范围在listView内,则由listView来处理
        if (mListView != null && checkArea(mListView,ev)) {
            return false;
        }

        return super.onInterceptTouchEvent(ev);
    }

    /**
     * <p>判断点击位置是否在view的范围内</p>
     * @param view
     * @param ev
     * @return
     */
    private boolean checkArea(View view, MotionEvent ev) {
        //获取点击位置的绝对坐标,相对屏幕左上角的位置
        float x = ev.getRawX();
        float y = ev.getRawY();
        int[] locate = new int[2];
        view.getLocationOnScreen(locate);
        int left = locate[0];
        int right = left + view.getWidth();
        int top = locate[1];
        int bottom = top + view.getHeight();

        if (x > left && x < right && y > top && y < bottom) {
            return true;
        }
        return false;
    }
}

把布局文件的ScrollView替换为MyScrollView,同时在ScrollDemoActivity.java文件中添加mScrollView.setListView(mList);

ScrollDemoActivity.java文件如下:


package com.tom.viewdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.tom.viewdemo.ui.MyScrollView;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

public class ScrollDemoActivity extends AppCompatActivity {

    Unbinder mBinder;
    @BindView(R.id.list)
    ListView mList;
    @BindView(R.id.scrollView)
    MyScrollView mScrollView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        mBinder = ButterKnife.bind(this);
        mScrollView.smoothScrollTo(0, 0);
        mScrollView.setListView(mList);
        initListData();
    }

    private void initListData() {

        List<String> dataList = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            dataList.add("tom" + i);
        }

        ArrayAdapter arrayAdapter = new ArrayAdapter(ScrollDemoActivity.this, android.R.layout.simple_list_item_1,android.R.id.text1, dataList);
        mList.setAdapter(arrayAdapter);

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBinder.unbind();
    }
}

此时滑动冲突问题已经解决,效果图如下。

解决滑动冲突-不完全版.gif

虽然已经解决了滑动冲突的问题,ListView可以滑动,ScrollView也可以滑动,但是当ListView滑动到底部或者顶部时,我是希望ScrollView可以接着滑动,因此进行如下修改。

滑动冲突解决优化改良版

重写listView里的dispatchTouchEvent方法,在移动时判断ListView是否可以继续滑动(根据滑动方向判断),如果不能滑动,则由ScrollView滑动。

MyListView.java

package com.tom.viewdemo.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;

/**
 * <p>Title: MyListView</p>
 * <p>Description: </p>
 *
 * @author tom
 * @date 2019/1/8 16:14
 **/
public class MyListView extends ListView {

    private float mLastY;

    public MyListView(Context context) {
        super(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //拦截down事件,由 listView 来处理
                getParent().getParent().requestDisallowInterceptTouchEvent(true);

                break;
            case MotionEvent.ACTION_MOVE:

                //向上滑动
                if (mLastY > ev.getY()) {
                    //滑动到listView的底部了,手指无法继续向上滑动,即listView无法向下滑动,则交由父布局处理
                    if (!canScrollList(1)) {
                        getParent().getParent().requestDisallowInterceptTouchEvent(false);
                        return false;
                    }

                }
                //向下滑动
                else if (mLastY < ev.getY()) {
                    //滑动到listView的顶部了,手指无法继续向下滑动,即list View无法向上滑动,则交由父布局处理
                    if (!canScrollList(-1)) {
                        getParent().getParent().requestDisallowInterceptTouchEvent(false);
                        return false;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                getParent().getParent().requestDisallowInterceptTouchEvent(false);
                break;
        }

        mLastY = ev.getY();
        return super.dispatchTouchEvent(ev);
    }
}

ListView里的canScrollList()方法用来判断是否能够继续滑动,可以查看源码里的注释。


    /**
     * Check if the items in the list can be scrolled in a certain direction.
     *
     * @param direction Negative to check scrolling up, positive to check
     *            scrolling down.
     * @return true if the list can be scrolled in the specified direction,
     *         false otherwise.
     * @see #scrollListBy(int)
     */

如果传入的参数为负,则检查listView是否可以向上滑动;为正,检查listView是否可以向下滑动。如果分不清楚向上还是向下,可以根据listviewscrollBar的运动方向来判断,或者理解为和手指的运动方向相反

MyScrollView.java


package com.tom.viewdemo.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
import android.widget.ScrollView;

/**
 * <p>Title: MyScrollView</p>
 * <p>Description: </p>
 *
 * @author tom
 * @date 2019/1/8 10:56
 **/
public class MyScrollView extends ScrollView {

    private ListView mListView;

    public ListView getListView() {
        return mListView;
    }

    public void setListView(ListView listView) {
        mListView = listView;
    }

    public MyScrollView(Context context) {
        super(context);
    }

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //如果点击的范围在listView内,则由listView来处理
//        if (mListView != null && checkArea(mListView,ev)) {
//            return false;
//        }

        //滑动冲突改良版
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onTouchEvent(ev);
            return false;
        }

        return super.onInterceptTouchEvent(ev);
    }

    /**
     * <p>判断点击位置是否在view的范围内</p>
     * @param view
     * @param ev
     * @return
     */
    private boolean checkArea(View view, MotionEvent ev) {
        //获取点击位置的绝对坐标,相对屏幕左上角的位置
        float x = ev.getRawX();
        float y = ev.getRawY();
        int[] locate = new int[2];
        view.getLocationOnScreen(locate);
        int left = locate[0];
        int right = left + view.getWidth();
        int top = locate[1];
        int bottom = top + view.getHeight();

        if (x > left && x < right && y > top && y < bottom) {
            return true;
        }
        return false;
    }
}

MotionEvent.ACTION_DOWN必须要让给ListView,这样ListView才能判断自己是否还能滑动,因为ScrollView的滑动需要在MotionEvent.ACTION_DOWN时做一些准备,因此需要主动调用一次onTouchEvent()方法。

ScrollDemoActivity.java

package com.tom.viewdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;

import com.tom.viewdemo.ui.MyListView;
import com.tom.viewdemo.ui.MyScrollView;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

public class ScrollDemoActivity extends AppCompatActivity {

    Unbinder mBinder;
    @BindView(R.id.list)
    MyListView mList;
    @BindView(R.id.scrollView)
    MyScrollView mScrollView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        mBinder = ButterKnife.bind(this);
        mScrollView.smoothScrollTo(0, 0);
        mScrollView.setListView(mList);
        initListData();
    }

    private void initListData() {

        List<String> dataList = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            dataList.add("tom" + i);
        }

        ArrayAdapter arrayAdapter = new ArrayAdapter(ScrollDemoActivity.this, android.R.layout.simple_list_item_1,android.R.id.text1, dataList);
        mList.setAdapter(arrayAdapter);

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBinder.unbind();
    }
}

布局文件activity_demo.xml


<?xml version="1.0" encoding="utf-8"?>
<com.tom.viewdemo.ui.MyScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ScrollDemoActivity"
    >


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >


        <TextView
            android:id="@+id/top"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#00da00"
            android:gravity="center"
            android:text="头部"
            />

        <com.tom.viewdemo.ui.MyListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:layout_below="@id/top"
            />


        <TextView
            android:id="@+id/bottom"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_below="@id/list"
            android:background="#00da00"
            android:gravity="center"
            android:text="底部"/>
    </RelativeLayout>


</com.tom.viewdemo.ui.MyScrollView>

最后,附上改良版的效果图。

解决滑动冲突-改良版.gif

两种常见的滑动冲突已经解决,主要还是重写父布局的onInterceptTouchEvent()方法,根据具体的业务,来判断需要由谁去处理事件。

相关文章

网友评论

    本文标题:View滑动冲突解决方案

    本文链接:https://www.haomeiwen.com/subject/bxjelqtx.html