ScrollView,ListView等带滚动条控件嵌套解决方案汇总
2016-05-23 12:40
417 查看
开发中可能遇到各种需求 ViewPager+ListView(首页顶部轮播图+产品/新闻列表)是特别常见的一种需求,这里就需要用到外部的ScrollView 嵌套一个内部的ListView 进行一个显示,直接写的话 ScrollView 的滚动条会覆盖掉ListView的滚动条 使它无法滚动,下面是网上收集的一些解决方案,还有一些开发中遇到的一点小技巧,让这种需求更简单的搞定。
1、手动设置ListView高度
经过测试发现,在xml中直接指定ListView的高度,是可以解决这个问题的,但是ListView中的数据是可变的,实际高度还需要实际测量。于是手动代码设置ListView高度的 方法就诞生了。
上面这个方法就是设定ListView的高度了,在为ListView设置了Adapter之后使用,就可以解决问题了。
但是这个方法有个两个细节需要注意:
一是Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用 listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的,没理由…。我最初使用的就是这个方法,但是因为子控件的顶层布局是RelativeLayout,所以一直报错,不得不放弃这个方法。
二是需要手动把ScrollView滚动至最顶端,因为使用这个方法的话,默认在ScrollView顶端的项是ListView,猜测应该是ListView调用方法的时候重新设置宽高导致的一些焦点抢夺问题,对于这个问题有小技巧 下面会讲到。
2、使用单个ListView取代ScrollView中所有内容
在我的文章android
ListView显示多个类型item 和 item中控件抢夺焦点解决办法中有说到,不知道的盆友可以去看看。
3、使用LinearLayout取代ListView
既然ListView不能适应ScrollView,那就换一个可以适应ScrollView的控件,干嘛非要吊死在ListView这一棵树上呢?而LinearLayout是最好的选择。通过addView(View
v)方法 可以依次添加item 只是这种方式的适配性很差 如果item少且固定可以考虑使用。
4、自定义可适应ScrollView的ListView
自定义一个类继承自ListView,通过重写其onMeasure方法,达到对ScrollView适配的效果。
下面是继承了ListView的自定义类:
这个方法和方法1有一个同样的毛病,就是默认显示的首项是ListView,需要手动把ScrollView滚动至最顶端。
sv = (ScrollView) findViewById(R.id.act_solution_4_sv);
sv.smoothScrollTo(0, 0);
接下来讲小技巧,方法4和方法1 应该是使用得最多的吧,其实可以不用手动滚动回去的,只需要设置ListView上方控件或者父控件的一个属性
下面给出方法4的相关代码,可直接拷贝使用
自定义的NoScrollListView
item_lv.xml
Activity
scroll_activity.xml
大家可以去掉属性测试 再添加属性进行测试,本人一直在用,是完全没问题的。
本文参考链接:http://www.devstore.cn/essay/essayInfo/945.html
1、手动设置ListView高度
经过测试发现,在xml中直接指定ListView的高度,是可以解决这个问题的,但是ListView中的数据是可变的,实际高度还需要实际测量。于是手动代码设置ListView高度的 方法就诞生了。
// 动态设置ListView的高度 // 此方法在对应的Adapter中定义,这里是ListAdapter。 // 设置适配器后调用此方法传入对应的ListView就可以了 public void setListViewHeightBasedOnChildren(ListView listView) { if(listView == null) return; ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { // pre-condition return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); }
上面这个方法就是设定ListView的高度了,在为ListView设置了Adapter之后使用,就可以解决问题了。
但是这个方法有个两个细节需要注意:
一是Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用 listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的,没理由…。我最初使用的就是这个方法,但是因为子控件的顶层布局是RelativeLayout,所以一直报错,不得不放弃这个方法。
二是需要手动把ScrollView滚动至最顶端,因为使用这个方法的话,默认在ScrollView顶端的项是ListView,猜测应该是ListView调用方法的时候重新设置宽高导致的一些焦点抢夺问题,对于这个问题有小技巧 下面会讲到。
2、使用单个ListView取代ScrollView中所有内容
在我的文章android
ListView显示多个类型item 和 item中控件抢夺焦点解决办法中有说到,不知道的盆友可以去看看。
3、使用LinearLayout取代ListView
既然ListView不能适应ScrollView,那就换一个可以适应ScrollView的控件,干嘛非要吊死在ListView这一棵树上呢?而LinearLayout是最好的选择。通过addView(View
v)方法 可以依次添加item 只是这种方式的适配性很差 如果item少且固定可以考虑使用。
4、自定义可适应ScrollView的ListView
自定义一个类继承自ListView,通过重写其onMeasure方法,达到对ScrollView适配的效果。
下面是继承了ListView的自定义类:
public class ListViewForScrollView extends ListView { public ListViewForScrollView(Context context) { super(context); } public ListViewForScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public ListViewForScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override /** * 重写该方法,达到使ListView适应ScrollView的效果 */ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }MeasureSpec属性不了解的可以参考http://blog.csdn.net/kaixinbingju/article/details/8649218
这个方法和方法1有一个同样的毛病,就是默认显示的首项是ListView,需要手动把ScrollView滚动至最顶端。
sv = (ScrollView) findViewById(R.id.act_solution_4_sv);
sv.smoothScrollTo(0, 0);
接下来讲小技巧,方法4和方法1 应该是使用得最多的吧,其实可以不用手动滚动回去的,只需要设置ListView上方控件或者父控件的一个属性
android:focusableInTouchMode="true" //需要注意的是 有时候设置父控件属性时会不起作用,具体情况不知。
下面给出方法4的相关代码,可直接拷贝使用
自定义的NoScrollListView
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 defStyleAttr) { super(context, attrs, defStyleAttr); } //MeasureSpec.EXACTLY:当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip", // 或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。 //MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化, // 此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。 //MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
item_lv.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="10dp"> <ImageView android:id="@+id/iv" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center_horizontal" android:background="#ff0000"/> <TextView android:id="@+id/item" android:layout_width="100dp" android:layout_height="100dp" android:gravity="fill_vertical" android:text="TextTextTestScrollView and ListView" android:textColor="#ff0000" android:textSize="30sp" /> <!--android:textColor="#1fa67a"--> </LinearLayout>
Activity
public class ScrollActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scroll_activity); ListView listView = (ListView) findViewById(R.id.lv); listView.setAdapter(new MyAdapter()); } class MyAdapter extends BaseAdapter { @Override public int getCount() { return 20; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.item_lv, null); } return convertView; } } }
scroll_activity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 在LinearLayout 或者ImageView中设置android:focusableInTouchMode属性都可以达到效果 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:focusableInTouchMode="true" > <ImageView android:layout_width="match_parent" android:layout_height="200dp" android:src="@mipmap/ic_launcher" /> <cd.com.hslistview.NoScrollListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/lv" > </cd.com.hslistview.NoScrollListView> </LinearLayout> </ScrollView> </LinearLayout>
大家可以去掉属性测试 再添加属性进行测试,本人一直在用,是完全没问题的。
本文参考链接:http://www.devstore.cn/essay/essayInfo/945.html
相关文章推荐
- ListView嵌套ListView实现论坛评论效果
- listview嵌套listview ScrollView嵌套listview 的冲突问题
- 关于ListView嵌套ListView时,内层ListView动态改变的问题
- android开发游记:ScrollView嵌套ListView,ListView完全展开及makeMeasureSpec测量机制原理分析
- ListView嵌套GridView,具有listView控件点击事件
- 【解决】Listview中嵌套Listview或者ScrollView中嵌套Listview【显示不完整和滑动冲突】
- 【解决】Listview 嵌套ListView/ScrollView 导致item点击无效
- scrollview嵌套listview运行后最先显示出来的位置不在顶部而是下方问题
- android 购物车 listview嵌套问题
- 仿淘宝订单listview的嵌套使用
- 解决ListView嵌套ListView或者ScrollView嵌套ListView出现的问题
- Android Adapter嵌套Adapter(文档类app,说明书类app)
- ListView嵌套ScrollView,MeasureSpec相关
- Android开发ScrollView嵌套ListView的处理方法
- ScoreView嵌套listview或者Listview嵌套ListviewUI冲突
- 关于ListView嵌套的问题
- Android实战技巧:如何在ListView中嵌套ListView(转)
- Eclipse更换应用包名
- Activity的生命周期
- [POJ 2096] Collecting Bugs