有关Scrollview嵌套ListView的那些事

有关Scrollview嵌套ListView的那些事

同样作为滑动控件的scrollview与listview,似乎本不应该嵌套使用,可作为研发的我们通常无法左右UI妹子们的奇(fan)思(ren)妙(lei)想。作为一个负责任的研发,必须时刻做好兵来将挡的准备。
首先我们来看这样一张设计稿:
经过Ps合成的设计稿

整个页面整体是一个带下拉刷新的布局,这里用到了被大家最广泛使用的PullToRefreshLayout,同时由于UI设计风格的不断演变,这个页面的内容也不断增多,于是乎在PullToRefreshLayout内部又放了一个Scrollview来滑动显示更多内容,在最近的一期任务中,新增了车辆操作记录这一项,即图片最下方的那个listview,于是乎这一个小小的页面竟然嵌套了PullToRefreshLayout ,Scrollview 与ListView三个滑动控件。
起初接到设计的时候并没有觉得什么,无非就是再加一个ListView么,简单的很,直接开码,item布局,adapter,分分钟搞定,当服务端接口开发完成,准备联调的时候,瞬间傻眼。无论接到的返回体数组的size为几,listview的显示永远只是可怜的一条。经过一番调查终于发现当listview嵌套在Scrollview中时无法正确计算自己的高度,无法正确计算listview实际的高度,但确刚刚好显示了一条数据,那是不是意味着可以通过listview的adapter获取item的个数,然后根据总item个数与单个item的高度计算出listview的实际高度呢?

手动计算listview高度

    public void setListViewHeightBasedOnItem(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            return;
        }
        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            if (null != listItem) {
                listItem.measure(0, 0);
                totalHeight += listItem.getMeasuredHeight();
            }

        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }

退出程序,Shift+F10,回车
再次观察运行结果,Perfect,listview的高度被完美的计算出来了。然而帅不过三秒,又出现了新的问题,那就是由于页面内容过多超出了一屏,导致每次进入这个页面,scrollview都自动滚动到了底部,这是什么鬼,好在还没有交付测试组,赶紧整改。
起初走了一些弯路,以为是scrollview的问题,于是写了一个手动让scrollview滑动到顶部的方法。

当开始layout的时候让scrollview滑动到顶部

scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    scrollView.post(new Runnable() {
                        public void run() {
                            scrollView.fullScroll(ScrollView.FOCUS_UP);
                                Glide.with(context).load(viewData.pictureUrl)
                                        .error(context.getResources().getDrawable(R.drawable.bg_nopicture_loading))
                                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                                        .placeholder(context.getResources().getDrawable(R.drawable.bg_nopicture_loading))
                                        .fitCenter()
                                        .dontAnimate()
                                        .into(viewAdapter.carPicture);
                            viewAdapter.parent.setVisibility(View.VISIBLE);
                        }
                    });
                }
            });

但这不是正路,顶多算是野路子,作为一个追求真理的好少年,这种方法当然不可行。最后在不懈努力之下,找到了原因,还是源于嵌套滑动。因为listview是一个滑动控件,具有滑动属性,所以,在手动计算listview高度的时候listview获取焦点,在listview滑动的驱动下,页面滑动到了listview的底部。解决方案是将listview不获取焦点。

让listview不获取焦点

        viewController.getActionListView().setFocusableInTouchMode(false);
        viewController.getActionListView().setFocusable(false);

我们还有第二种方法:

让顶部view获取焦点

    public static void scrollToTop(View view){
        view.setFocusable(true);
        view.setFocusableInTouchMode(true);
        view.requestFocus();
    }

让页面最上边的view获取焦点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值