欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-20 08:15:46
android在嵌套滑动的时候会产生滑动冲突。之前我也碰到,但是以前的笔记本丢失了,所以只能重新再写一章。 一.会产生滑动冲突的情况 那么什么时候会产生滑动冲突呢?比如...

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

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

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

二.以前的做法

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

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

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

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

三.现在的做法

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

1.布局只嵌套recyclerview的情况

就是如下图的情况:

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

这种情况最容易解决,就直接使用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等可滑动控件的情况

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

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

其实我之前写过一篇文章能解决这种情况,那就是使用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接口中有这些方法。

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

你需要在这些方法里面自己写上处理滑动冲突的逻辑,你可以参考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属性。

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

上一篇:

下一篇: