ScrollView+ViewPager+Fragment问题整理

ScrollView+ViewPager+Fragment数据不显示/不完全显示的冲突


      自己在搭建框架的时候习惯使用viewpager+fragment 下面的三个问题只要用到scrollview就经常会遇见的,总是没有整理,总结过,每次忘了就是查,查了直接就过去了,今天翻看大神的博客,发现他总结的特别好,

问题分析

出现问题有几种:

1.ListView数量仅仅显示一条:
出现原因:

在ScrollView中嵌套ListView空间,无法正确的计算ListView的大小,故可以通过代码,根据当前的ListView的列表项计算列表的尺寸。

解决方法:

1.取消ScrollView+ListView的布局,改为使用ListView.addHeaderView,为listView添加头布局。


2.重写ListView的onMeasure方法,使得根据当前的ListView的列表项计算列表的尺寸并展示。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
            MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, expandSpec);
}

重写一个继承ListView的MyListView,这样做也有一个弊端,就是ListView的item复用就成了摆设,在使用listview承载大量item的时候,要考虑周全选择合适的方式解决问题,推荐使用第一种

2.ListView数据不显示:
出现原因:

log显示,数据源是有数据的,但就是listView没有展示,通过各种调试,发现当ScrollView的子布局为Linearlayout(包裹textview+viewpager)时,ListView数据无法展示,但改为使用RelativeLayout时没有任何问题。

解决方法:

将ScrollView的子布局改为RelativeLayout.

主界面代码如下(请注意里面有自定义的view,仅供参考,不能直接复制粘贴使用):

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mei_husky.testtab.MainActivity">


    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <!--必须用相对布局 线性布局不显示!-->
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:id="@+id/tv_hide"
                android:layout_width="wrap_content"
                android:layout_height="95dp" />
            <com.mei_husky.testtab.view.CustomViewPager
                android:layout_below="@id/tv_hide"
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"></com.mei_husky.testtab.view.CustomViewPager>
        </RelativeLayout>

    </ScrollView>

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

        <!--放置点击穿透-->
        <TextView
            android:clickable="true"
            android:background="#44ffffff"
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:text="这是标题栏"
            android:textSize="18sp"
            android:gravity="center"
            />

        <android.support.design.widget.TabLayout
            android:id="@+id/tab"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:background="#ffffffff"
            ></android.support.design.widget.TabLayout>
    </LinearLayout>
    </FrameLayout>

2.Fragment+RecyclerView(ListView或GridView)

RecyclerView的好处是能够比较方便的进行不同种类布局展示的切换,相对麻烦一些就是config的设置和监听的实现

使用了listView或者GridView时,不可避免遇到一个问题,

ScrollView嵌套ListView不在最顶部显示的问题

问题分析

在布局中我们可以了解到,包含listview的ViewPager所在布局的上方还有一个空白的TextView,两者同在一个ScrollView的子布局下,因此在展示界面时,空白的TextView理应在(0,0)的位置上,但实际上确实空白的TextView被挤上去了,listView直接在(0,0)的位置上,只有下拉,我们才能看到我们所设置的textview,显然这是不合适的。

出现问题的效果如下:

出现原因:

个人猜测:Scroll包含ListView时,在展示界面时,ListView抢夺了ScrollView的焦点,因此直接以listView的左上角为(0,0)点展示在界面上。GridView,RecyclerView同理。

解决方法:

解决方案有两种:

1.设置myScrollView.smoothScrollTo(0,20);在数据展示完毕之后,使ScrollView直接跳转到顶部的位置。

2.设置ListView.setFocusable(false);相对应的ListView(GridView&RecyclerView),使其展示数据不获得焦点。

这两种解决方案经过笔者实践,都是可以解决问题的。笔者推荐两种方案同时使用,因为在这个项目中我们的SrcollView和ListView的逻辑是不在一个界面的(ScrollView的处理逻辑在MainActivity中,而listView则是在ViewPager中的fragment对象中做的处理)。

因此,以防万一,笔者在MainActivity中的onResume()方法中添加myScrollView.smoothScrollTo(0,20);在Fragment中添加了ListView.setFocusable(false);

这样做是考虑到,后续的下拉刷新或者分页等功能的实现做准备,因为下拉刷新或者分页功能,不需要处理ScrollView的逻辑,因此直接处理listView的adapter和数据源即可。两种方案的同时使用,为后面功能的拓展提供了方便,而不需要再次处理类似的问题。

*ps:ScrollView包裹listView同样也会触发另外一个弊端,就是listView无法直接获取滑动事件(因为滑动被ScrollView消费了)

3.调试时的小问题

通过设置一个简单的数据源和adapter,我们可以将数据展示在界面上,同时,通过

android:background="#44ffffff" //为了显示效果此处透明度为44,推荐透明度为ee或dd

将标题栏设置为半透明的,在拖动listView(实际上是拖动ScrollView)的同时,listView的item也可以通过半透明的标题栏看到。我们给listView的item设置点击事件,弹出吐司提示条目的position值。

但是这样还出现了了一个问题,我们假设这样一种情况,标题栏上有一些button,比如搜索或者返回按钮,用户点击按钮实现相对应的功能。但是如果用户误操作,没有点到按钮,而是点到了标题栏其他的地方,这时,标题栏的正下方是listView的item,会发生什么情况呢?

2.FrameLayout/LinearLayout或其他布局点击穿透(click through)问题

出现原因:

显然这不是我们所想达到的效果,我们所希望的是,用户点击按钮,实现对应功能,点击标题栏其他地方,也不会触发listView中item的点击事件。

解决方法:

在xml布局文件中给标题栏的根部局中添加一行代码

  android:clickable="true"

使得该布局在收到点击事件时,直接消费该事件,而不会将点击事件传给下一个weight。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值