ScrollView与ListView冲突解决
正 常来说,在ScrollView添加一个ListView后在真机上只会显示ListView的一行多一点,我也不理解为什么会这样,后来我把 ListView的layout_height改成400dip,而不是用match_parent和wrap_content,我发现这样的话 ListView就显示的多了很多。所以就产生了把ListView所有的item的高度算出来给ListView设置的想法。下面是代码:
源码:http://www.jinhusns.com/Products/Download/?type=xcj
Java代码
public void setListViewHeightBasedOnChildren(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);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
params.height += 5;//if without this statement,the listview will be a little short
listView.setLayoutParams(params);
}
在代码的倒数第二行二我又给加了5个像素,这是因为我在listview的属性里面添加了padding=5dip。
然后每次ListView的数据一有变化就用这个函数设置一下就好了,不过这样总感觉效率很低,希望有达人给指点一下。
简单来说就是把layout_height写死,这种办法也很适用于GridView(如果能估计得出GridView的高度的话)。
listview与ScrollView老问题的另类解法
http://www.eoeandroid.com/thread-42893-1-1.html
这
几天一直被listview怎么合理的放进scorllview中的问题困扰,尝试过把listview放入scorllview中的朋友都知
道,被放入的listview显示是有问题的,无论怎么设置layout都只显示大概2行的高度,看起来很郁闷,更别说美观了,后来上网查询了一下,解决
方法有的是用linearlayout替换listview,还有修改onmeasure的,我比较懒个人感觉很麻烦不喜欢,终于想出了一个还算和谐的解
决方法:xml中的textlist设置如下:
Java代码
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#44444444">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:orientation="vertical"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="30dp"
android:paddingBottom="30dp"
android:background="#ff888888">
<TextView
android:text="あ"
android:textColor="#ffeeeeee"
android:textSize="18sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></TextView>
<ListView
android:scrollbars="none"
android:stackFromBottom="true"
android:id="@+id/lv0"
android:layout_width="fill_parent"
android:layout_height="20dp"></ListView>
</LinearLayout>
</ScrollView>
</LinearLayout>
其中的textview是我做的东西要用到的,和方法无关可以不看,然后就是在java中重新设置listview的高度了,目的是把listview“撑”开:
LinearLayout.LayoutParams lp5 =new LinearLayout.LayoutParam(LayoutParams.FILL_PARENT, listItem.size()*51-1);
其
中第一个属性不必说了,第二个是为了计算listview要设置的总高度用的,51是我事先设置好的一行的高度(50)+每行之间的间隔(1)
而得来的,listItem.size()是我要显示的行数,用.setLayoutParams(lp5);来重新设置高度,其他别的设置跟以前一样,
想要源码我整理完之后贴出来
如果不想写死 ,Android 解决ListView 和 ScrollView 共存冲突的问题
http://labs.chinamobile.com/mblog/532767_72693?wralxianxrnx
http://blog.liaoxiaoqi.com/?p=503
下面是我的一个实现 步骤:
1、继承LinearLayout,既然会冲突那就不用ListView 改成线性布局做动态布局效果
2、继承BaseAdapter ,可以参照一下Android app源码中 Widget 目录下的SimpleAdapter 为前面扩展的LinearLayout做数据。
3、模拟数据填充扩展后的BaseAdapter 为扩展后的LinearLayout 加载数据
第一步:新建LinearLayoutForListView 类使其扩展LinearLayout重写以下两个方法:
Java代码
public LinearLayoutForListView(Context context) {
super(context);
}
public LinearLayoutForListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
这两个方法可选,不过建议都写上,第一个方法可以让我们通过 编程的方式 实例化出来,第二个方法可以允许我们通过 XML的方式注册 控件,可以在第二个方法里面为扩展的复合组件加属性。为其添加get / set 方法
Java代码
/**
* 获取Adapter
*
* @return adapter
*/
public AdapterForLinearLayout getAdpater() {
return adapter;
}
/**
* 设置数据
*
* @param adpater
*/
public void setAdapter(AdapterForLinearLayout adpater) {
this.adapter = adpater;
bindLinearLayout();
}
/**
* 获取点击事件
*
* @return
*/
public OnClickListener getOnclickListner() {
return onClickListener;
}
/**
* 设置点击事件
*
* @param onClickListener
*/
public void setOnclickLinstener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
sp;
第二步:新建AdapterForLinearLayout 类继承自BaseAdapter,并为其添加构造函数
Java代码
private LayoutInflater mInflater;
private int resource;
private List<? extends Map<String, ?>> data;
private String[] from;
private int[] to;
public AdapterForLinearLayout(Context context,
List<? extends Map<String, ?>> data, int resouce, String[] from,
int[] to) {
this.data = data;
this.resource = resouce;
this.data = data;
this.from = from;
this.to = to;
this.mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
此
构造函数模仿 simpleAdapter 通过传进来的resouce 为布局设置数据。通过继承BaseAdapter
重要的实现方法在下面getView ,此方法判断通过传进来的 String[] from 与 int[] to 为分别查找出View
并为View 设置相应的Text,代码如下:
Java代码
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
convertView = mInflater.inflate(resource, null);
Map<String, ?> item = data.get(position);
int count = to.length;
for (int i = 0; i < count; i++) {
View v = convertView.findViewById(to[i]);
bindView(v, item, from[i]);
}
convertView.setTag(position);
return convertView;
}
/**
* 绑定视图
* @param view
* @param item
* @param from
*/
private void bindView(View view, Map<String, ?> item, String from) {
Object data = item.get(from);
if (view instanceof TextView) {
((TextView) view).setText(data == null ? "" : data.toString());
}
}
Tip:
BindView 方法是一个自定义方法,在方法体内可以为通过判断使本类更具灵活性,如上,你不仅可以判断是TextView 并且可以传入任何你想要的View 只要在方法体内加入相应判断即可,数据可以通过data 做相应处理,具体如何操作读者可另行测试。
convertView.setTag(position); 此句代码为View 设置tag 在以后我们可以通过 getTag 找出下标,后文有介绍如何通过下标操作数据。
下面是两个类的全部代码,读者可以无须更改直接使用:
Java代码
LinearLayoutForListView
package com.terry.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
public class LinearLayoutForListView extends LinearLayout {
private AdapterForLinearLayout adapter;
private OnClickListener onClickListener = null ;
/**
* 绑定布局
*/
public void bindLinearLayout() {
int count = adapter.getCount();
for ( int i = 0 ; i < count; i ++ ) {
View v = adapter.getView(i, null , null );
v.setOnClickListener( this .onClickListener);
if (i == count - 1 ) {
LinearLayout ly = (LinearLayout) v;
ly.removeViewAt( 2 );
}
addView(v, i);
}
Log.v( " countTAG " , "" + count);
}
public LinearLayoutForListView(Context context) {
super (context);
}
public LinearLayoutForListView(Context context, AttributeSet attrs) {
super (context, attrs);
}
/**
* 获取Adapter
*
* @ return adapter
*/
public AdapterForLinearLayout getAdpater() {
return adapter;
}
/**
* 设置数据
*
* @ param adpater
*/
public void setAdapter(AdapterForLinearLayout adpater) {
this .adapter = adpater;
bindLinearLayout();
}
/**
* 获取点击事件
*
* @ return
*/
public OnClickListener getOnclickListner() {
return onClickListener;
}
/**
* 设置点击事件
*
* @ param onClickListener
*/
public void setOnclickLinstener(OnClickListener onClickListener) {
this .onClickListener = onClickListener;
}
}
Java代码
AdapterForLinearLayout
package com.terry.widget;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class AdapterForLinearLayout extends BaseAdapter {
private LayoutInflater mInflater;
private int resource;
private List <? extends Map < String, ?>> data;
private String[] from;
private int [] to;
public AdapterForLinearLayout(Context context,
List <? extends Map < String, ?>> data, int resouce, String[] from,
int [] to) {
this .data = data;
this .resource = resouce;
this .data = data;
this .from = from;
this .to = to;
this .mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@ Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
@ Override
public Object getItem( int position) {
// TODO Auto-generated method stub
return data.get(position);
}
@ SuppressWarnings( " unchecked " )
public String get( int position, Object key) {
Map < String, ?> map = (Map < String, ?> ) getItem(position);
return map.get(key).toString();
}
@ Override
public long getItemId( int position) {
// TODO Auto-generated method stub
return position;
}
@ Override
public View getView( int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
convertView = mInflater.inflate(resource, null );
Map < String, ?> item = data.get(position);
int count = to.length;
for ( int i = 0 ; i < count; i ++ ) {
View v = convertView.findViewById(to[i]);
bindView(v, item, from[i]);
}
convertView.setTag(position);
return convertView;
}
/**
* 绑定视图
* @ param view
* @ param item
* @ param from
*/
private void bindView(View view, Map < String, ?> item, String from) {
Object data = item.get(from);
if (view instanceof TextView) {
((TextView) view).setText(data == null ? "" : data.toString());
}
}
}
对应的XML 如下:
Java代码
<? xml version="1.0" encoding="UTF-8" ?>
< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
android:orientation ="vertical" android:layout_width ="fill_parent"
android:layout_height ="fill_parent" >
< TextView android:id ="@ +id/TextView01"
android:layout_marginLeft ="10px" android:textAppearance ="?android:attr/textAppearanceLarge"
android:layout_width ="wrap_content" android:layout_height ="wrap_content" >
</ TextView >
< TextView android:id ="@ +id/TextView02" android:layout_width ="wrap_content"
android:textAppearance ="?android:attr/textAppearanceSmall"
android:layout_marginLeft ="10px" android:layout_height ="wrap_content" >
</ TextView >
< View android:layout_height ="1px" android:background ="#FFFFFF"
android:layout_width ="fill_parent" ></ View >
</ LinearLayout >
第三步:主页面使用控件并为其设置数据
XML如下:
Java代码
< com.terry.widget.LinearLayoutForListView
android:orientation ="vertical" android:layout_width ="450px"
android:layout_height ="fill_parent" android:id ="@ +id/ListView01" >
</ com.terry.widget.LinearLayoutForListView >
加载数据如下:
Java代码
lv = (LinearLayoutForListView) findViewById(R.id.ListView01);
for ( int i = 0 ; i < 10 ; i ++ ) {
HashMap < String, Object > map = new HashMap < String, Object > ();
map.put( " key_name " , " name " + i);
map.put( " value_name " , " value " + i);
list.add(map);
}
final AdapterForLinearLayout Layoutadpater = new AdapterForLinearLayout(
this , list, R.layout.test, new String[] { " key_name " ,
" value_name " }, new int [] { R.id.TextView01,
R.id.TextView02 });
事件操作,并通过下标得到数据源:
Java代码
Tip:get方法是在Layoutadpater 封装的一个通过下标获取相应数据的方法请参考上文。
lv.setOnclickLinstener( new OnClickListener() {
@ Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(
BlueToothActivity. this ,
Layoutadpater.get(Integer.parseInt(v.getTag()
.toString()), " key_name " ), 1000 ).show();
}
});
lv.setAdapter(Layoutadpater);
至此完成。有碰到这个问题的朋友可以试试。
有人的总结如下:
只要在设置ListView的Adapter后调用此静态方法即可让ListView正确的显示在其父ListView的ListItem中。但是要注意
的是,子ListView的每个Item必须是LinearLayout,不能是其他的,因为其他的Layout(如RelativeLayout)没有
重写onMeasure(),所以会在onMeasure()时抛出异常。
在ScrollView中嵌套ListView(或者
ScrollView)的另外一个问题就是,子ScrollView中无法滑动的(如果它没有显
示完全的话),因为滑动事件会被父ScrollView吃掉,如果想要让子ScrollView也可以滑动,只能强行截取滑动事件,有牛人在论坛 中发过代码说可以。虽然我没有亲自试过,但估计是可行的。
虽然在ScrollView中显示ScrollView在技术上的难题可以攻破,但是这样的设计却是非常差的用户体验因为用户会不容易看到和操作子
ScrollView中的内容。比如好的设计是,父ListView的每个Item只显示概括性的描述,然后点击其Item会进入另外一个页面来详细描述
和展示以及对这个Item的操作。
源码:http://www.jinhusns.com/Products/Download/?type=xcj
于是找到另外两种比较简单的方法,而且又没有影响的:
1.在ScrollView中添加一属性 android:fillViewport="true" ,这样就可以让ListView全屏显示了
2.指定ListView的高度 android:layout_height="420dp" ;
ScrollView与ListView冲突解决的更多相关文章
- ScrollView 和 ListView 冲突解决方案
网上说了很多阿,什么linearLayout 实现listView 什么的.还设置高什么的. 其实,你们可能忘记了,如果出现 ScrollView 和 ListView 同时出现,那就是设计错误了. ...
- Android ScrollView 嵌套 ListView、 ListView 嵌套ScrollView Scroll事件冲突解决办法
本人菜鸟一名,最近工作了,开始学习Android. 最近在做项目的时候,UX给了个design,大概就是下拉刷新的ListView中嵌套了ScrollView,而且还要在ScrollView中添加动画 ...
- Android之ScrollView嵌套ListView冲突
在ScrollView中嵌套使用ListView,ListView只会显示一行多一点.两者进行嵌套,即会发生冲突.由于ListView本身都继承于ScrollView,一旦在ScrollView中嵌套 ...
- 冲突--ScrollView嵌套ListView冲突问题的最优解决方案
项目做多了之后,会发现其实 ScrollView嵌套ListVew或者GridView等很常用,但是你也会发现各种奇怪问题产生.根据个人经验现在列出常见问题以及代码最少最简单的解决方法. 问题一 : ...
- ScrollView嵌套ListView冲突问题的最优解决方式
项目做多了之后.会发现事实上ScrollView嵌套ListVew或者GridView等非经常常使用,可是你也会发现各种奇怪问题产生.依据个人经验如今列出常见问题以及代码最少最简单的解决方法. 问题一 ...
- Android之ScrollView嵌套ListView冲突 (listView只显示一行)
在ScrollView中嵌套使用ListView,ListView只会显示一行多一点.两者进行嵌套,即会发生冲突.由于ListView本身都继承于ScrollView,一旦在ScrollView中嵌套 ...
- 解决ScrollView嵌到listView冲突问题
方法一: 把下面的方法放在绑定适配器操作的下面就行. /** * 重新计算ListView的高度,解决ScrollView和ListView两个View都有滚动的效果,在嵌套使用时起冲突的问题 * @ ...
- Android——MeasureSpec学习 - 解决ScrollView嵌套ListView和GridView冲突的方法
原文地址:http://blog.csdn.net/yuhailong626/article/details/20639217 在自定义View和ViewGroup的时候,我们经常会遇到int ...
- ScrollView嵌套使用ListView冲突的解决与分析
因为ScrollView与ListView都是具有滚动条的控件,所以嵌套在一起使用的时候可能会出现事件的冲突,比如我就遇见了ListView中只显示一条数据的问题.解决的办法,就是自定义了一个List ...
随机推荐
- Unity3d使用经验总结 数据驱动篇
我这里说的数据驱动,不是指某种框架,某种结构,或者某种编码方式. 我要说的,是一种开发方式. 大家都知道,U3D中,我们可以为某个对象编写一个脚本,然后将这个脚本挂在对象上,那这个对象就拥有了相应的能 ...
- linux下目录操作
1. 常用函数 #include <dirent.h> //open a directory //failed-NULL, other-return a DIR stream DIR *o ...
- 趣味C程序-HelloWord
说明:刚才写了一个基础的helloWord程序(很早以前从其他地方收集的.),本以为群里面的人是可以答对了,但是我错了,没有人.他们的错误往往被程序的外表给蒙蔽了. 很多人的回答是0.如果你仔细看的话 ...
- xamarin误删vEthernet(internal Ethernet Port Windows Phone Emulator) 网络设备的处理。
昨天一不小心误删了xamarin 开发环境下的虚拟设备网络设备.名称为:vEthernet(internal Ethernet Port Windows Phone Emulator).导致原来能正确 ...
- js笔记——call,apply,bind使用笔记
call和apply obj.call(thisObj, arg1, arg2, ...); obj.apply(thisObj, [arg1, arg2, ...]); 两者作用一致,都是把obj( ...
- Java程序员的日常 —— 多进程开发
最近再弄进程管理相关的工作,因此必要的就涉及到各种系统下关于进程的管理. 这里简单的介绍下: 如何在Java中执行命令 在windows下肯定是dos命令了,而在linux则为shell命令.执行的方 ...
- 数据库MySQL开篇
作为一名前端,后天方面的知识虽说不一定要精通后台但是对后台方面的知识有一定了解是非常必要的. 今天先说一些概念方面的,因本人才疏学浅,对于数据库这方面的自学相当于摸着石头过河,有什么写的不对的地方,希 ...
- try-catch和throw,throws的区别
java里的异常多种多样,这是一种非常有用的机制,它能帮助我们处理那些我们未知的错误,在java里,关于异常的有throw throws,还有一个try catch 程序块.接下来我们挨个看看这几个的 ...
- Mybatis 缓存
1. 一级缓存:其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空. 2. 二级缓存与一级缓存其机制相同,不同在于其存 ...
- ng-表单验证
表单验证<AngularJs> 常用的表单验证指令 1. 必填项验证 某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: <input type ...