Android嵌套滑动冲突的解决方法

android在嵌套滑动的时候会产生滑动冲突。之前我也碰到,但是以前的笔记本丢失了,所以只能重新再写一章。

一.会产生滑动冲突的情况

那么什么时候会产生滑动冲突呢?比如你有个activity,activity的上半部分是一个布局,下半部分是一个可滑动控件(RecyclerView、ListView等),或者下半部分是个viewpager,里面的fragment布局是一个可滑动控件,这样的页面就会产生滑动冲突。

二.以前的做法

虽然我以前的笔记丢失了,但是当时的解决问题的思路我依然记得。

(1)重写一个viewpager继承系统的ViewPager,至于怎么重写的我不太记得了

(2)重写RecyclerView继承系统的RecyclerView,因为我记得会出现高度的原因导致RecyclerView不设置固定高度的话会不显示或者只显示一个Item,所以要重写RecyclerView去动态衡量Item x count 的高度。

当时虽然能解决,但是最后的效果很变扭。

三.现在的做法

现在我肯定不会像之前一样做,因为出了一个新控件NestedScrollView。它能够很好的帮我们解决滑动冲突,接下来我会尽我所能分析所有可能出现的情况。

1.布局只嵌套RecyclerView的情况

就是如下图的情况:

这种情况最容易解决,就直接使用NestedScrollView做父布局,然后嵌套RecyclerView就行。

<android.support.v4.widget.NestedScrollView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:id="@+id/m_nsv"
  android:fillViewport="true"
  xmlns:android="http://schemas.android.com/apk/res/android">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
      android:layout_width="match_parent"
      android:layout_height="150dp"
      android:text="Hello World!" />

    <android.support.v7.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/c_rv"
      >

    </android.support.v7.widget.RecyclerView>

  </LinearLayout>

</android.support.v4.widget.NestedScrollView>

这样就行,切记要记住两点:

(1)在父布局NestedScrollView加android:fillViewport="true",然后RecyclerView会不显示出来,不显示出来的原因是RecyclerView是一个动态展示的View,而直接使用的话用我之前说的话叫做会被压扁,所以加这个属性让子View显示match_parent的效果。

(2)有的人说要给RecyclerView设setNestedScrollingEnabled(false),不然滑动时会卡,这个我没试过,我设的是true,目前感觉滑动时没什么影响。

2.布局嵌套其它可滚动控件的情况

就是在第一种情况下把RecyclerView换成其它可滑动控件。

直接说吧,你要用NestedScrollView才有用,原因是解决滑动冲突的关键在于NestedScrollingParent和NestedScrollingChild两个接口(下面会详细说)

而RecyclerView和NestedScrollView都实现NestedScrollingChild接口,并在内部封装了解决滑动冲突的逻辑处理,所以只有NestedScrollView直接嵌套RecyclerView或NestedScrollView不会产生滑动冲突。

NestedScrollView的用法和RecyclerView一样,记得加那些属性。

3.布局嵌套ViewPager,ViewPager嵌套RecyclerView等可滑动控件的情况

这种情况处理起来比较麻烦,而很多人都是碰到这种情况。如下图:

其实我之前写过一篇文章能解决这种情况,那就是使用CoordinatorLayout,使用CoordinatorLayout能解决这种情况。
但是,我文章里也说过了,CoordinatorLayout有BUG,使用起来卡得像坨屎一样,不管你能不能忍,反正我是不能忍,所以我不会使用CoordinatorLayout。

不用CoordinatorLayout还有以下三种解决办法:

(1)使用github上面开源的那个自定义CoordinatorLayout来解决,叫什么我忘了。

但是我们老大说了,最好别用别人的开源View。于是我只能用第二种方法。

(2)放弃使用ViewPager

为什么,因为系统的ViewPager做不到,上面有说到能解决冲突是因为NestedScrollingParent和NestedScrollingChild,并且NestedScrollingChild的ViewGroup要是实现NestedScrollingParent接口的View,NestedScrollingParent的ChildView要是实现NestedScrollingChild接口的View。

而图中的父布局和RecyclerView隔着一个ViewPager,也就是说NestedScrollingParent的ChildView是ViewPager,NestedScrollingChild的ViewGroup是ViewPager。所以说直接嵌套一层ViewPager的情况是无法解决滑动冲突的。

那有一个很直接的办法就是不用ViewPager,用FragmentManager,这样就能实现解决滑动冲突。

