完美解决Android ListView 和 ScrollView 共存时冲突 问题_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > 完美解决Android ListView 和 ScrollView 共存时冲突 问题

完美解决Android ListView 和 ScrollView 共存时冲突 问题

 2013/11/18 10:20:51  And103  博客园  我要评论(0)
  • 摘要:当同一个页面布局中的ScrollView中包含有ListView时,两个布局由于都有滑动而导致冲突,最明显的特征就是当ListView中有多个子项时,会出现显示不全的情况,只会显示一两个子项。以前查到一个简单的解决办法setListViewHeightBasedOnChildren(ListViewlistView)的那个办法,是测出ListView中每一个子项视图的高度,然后再相加起来,以这个值来设定整个ListView的高度。这种方法的优点是比较简单
  • 标签:android 解决 view list 完美 问题

当同一个页面布局中的ScrollView中包含有ListView时,两个布局由于都有滑动而导致冲突,最明显的特征就是当ListView中有多个子项时,会出现显示不全的情况,只会显示一两个子项。

 

以前查到一个简单的解决办法setListViewHeightBasedOnChildren(ListView listView)的那个办法,是测出ListView中每一个子项视图的高度,然后再相加起来,以这个值来设定整个ListView的高度。这种方法的优点是比较简单,能解决子项视图布局比较简单且文字较少的情况;但不足之处是每次刷新ListView时都要调用这个函数来重新设定ListView的高度,重点是:若子项视图中文字过多,出现文字自动换行的时候,此时测出来的高度就不准确了,难以做到准确设置ListView的高度。

 

这次要介绍的方法虽说有点麻烦,但是相对来说比较治本的方法,其思想是继承并扩展线性布局LinearLayout,用LinearLayout替代ListView来实现ListView的功能和效果。

 

下面是效果示例:

这是修改前的冲突情况(ListView显示只能显示第一行)

 

这是修改后的效果

 

 

本文的实现思想和代码是在

Android 解决ListView ScrollView 共存冲突的问题http://terryblog.blog.51cto.com/1764499/373509

这篇文章的基础上作了少许修改和“添加子项间分隔线、子项点击事件监听”而成的。

 

主要思想是:

给LinearLayout添加BaseAdapter、OnItemClickListener成员,

然后在绑定布局时调用BaseAdapter的getView方法取得子项的视图View,

将此View用addView方法添加进LinearLayout中;

并设置每一个子项视图View的监听点击事件OnClickListener,

在OnClickListener的onClick方法中调用OnItemClickListener的

onItemClick方法,即在将子项的点击事件转发到LinearLayout的onItemClick事件中。

 

下面是用来替代ListViewLinearLayout代码,此LinearLayoutForListView作为自定义控件来替代ListView

