我到处寻找这个问题的解决方案,我能找到的唯一答案似乎是“不要把一个ListView放入一个ScrollView”。不过,我还没有看到任何真正的解释。我能找到的唯一原因似乎是谷歌认为你不应该这么做。我知道,所以我做了。
问题是,如何将ListView放到ScrollView中而不缩到最小高度?
我到处寻找这个问题的解决方案,我能找到的唯一答案似乎是“不要把一个ListView放入一个ScrollView”。不过,我还没有看到任何真正的解释。我能找到的唯一原因似乎是谷歌认为你不应该这么做。我知道,所以我做了。
问题是,如何将ListView放到ScrollView中而不缩到最小高度?
当前回答
我们不能同时使用两个滚动。我们将获得ListView的总长度,并用总高度展开ListView。然后我们可以直接或使用线性布局在ScrollView中添加ListView,因为ScrollView直接有一个子。 在你的代码中复制setListViewHeightBasedOnChildren(lv)方法并展开listview,然后你可以在scrollview中使用listview。 \layout XML文件
<?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="match_parent"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#1D1D1D"
android:orientation="vertical"
android:scrollbars="none" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#1D1D1D"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="40dip"
android:background="#333"
android:gravity="center_vertical"
android:paddingLeft="8dip"
android:text="First ListView"
android:textColor="#C7C7C7"
android:textSize="20sp" />
<ListView
android:id="@+id/first_listview"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:divider="#00000000"
android:listSelector="#ff0000"
android:scrollbars="none" />
<TextView
android:layout_width="fill_parent"
android:layout_height="40dip"
android:background="#333"
android:gravity="center_vertical"
android:paddingLeft="8dip"
android:text="Second ListView"
android:textColor="#C7C7C7"
android:textSize="20sp" />
<ListView
android:id="@+id/secondList"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:divider="#00000000"
android:listSelector="#ffcc00"
android:scrollbars="none" />
</LinearLayout>
</ScrollView>
</LinearLayout>
Activity类中的onCreate方法:
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_inside_scrollview);
ListView list_first=(ListView) findViewById(R.id.first_listview);
ListView list_second=(ListView) findViewById(R.id.secondList);
ArrayList<String> list=new ArrayList<String>();
for(int x=0;x<30;x++)
{
list.add("Item "+x);
}
ArrayAdapter<String> adapter=new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,list);
list_first.setAdapter(adapter);
setListViewHeightBasedOnChildren(list_first);
list_second.setAdapter(adapter);
setListViewHeightBasedOnChildren(list_second);
}
public static void setListViewHeightBasedOnChildren(ListView listView) {
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);
}
其他回答
我把@DougW的实用程序转换成c#(在Xamarin中使用)。下面的代码对于列表中固定高度的项目很有效,如果只有一些项目比标准项目稍大一点,那么大多数项目都将很好,或者至少是一个良好的开端。
// You will need to put this Utility class into a code file including various
// libraries, I found that I needed at least System, Linq, Android.Views and
// Android.Widget.
using System;
using System.Linq;
using Android.Views;
using Android.Widget;
namespace UtilityNamespace // whatever you like, obviously!
{
public class Utility
{
public static void setListViewHeightBasedOnChildren (ListView listView)
{
if (listView.Adapter == null) {
// pre-condition
return;
}
int totalHeight = listView.PaddingTop + listView.PaddingBottom;
for (int i = 0; i < listView.Count; i++) {
View listItem = listView.Adapter.GetView (i, null, listView);
if (listItem.GetType () == typeof(ViewGroup)) {
listItem.LayoutParameters = new LinearLayout.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
}
listItem.Measure (0, 0);
totalHeight += listItem.MeasuredHeight;
}
listView.LayoutParameters.Height = totalHeight + (listView.DividerHeight * (listView.Count - 1));
}
}
}
谢谢@DougW,当我不得不使用其他人的代码时,这让我摆脱了困境。: -)
我们不能同时使用两个滚动。我们将获得ListView的总长度,并用总高度展开ListView。然后我们可以直接或使用线性布局在ScrollView中添加ListView,因为ScrollView直接有一个子。 在你的代码中复制setListViewHeightBasedOnChildren(lv)方法并展开listview,然后你可以在scrollview中使用listview。 \layout XML文件
<?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="match_parent"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#1D1D1D"
android:orientation="vertical"
android:scrollbars="none" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#1D1D1D"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="40dip"
android:background="#333"
android:gravity="center_vertical"
android:paddingLeft="8dip"
android:text="First ListView"
android:textColor="#C7C7C7"
android:textSize="20sp" />
<ListView
android:id="@+id/first_listview"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:divider="#00000000"
android:listSelector="#ff0000"
android:scrollbars="none" />
<TextView
android:layout_width="fill_parent"
android:layout_height="40dip"
android:background="#333"
android:gravity="center_vertical"
android:paddingLeft="8dip"
android:text="Second ListView"
android:textColor="#C7C7C7"
android:textSize="20sp" />
<ListView
android:id="@+id/secondList"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:divider="#00000000"
android:listSelector="#ffcc00"
android:scrollbars="none" />
</LinearLayout>
</ScrollView>
</LinearLayout>
Activity类中的onCreate方法:
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_inside_scrollview);
ListView list_first=(ListView) findViewById(R.id.first_listview);
ListView list_second=(ListView) findViewById(R.id.secondList);
ArrayList<String> list=new ArrayList<String>();
for(int x=0;x<30;x++)
{
list.add("Item "+x);
}
ArrayAdapter<String> adapter=new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,list);
list_first.setAdapter(adapter);
setListViewHeightBasedOnChildren(list_first);
list_second.setAdapter(adapter);
setListViewHeightBasedOnChildren(list_second);
}
public static void setListViewHeightBasedOnChildren(ListView listView) {
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);
}
虽然建议的setListViewHeightBasedOnChildren()方法在大多数情况下都可以工作,但在某些情况下,特别是对于许多项,我注意到最后一个元素不显示。所以我决定模仿一个简单版本的ListView行为,以便重用任何适配器代码,这里是ListView的替代方案:
import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
public class StretchedListView extends LinearLayout {
private final DataSetObserver dataSetObserver;
private ListAdapter adapter;
private OnItemClickListener onItemClickListener;
public StretchedListView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);
this.dataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
syncDataFromAdapter();
super.onChanged();
}
@Override
public void onInvalidated() {
syncDataFromAdapter();
super.onInvalidated();
}
};
}
public void setAdapter(ListAdapter adapter) {
ensureDataSetObserverIsUnregistered();
this.adapter = adapter;
if (this.adapter != null) {
this.adapter.registerDataSetObserver(dataSetObserver);
}
syncDataFromAdapter();
}
protected void ensureDataSetObserverIsUnregistered() {
if (this.adapter != null) {
this.adapter.unregisterDataSetObserver(dataSetObserver);
}
}
public Object getItemAtPosition(int position) {
return adapter != null ? adapter.getItem(position) : null;
}
public void setSelection(int i) {
getChildAt(i).setSelected(true);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public ListAdapter getAdapter() {
return adapter;
}
public int getCount() {
return adapter != null ? adapter.getCount() : 0;
}
private void syncDataFromAdapter() {
removeAllViews();
if (adapter != null) {
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
View view = adapter.getView(i, null, this);
boolean enabled = adapter.isEnabled(i);
if (enabled) {
final int position = i;
final long id = adapter.getItemId(position);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(null, v, position, id);
}
}
});
}
addView(view);
}
}
}
}
嘿,我也有类似的问题。我想显示一个列表视图,不滚动,我发现操纵参数工作,但效率低,会在不同的设备上表现不同。因此,这是我的一段调度代码,它实际上非常有效地完成了这个任务。
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();
}
});
这是我的解决方案。我对Android平台相当陌生,我确信这有点笨拙,特别是在直接调用.measure和设置LayoutParams的部分。直接使用Height属性,但它是有效的。
你所要做的就是调用Utility.setListViewHeightBasedOnChildren(yourListView),它将被调整大小,以完全适应其项目的高度。
public class Utility {
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
}