<android.support.v4.widget.NestedScrollView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:fillViewport="true"
  android:id="@+id/nsv"
  app:layout_behavior="@string/appbar_scrolling_view_behavior"
  xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical">

      <LinearLayout
        android:descendantFocusability="blocksDescendants"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="horizontal"
        android:minHeight="10dp"
        android:padding="10dp"
        android:id="@+id/ll_header">

        .........................................

       </LinearLayout>
      </LinearLayout>

      <android.support.v4.widget.NestedScrollView
        android:layout_marginTop="15dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:id="@+id/c_nsv"
        >
        <FrameLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:id="@+id/fl_content"
          >

        </FrameLayout>

      </android.support.v4.widget.NestedScrollView>

    </LinearLayout>
  </android.support.v4.widget.NestedScrollView>

这里的FrameLayout就是给FragmentManager来显示FrameLayout。

这样做就能解决一个activity多个fragment的情况下的滑动冲突。

但是有的朋友说不嘛,我就要Viewpager,我就要酷酷的滑动动画效果。唉,那你就用最实在的第三中方法吧。

(3)自定义

没办法了,那就用自定义吧,自定义一个VIewGroup实现NestedScrollingParent接口,然后自定义一个View实现NestedScrollingChild接口。或者你可以外层使用NestedScrollView,内层自定义ViewPager来实现NestedScrollingChild接口。

你以为这样就完啦?当然没这么简单。在NestedScrollingChild接口中有这些方法。

你需要在这些方法里面自己写上处理滑动冲突的逻辑,你可以参考RecyclerView的去写,也可以在网上找,网上有一些大神是真的有介绍,但也有一些人要么瞎JB抄别人的又不抄完,要么只会说用CoordinatorLayout。我其实也不是很会里面的细节处理,只是知道流程而已,所以也不装X了。

四.其它使用时的问题

并非解决滑动冲突就没有其它问题。

1.NestedScrollView(RecyclerView)重新加载数据时会自动滚动到底部。

如果你碰到这种情况,只要给父布局的NestedScrollView设.scrollTo(0, 0)就行,和ScrollView一样的。

2.禁止滑动。

如果你想在某些情况下禁止NestedScrollView滑动,可以像处理ScrollView一样,在父布局的NestedScrollView加入监听,例如我这:

public void isScroll(boolean bol){
    Nsv.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        return !bol;
      }
    });
  }

这个方法是设置可滑动和不可滑动。

3.记得设android:fillViewport="true"