用法和ListView的用法一样,使用BaseAdapter来做适配器

  1 package com.and.mine;
  2 
  3 import android.content.Context;
  4 import android.util.AttributeSet;
  5 import android.util.Log;
  6 import android.util.TypedValue;
  7 import android.view.View;
  8 import android.widget.AdapterView.OnItemClickListener;
  9 import android.widget.BaseAdapter;
 10 import android.widget.LinearLayout;
 11 
 12 public class LinearLayoutForListView extends LinearLayout
 13 {
 14     private BaseAdapter adapter;
 15     private OnItemClickListener onItemClickListener;
 16 
 17     
 18     /**
 19      * 通过 Java代码  实例化
 20      * @param context
 21      */
 22     public LinearLayoutForListView(Context context)
 23     {
 24         super(context);
 25         //设置LinearLayoutForListView为垂直布局,否者默认为水平布局,容易疏忽导致子项显示不全
 26         LinearLayoutForListView.this.setOrientation(LinearLayout.VERTICAL);
 27     }
 28 
 29     
 30     /**
 31      * 此构造函数可以允许我们通过 XML的方式注册 控件
 32      * @param context
 33      * @param attrs
 34      */
 35     public LinearLayoutForListView(Context context, AttributeSet attrs)
 36     {
 37         super(context, attrs);
 38         LinearLayoutForListView.this.setOrientation(LinearLayout.VERTICAL);
 39     }
 40     
 41     
 42 
 43     /**
 44      * 设置适配器
 45      * 
 46      * @param adpater
 47      */
 48     public void setAdapter(BaseAdapter adpater)
 49     {
 50         this.adapter = adpater;
 51         bindLinearLayout();
 52     }
 53 
 54     /**
 55      * 获取适配器Adapter
 56      * 
 57      * @return adapter
 58      */
 59     public BaseAdapter getAdpater()
 60     {
 61         return adapter;
 62     }
 63 
 64     
 65     
 66     /**
 67      * 绑定布局:将每个子项的视图view添加进此线性布局LinearLayout中
 68      */
 69     public void bindLinearLayout()
 70     {
 71         int count = adapter.getCount();
 72         for (int i = 0; i < count; i++)
 73         {
 74             View v = adapter.getView(i, null, null);
 75 
 76             if (i != count - 1)
 77             {    //添加每项item之间的分割线
 78                  v = addLine(v);
 79             }
 80             addView(v, i);
 81         }
 82         setItemClickListener();
 83         Log.v("countTAG", "" + count);
 84     }
 85 
 86     /**
 87      * 添加每项item之间的分割线
 88      * 
 89      * @param view
 90      * @return
 91      */
 92     public View addLine(View view)
 93     {
 94         //分割线view
 95         View lineView = new View(view.getContext());
 96 
 97         // 将数据从dip(即dp)转换到px,第一参数为数据原单位(此为DIP),第二参数为要转换的数据值
 98         float fPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
 99                 (float) 0.5, view.getResources().getDisplayMetrics());
100         int iPx = Math.round(fPx);
101 
102         LayoutParams layoutParams = new LayoutParams(
103                 LinearLayout.LayoutParams.MATCH_PARENT, iPx);
104         lineView.setLayoutParams(layoutParams);
105         lineView.setBackgroundColor(view.getSolidColor());
106 
107         LinearLayout ly = new LinearLayout(view.getContext());
108         ly.setOrientation(LinearLayout.VERTICAL);
109 
110         ly.addView(view);
111         ly.addView(lineView);
112 
113         return ly;
114     }
115 
116     
117     /**
118      * 设置点击子项事件监听对象
119      * @param onItemClickListener
120      */
121     public void setOnItemClickListener(OnItemClickListener onItemClickListener)
122     {
123         this.onItemClickListener = onItemClickListener;
124         setItemClickListener();
125     }
126     
127     /**
128      * 获取点击子项事件监听对象
129      * @return
130      */
131     public OnItemClickListener getOnItemClickListener()
132     {
133         return onItemClickListener;
134     }
135     
136     
137     /**
138      * 设置子项点击事件
139      */
140     private void setItemClickListener()
141     {
142         if (adapter != null)
143         {
144             for (int i = 0; i < LinearLayoutForListView.this.getChildCount(); i++)
145             {
146                 View view = LinearLayoutForListView.this.getChildAt(i);
147                 if (onItemClickListener != null)
148                 {
149                     //设置子项点击事件
150                     view.setOnClickListener(new ItemClickListener(view, i, adapter.getItemId(i)));
151                 }
152             }
153         }
154     }
155     
156     class ItemClickListener implements OnClickListener
157     {
158         View view;
159         int position;
160         long id;
161         
162         public ItemClickListener(View view, int position, long id)
163         {
164             this.view = view;
165             this.position = position;
166             this.id = id;
167         }
168 
169         @Override
170         public void onClick(View v)
171         {
172             //将子项视图的点击事件转发到整个listview的OnItemClick事件中
173             //此方法有局限性,第一个参数 AdapterView<?> parent(即当前listView的视图)没传入onItemClick()中
174             onItemClickListener.onItemClick(null, view, position, id);
175         }
176     }
177 }

 

XML中使用自定义控件来调用LinearLayoutForListView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <com.and.mine.LinearLayoutForListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </com.and.mine.LinearLayoutForListView>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="使用方法" />

</LinearLayout>


 

当然这种这种方法也是存在不足之处的,欢迎各位指正

 

THE END


 

发表评论
用户名: 匿名