我到处寻找这个问题的解决方案,我能找到的唯一答案似乎是“不要把一个ListView放入一个ScrollView”。不过,我还没有看到任何真正的解释。我能找到的唯一原因似乎是谷歌认为你不应该这么做。我知道,所以我做了。
问题是,如何将ListView放到ScrollView中而不缩到最小高度?
我到处寻找这个问题的解决方案,我能找到的唯一答案似乎是“不要把一个ListView放入一个ScrollView”。不过,我还没有看到任何真正的解释。我能找到的唯一原因似乎是谷歌认为你不应该这么做。我知道,所以我做了。
问题是,如何将ListView放到ScrollView中而不缩到最小高度?
当前回答
在很多情况下,在ScrollView中有ListView是很有意义的。
下面是基于DougW建议的代码…工作在一个片段,占用较少的内存。
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
int totalHeight = 0;
View view = null;
for (int i = 0; i < listAdapter.getCount(); i++) {
view = listAdapter.getView(i, view, listView);
if (i == 0) {
view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LayoutParams.WRAP_CONTENT));
}
view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += view.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
在每个嵌入的列表视图上调用setListViewHeightBasedOnChildren(listview)。
其他回答
下面是我的计算列表视图总高度的代码版本。这个对我很有用:
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null || listAdapter.getCount() < 2) {
// pre-condition
return;
}
int totalHeight = 0;
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(BCTDApp.getDisplaySize().width, View.MeasureSpec.AT_MOST);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) listItem.setLayoutParams(lp);
listItem.measure(widthMeasureSpec, heightMeasureSpec);
totalHeight += listItem.getMeasuredHeight();
}
totalHeight += listView.getPaddingTop() + listView.getPaddingBottom();
totalHeight += (listView.getDividerHeight() * (listAdapter.getCount() - 1));
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight;
listView.setLayoutParams(params);
listView.requestLayout();
}
如果LinearLayout有一个setAdapter方法,整个问题就会消失,因为当你告诉别人使用它时,替代方案将是微不足道的。
如果你想要一个滚动的ListView在另一个滚动视图中,这不会有帮助,但至少会给你一个想法。
您需要创建一个自定义适配器来组合要滚动的所有内容,并将ListView的适配器设置为该内容。
我手头没有样本代码,但如果你想要。
<ListView/>
(other content)
<ListView/>
然后需要创建一个表示所有这些内容的适配器。ListView/Adapters也足够智能,可以处理不同的类型,但是您需要自己编写适配器。
android的UI API并不像其他平台那么成熟,所以它不像其他平台那么精致。此外,当你在android上做一些事情时,你需要以android (unix)的心态来做任何事情,你可能不得不将更小的部分的功能组装起来,并编写一堆自己的代码来让它工作。
这些答案都是错的!! 如果你想把一个列表视图放在滚动视图中,你应该重新考虑你的设计。你试图把一个ScrollView放到一个ScrollView中。干扰列表将损害列表性能。Android就是这样设计的。
如果你真的想让列表和其他元素在同一个滚动中,你所要做的就是在适配器中使用一个简单的switch语句将其他项添加到列表的顶部:
class MyAdapter extends ArrayAdapter{
public MyAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewItem viewType = getItem(position);
switch(viewType.type){
case TEXTVIEW:
convertView = layouteInflater.inflate(R.layout.textView1, parent, false);
break;
case LISTITEM:
convertView = layouteInflater.inflate(R.layout.listItem, parent, false);
break; }
return convertView;
}
}
列表适配器可以处理所有内容,因为它只呈现可见的内容。
感谢Vinay的代码,这是我的代码,当你不能在滚动视图中有一个列表视图时,你需要这样的东西
LayoutInflater li = LayoutInflater.from(this);
RelativeLayout parent = (RelativeLayout) this.findViewById(R.id.relativeLayoutCliente);
int recent = 0;
for(Contatto contatto : contatti)
{
View inflated_layout = li.inflate(R.layout.header_listview_contatti, layout, false);
inflated_layout.setId(contatto.getId());
((TextView)inflated_layout.findViewById(R.id.textViewDescrizione)).setText(contatto.getDescrizione());
((TextView)inflated_layout.findViewById(R.id.textViewIndirizzo)).setText(contatto.getIndirizzo());
((TextView)inflated_layout.findViewById(R.id.textViewTelefono)).setText(contatto.getTelefono());
((TextView)inflated_layout.findViewById(R.id.textViewMobile)).setText(contatto.getMobile());
((TextView)inflated_layout.findViewById(R.id.textViewFax)).setText(contatto.getFax());
((TextView)inflated_layout.findViewById(R.id.textViewEmail)).setText(contatto.getEmail());
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
if (recent == 0)
{
relativeParams.addRule(RelativeLayout.BELOW, R.id.headerListViewContatti);
}
else
{
relativeParams.addRule(RelativeLayout.BELOW, recent);
}
recent = inflated_layout.getId();
inflated_layout.setLayoutParams(relativeParams);
//inflated_layout.setLayoutParams( new RelativeLayout.LayoutParams(source));
parent.addView(inflated_layout);
}
relativeLayout保持在ScrollView中,所以它都是可滚动的:)
嘿,我也有类似的问题。我想显示一个列表视图,不滚动,我发现操纵参数工作,但效率低,会在不同的设备上表现不同。因此,这是我的一段调度代码,它实际上非常有效地完成了这个任务。
db = new dbhelper(this);
cursor = db.dbCursor();
int count = cursor.getCount();
if (count > 0)
{
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layoutId);
startManagingCursor(YOUR_CURSOR);
YOUR_ADAPTER(**or SimpleCursorAdapter **) adapter = new YOUR_ADAPTER(this,
R.layout.itemLayout, cursor, arrayOrWhatever, R.id.textViewId,
this.getApplication());
int i;
for (i = 0; i < count; i++){
View listItem = adapter.getView(i,null,null);
linearLayout.addView(listItem);
}
}
注意:如果你使用这个,notifyDataSetChanged();将不会像预期的那样工作,因为视图将不会被重绘。 如果你需要变通,就这么做
adapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
removeAndRedrawViews();
}
});