如果你嵌套的布局没有显示,那有可能你忘了给父布局NestedScrollView设置android:fillViewport属性。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android解决viewpager嵌套滑动冲突并保留侧滑菜单功能

    重写子pagerview的dispatchTouchEvent方法,在返回前添加一句getParent().requestDisallowInterceptTouchEvent(true)中断掉事件的传递,类如下 public class SupperViewPager extends ViewPager { private int screenWidth;//屏幕宽度 public SupperViewPager(Context context) { super(context); } pub

  • Android中RecyclerView嵌套滑动冲突解决的代码片段

    在纵向RecyclerView嵌套横向RecyclerView时,如果纵向RecyclerView有下拉刷新功能,那么内部的横向RecyclerView的横向滑动体验会很差.(只有纯横向滑动时,才能滑动内部的横向RecyclerView,否则滑动事件就会影响到下拉刷新),添加拦截判断. public class MySwipeRefreshLayout extends SwipeRefreshLayout { private boolean mIsVpDragger; private final

  • Android ScrollView嵌套横向滑动控件时冲突问题

    前言:今天在开发的时候遇到这样的问题,最外层是ScrollView,里面嵌套了一个横向滑动的日历控件,在滑动日历的时候很卡顿.看到这种问题,自然而然的就会想到scrollview和其他可滑动控件的冲突问题. 解决思路 用户的左右滑动操作被最外层的scrollView控件处理掉了,所以只要让scrollview对左右滑动事件不监听,让其子控件处理左右滑动事件 .重写scrollview的onInterceptTouchEvent方法,当上下滑动时不处理即可. 代码如下 public void se

  • Android嵌套RecyclerView左右滑动替代自定义view

    以前的左右滑动效果采用自定义scrollview或者linearlayout来实现,recyclerview可以很好的做这个功能,一般的需求就是要么一个独立的左右滑动效果,要么在一个列表里的中间部分一个左右滑动效果 而列表里面也容易,只是需要解决一点小问题,个人认为值得一提的就是高度问题,一般的人采用固定死的高度,可是在列表里面展示和机型的不同,固定死的话很难保证美观,动态的高度才能解决问题的所在 首先在一个列表控件布局上添加一个recyclerview控件 <android.support.v

  • 详解Android中的NestedScrolling机制带你玩转嵌套滑动

    一.概述 Android在support.v4包中为大家提供了两个非常神奇的类: NestedScrollingParent NestedScrollingChild 如果你从未听说过这两个类,没关系,听我慢慢介绍,你就明白这两个类可以用来干嘛了.相信大家都见识过或者使用过CoordinatorLayout,通过这个类可以非常便利的帮助我们完成一些炫丽的效果,例如下面这样的: 这样的效果就非常适合使用NestedScrolling机制去完成,并且CoordinatorLayout背后其实也是利用

  • Android嵌套滑动冲突的解决方法

    android在嵌套滑动的时候会产生滑动冲突.之前我也碰到,但是以前的笔记本丢失了,所以只能重新再写一章. 一.会产生滑动冲突的情况 那么什么时候会产生滑动冲突呢?比如你有个activity,activity的上半部分是一个布局,下半部分是一个可滑动控件(RecyclerView.ListView等),或者下半部分是个viewpager,里面的fragment布局是一个可滑动控件,这样的页面就会产生滑动冲突. 二.以前的做法 虽然我以前的笔记丢失了,但是当时的解决问题的思路我依然记得. (1)重

  • 浅谈Android View滑动冲突的解决方法

    引言 这一篇文章我们就通过介绍滑动冲突的规则和一个实例来更加深入的学习View的事件分发机制. 1.外部滑动方向和内部滑动方向不一致 考虑这样一种场景,开发中我们经常使用ViewPager和Fragment配合使用所组成的页面滑动效果,很多主流的应用都会使用这样的效果.在这种效果中,可以使用左右滑动来切换界面,而每一个界面里面往往又都是ListView这样的控件.本来这种情况是存在滑动冲突的,只是ViewPager内部处理了这种滑动冲突.如果我们不使用ViewPager而是使用ScrollVie

  • 外层竖向ScrollView,里层横向ScrollView滑动冲突的解决方法

    实例如下: public class CustomScrollView extends ScrollView { private GestureDetector mGestureDetector; View.OnTouchListener mGestureListener; @SuppressWarnings("deprecation") public CustomScrollView(Context context,AttributeSet attrs) { super(contex

  • android中view手势滑动冲突的解决方法

    Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是:dispatchTouchEvent.onInterceptTouchEvent和onTouchEvent. public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来进行事件的分发.如果事件传递到view,那么这个方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是

  • Android中DrawerLayout+ViewPager滑动冲突的解决方法

    DrawerLayout 是 Android 官方的侧滑菜单控件,而 ViewPager 相信大家都很熟悉了.今天这里就讲一下当在 DrawerLayout 中嵌套 ViewPager 时,要如何解决滑动冲突的问题,效果如下: 首先,让我们先来解决 DrawerLayout 和 ViewPager 的侧滑事件冲突.当 DrawerLayout 中嵌套 ViewPager 时,侧滑默认是执行 DrawerLayout 的侧滑事件,因为 Android 的事件分发是从 外层 ViewGroup 向里

  • ViewPager2滑动冲突的解决方法

    ViewPager2滑动冲突解决,供大家参考,具体内容如下 本文章对ViewPager2的滑动冲突没有提供完善的解决方案,仅为巩固解决滑动冲突方面的知识 首先看看没有解决滑动冲突时写的demo: MainActivity.java package com.example.banner import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.viewpager2.widget.

  • ScrollView嵌套ListView滑动冲突的解决方法

    ScrollView和ListView这两个控件想必大家都不会陌生,但是这两者嵌套使用的时候就会出现麻烦.比如,我们如果想在ListView下面添加其他的布局或者控件,然后想让它们作为一个整体都可以滑动的话,最常想到的就是用一个ScrollView把它们包裹起来.想法似乎很美好,但是现实就有点残酷了.我们可以写一个小例子体验一下. 首先创建一个Activity,在它的布局文件上放置一个ListView: <?xml version="1.0" encoding="utf

  • Android中listview嵌套scrollveiw冲突的解决方法

    一.使用网上用的动态改变listview高度的方法 该方法只适用于item布局是LinearLayout布局的情况,不能是其他的,因为其他的Layout(如RelativeLayout)没有重写onMeasure(),所以会在onMeasure()时抛出异常.所以使用限制较大. public class Utility { public static void setListViewHeightBasedOnChildren(ListView listView) { //获取ListView对应

  • Android ListView与ScrollView冲突的解决方法总结

    Android ListView与ScrollView冲突的解决方法总结 众所周知ListView与ScrollView都具有滚动能力,对于这样的View控件,当ScrollView与ListView相互嵌套会成为一种问题:  问题一:ScrollView与ListView嵌套导致ListView显示不全面  问题二:ScrollView不能正常滑动 解决方式一: ScrollView+LinearLayout+ListView可以换成ScrollView+LinearLayout+Linear

随机推荐