ScrollView和Fragment中的ListView、WebView滑动冲突问题的解决

        日常开发中很少会碰到ScrollView中嵌套listview或webview的情况,而且谷歌官方也不推荐这么做,但是也不是一定不会有这样的需求,毕竟定需求的不是我们程序员,而是产品经理。比如像下面这种需求:
       可以看到,整个页面有一个共同的头部,下面有两个tab,左边tab下是个可以滚动的webview,右边是个listview。要求listview和webview在默认情况下不滚动,但外部整个页面可以滚动,当外层页面滚动到底部时,也就是两个tab的位置大概位于actionbar下方的时候,要求listview和webview自己能滑动而外层不动,当listview或webview下拉到顶部时,又让外层接管滑动,此时共同的头部可以拉下来。
        碰到这种情况,一般的情况肯定是外层套个scrollview,两个tab里分别放个fragment,左右两个fragment分别放置listview。但是很不幸,这样做之后发现listview根本连显示都显示不了,更别提可以滑动了。读者一试便知。原因就在与scrollview和listview存在滑动事件的冲突,那么如何解决这个问题呢?网上有人给出了一个方法:手动计算listview的高度然后显示地设置他的高度。你只需要在listview.setAdapter()方法后调用如下代码:
   
   
   
  1. public void setListViewHeightBasedOnChildren(ListView listView) {
  2. ListAdapter listAdapter = listView.getAdapter();
  3. if (listAdapter == null) {
  4. return;
  5. }
  6. int totalHeight = 0;
  7. for (int i = 0; i < listAdapter.getCount(); i++) {
  8. View listItem = listAdapter.getView(i, null, listView);
  9. listItem.measure(0, 0);
  10. totalHeight += listItem.getMeasuredHeight();
  11. }
  12. ViewGroup.LayoutParams params = listView.getLayoutParams();
  13. params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
  14. Log.d(TAG, "params.height: "+params.height);
  15. listView.setLayoutParams(params);
  16. }
        很不幸!这段代码只有在没有fragment的情况下才有效果,现在的情况是scrollview在宿主Activity中,而listview却在其中一个fragment中,按理说fragment也是放在Activity中那就相当于listview也在Activity中,但是实际情况就是显示不出来listview,具体什么原因我暂时也不清楚。
        那既然在没有fragment的情况下才可以显示listview,那如果不用fragment怎么达到上述切换的效果呢?很简单!在Activity中切换的位置放置个空的容器FrameLayout,然后在切换tab的时候动态添加进想要的view,无论是webvie还是listview甚至是更复杂的view。其实在fragment出现之前,解耦Activity就采用的是这中方式。
我们采用mvc的思想抽象出一个controller基类,功能类似于一个简单的fragment,里面可以绑定view视图和model数据。
   
   
   
  1. public abstract class BaseController
  2. {
  3. public View mRootView;
  4. public Context mContext;
  5. public BaseController(Context context){
  6. this.mContext = context;
  7. // 在构造中 就加载显示的view
  8. mRootView = initView(context);
  9. }
  10. /**
  11. * 初始化view的方法让子类去实现
  12. * @return
  13. */
  14. protected abstract View initView(Context context);
  15. /**
  16. * 加载数据的方法,子类可以实现,也可以不实现
  17. */
  18. public void initData(){
  19. }
  20. /**
  21. * 暴露出去的获得根view的方法
  22. * @return
  23. */
  24. public View getRootView()
  25. {
  26. return mRootView;
  27. }
  28. }
        然后继承这个基类分别创建LeftController 和 RightController,我们先以RightController为例,来把显示listview显示出来。
   
   
   
  1. public class RightController extends BaseController {
  2. private static final String TAG = "RightController";
  3. private ListView mListView;
  4. private List<String> mDatas;
  5. public RightController(Context context) {
  6. super(context);
  7. }
  8. @Override
  9. protected View initView(Context context) {
  10. // TextView readView = new TextView(context);
  11. // readView.setText("right-页面");
  12. View rootView = View.inflate(context, R.layout.controller_right, null);
  13. mListView = (ListView) rootView.findViewById(R.id.lv);
  14. prepareData();
  15. RightAdapter rightAdapter = new RightAdapter(context, mDatas);
  16. mListView.setAdapter(rightAdapter);
  17. setListViewHeightBasedOnChildren(mListView);
  18. return rootView;
  19. }
  20. private void prepareData() {
  21. mDatas = new ArrayList<>();
  22. for (int i = 0; i < 20; i++) {
  23. mDatas.add("item_" + i);
  24. }
  25. }
  26. /**
  27. * 在scrollview中完整显示listview
  28. *
  29. * @param listView
  30. */
  31. public void setListViewHeightBasedOnChildren(ListView listView) {
  32. ListAdapter listAdapter = listView.getAdapter();
  33. if (listAdapter == null) {
  34. return;
  35. }
  36. int totalHeight = 0;
  37. // for (int i = 0; i < listAdapter.getCount(); i++) {
  38. for (int i = 0; i < 10; i++) {
  39. View listItem = listAdapter.getView(i, null, listView);
  40. listItem.measure(0, 0);
  41. totalHeight += listItem.getMeasuredHeight();
  42. }
  43. ViewGroup.LayoutParams params = listView.getLayoutParams();
  44. params.height = totalHeight + (listView.getDividerHeight() * 5);// (listAdapter.getCount() - 1));
  45. Log.d(TAG, "params.height: "+params.height);
  46. listView.setLayoutParams(params);
  47. }
  48. }
        而在Activity的tab切换事件中只需这样两句代码即可把controller的view动态添加进Activity中:
   
   
   
  1. @Override
  2. public
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值