ScrollView嵌套ListView多种滚动兼容问题的解决

来源:互联网 发布:二级建造师 知乎 编辑:程序博客网 时间:2024/05/16 17:15

一.ScrollView嵌套ListView,只显示一行问题解决

要让ListView显示完整,需要在ListView的数据源赋值后,获取ListViewItem的数量,既可以得到ListView所需的实际高度,然后重新给ListView分配高度即可。此方案可以完美解决显示一行的问题,而且不需要自定义控件即可实现。

    /*     * 根据列表项个数动态设置ListView高度,解决ScrollView嵌套ListView只显示一行问题     */    private void setListViewHeightByItemCount(ListView listView) {        ListAdapter  listAdapter =  listView.getAdapter();        if (listAdapter == null) {            return;        }        int allItemsHeight = 0;        for (int i = 0; i < listAdapter.getCount(); i++) {            View listItem = listAdapter.getView(i, null, listView);            listItem.measure(0, 0);            //获取所有Items的高度和            allItemsHeight += listItem.getMeasuredHeight();        }        //获取ListView中的所有分割线高度和,如果没有则为0        int alldevideLineHeight = (listView.getDividerHeight() * (listAdapter.getCount() - 1));        //给ListView设置高度        ViewGroup.LayoutParams params = listView.getLayoutParams();        params.height = allItemsHeight +alldevideLineHeight;        listView.setLayoutParams(params);    }

注:如果ListView的数据量很大,需要新起一个线程调用此方法,并用Handler同步,这样可加快页面渲染速度

二.仅保留ScrollView的滚动效果,禁用ListView的滚动

1.在ListView上滑动,也触发父类ScrollView的滑动效果方式

应用场景:下拉ListView缩放父类ScrollView中的顶部图片。

要想让ScrollView滚动,只需要让ScrollView子布局高度超出ScrollView的高度即可。如果内容多,超出父类即可实现了,可如果子类布局的高度不足超出父类的ScrollView,该怎么办?提供一个方案,将ScrollView子布局最底部的控件的android:layout_marginBottom="25dp"属性值,调整到一个恰当大的值,即可让ScrollView触发滚动。ListView的高度可以用第一步中提供的方法解决。

2.在ListView滑动,父类ScrollView不会滚动的方式

这种效果,可以让页面保持单屏,但ListView的滑动效果就被终结了,只能触发ScrollView的滚动事件。实现方式就是重写ListView。

package com.today.ui.view;import android.content.Context;import android.util.AttributeSet;import android.widget.ListView;/** * 自定义NoScrollListview *  * @see 防止Listview下滑事件和ScrollView的下滑事件冲突 */public class NoScrollListview extends ListView {    public NoScrollListview(Context context) {        super(context);    }    public NoScrollListview(Context context, AttributeSet attrs) {        super(context, attrs);    }    public NoScrollListview(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    /**     * 重设高度     */    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);        super.onMeasure(widthMeasureSpec, expandSpec);    }}

三.让被嵌套的ListView滑动到顶端,ScrollView才能滚动

1.自定义ListView,支持滑动到顶部时,ScrollView获取滑动权

这种情况可能出现在下拉刷新中,下拉刷新中的自带的ScrollView嵌套LInearLayout再嵌套一个ListView和其他布局的时候,这时候需要对ListView的高度进行计算。

首先要自定义一个支持下拉刷新的ListView,实现当滑动到顶部时候,滑动权交给父类;当ListView的第一项不在顶部的时候,滑动权在ListView手上。

package com.today.ui.view;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ListView;/** * 自定义PullRefreshListView * @see 防止Listview下滑事件和下拉刷新的下滑事件冲突,重写onInterceptTouchEvent事件 */public class PullToRefreshListView extends ListView {    public PullToRefreshListView(Context context) {        super(context);    }    public PullToRefreshListView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        // 判断是否滑动到顶部了        if (getFirstVisiblePosition() == 0 && getChildAt(0).getTop() == 0) {            // 滑动到顶部,父类获取到触摸事件,开始下拉刷新;            getParent().requestDisallowInterceptTouchEvent(false);        } else {            // 没有滑动到头部,父类拦截触摸事件,不会触发下拉刷新            getParent().requestDisallowInterceptTouchEvent(true);        }        return super.onInterceptTouchEvent(ev);    }}

2.设置ListView的高度为ScrollView的剩余高度

这时候不能通过ListView中的Items数量来设置高度了,而要通过计算下拉刷洗的ScrollView的高度,将此高度设为ListView的高度,这样ListView中的Item数量所需的高度,超过ScrollView的高度的时候,就可以实现ListView滚动,而ScrollView不滚动的效果。

这个需要根据自己嵌套的布局个数计算,展示一个例子:一个下拉刷洗中嵌套了多个控件,计算ListView可以使用的高度

/**     * 将页面剩余高度设置为ListView的高度     *      * @param listView     */    private void setRestHeightToListView(ListView listView) {        // 下拉刷新控件的高度,即顶级容器高度        int ptrHeight = mPullRefreshView.getMeasuredHeight();        // 下拉框高度(嵌套了一个下拉框)        int spinnerbarHeight = spinner_city.getMeasuredHeight();        // 标题栏高度(嵌套了一个文本框)        int deviceBarHeight = deviceBar.getMeasuredHeight();        // 分割线高度(嵌套了一个View)        int devideLineHeight = devide_line.getMeasuredHeight();        // ListView可用的剩余高度,即下拉刷新减去下拉框、分割线、标题栏的高度(实际高度计算)        int restHeight = ptrHeight - spinnerbarHeight - devideLineHeight - deviceBarHeight;        // 获取ListView的参数        ViewGroup.LayoutParams params = listView.getLayoutParams();        // 组装参数        params.height = restHeight;        // 设置ListView的高度        listView.setLayoutParams(params);        // ListView代理视图也设置为此高度,即可实现居中显示        listView.getEmptyView().setLayoutParams(params);    }

这一步主要是保证,ListView的高度刚好填满ScrollViewListView就可以滚动了。否则ScrollView就会优先滚动,而ListView就会失去了滑动权。所以高度一定要算对,里面的任何一条细线都不要漏掉,只要ScrollView能滚动,而ListView是固定不动的,这就有可能是你的高度算错了,检查下。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 寄的水果压坏了怎么办 吃了一个烂水果怎么办 孕期吃了烂水果怎么办 邮快递水果坏了怎么办 快递寄水果坏了怎么办 闲鱼买家拒收水果怎么办 洗澡桶里有很多老鼠屎怎么办? 塑料和金属断了怎么办 孕妇吃了沙拉酱怎么办 孕妇淀粉吃多了怎么办 怀孕初期吃了杏怎么办 如果睡觉吃梨了怎么办 怀孕6个月有点贫血怎么办 怀孕八个多月有点贫血怎么办 生完小孩身体虚怎么办 孩子咳嗽厉害怎么办吃什么药 新生儿三天不拉大便怎么办 胃吃的变大了怎么办 小孩长高长的慢怎么办 小孩长高长得慢怎么办 小孩吃东西不吸收营养怎么办 婴儿长得太快怎么办 2个月婴儿长太快怎么办 孩子脚长得太快怎么办 4个月宝宝缺钙怎么办 2个月宝宝不长肉怎么办 小孩子长得不高怎么办 宝宝误吃蜂蜜了怎么办 有人拿着吃完的东西退货怎么办 婴儿个子长的慢怎么办 儿童长得太快怎么办 宝宝个子长太快怎么办 孩子九个月奶水不够怎么办 小孩起热痱子痒怎么办 媳妇生完小孩奶水出不来怎么办 生完孩子下奶疼怎么办 生完小孩没奶水怎么办 孩子半个月奶水越来越少怎么办 半个月后奶水越来越少怎么办 坐月子半个月奶水越来越少怎么办 孩子七个月奶水越来越少怎么办