我一直在寻找解决此问题的方法,我唯一能找到的答案似乎是“ 不要将ListView放入ScrollView ”。我还没有看到为什么的任何真正的解释。我似乎能找到的唯一原因是Google认为您不应该这样做。好吧,我做到了。
所以问题是,如何将ListView放到ScrollView中而不塌缩到最小高度?
ListView
。ListView
可以具有多种行样式以及不可选择的行。
我一直在寻找解决此问题的方法,我唯一能找到的答案似乎是“ 不要将ListView放入ScrollView ”。我还没有看到为什么的任何真正的解释。我似乎能找到的唯一原因是Google认为您不应该这样做。好吧,我做到了。
所以问题是,如何将ListView放到ScrollView中而不塌缩到最小高度?
ListView
。ListView
可以具有多种行样式以及不可选择的行。
Answers:
使用a ListView
使其不滚动非常昂贵,并且违背了的全部目的ListView
。你应该不这样做。只需使用一个LinearLayout
代替。
How can I put a ListView into a ScrollView without it collapsing?
。您可以告诉您不应该这样做,但是也可以给出解决方法,这是一个很好的答案。您知道ListView除了滚动之外还具有其他一些很酷的功能,而LinearLayout没有这些功能。
这是我的解决方案。我对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);
}
}
LinearLayout
并没有a的所有固有优点之外,ListView
它没有分隔线,页眉/页脚视图,与手机的UI主题颜色匹配的列表选择器等。老实说,没有理由您不能滚动内部容器,直到到达终点为止,然后停止拦截触摸事件,以便外部容器滚动。使用滚轮时,每个桌面浏览器都会执行此操作。如果您通过轨迹球导航,Android本身可以处理嵌套滚动,那么为什么不通过触摸导航呢?
listItem.measure(0,0)
如果listItem是ViewGroup实例,将抛出NPE。我之前添加了以下内容listItem.measure
:if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
ListView
可以容纳高度可变的物品时,这种方法有点缺陷。调用getMeasuredHeight()
只会返回目标最小高度,而不是实际高度。我尝试getHeight()
改用,但返回0。有人对如何实现此方法有任何见解吗?
这绝对可以工作.............
您只需要像这样 替换您<ScrollView ></ScrollView>
的布局XML文件Custom ScrollView
<com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
package com.tmd.utils;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;
public class VerticalScrollview extends ScrollView{
public VerticalScrollview(Context context) {
super(context);
}
public VerticalScrollview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
Log.i("VerticalScrollview", "onInterceptTouchEvent: DOWN super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
Log.i("VerticalScrollview", "onInterceptTouchEvent: CANCEL super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
Log.i("VerticalScrollview", "onInterceptTouchEvent: UP super false" );
return false;
default: Log.i("VerticalScrollview", "onInterceptTouchEvent: " + action ); break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() );
return true;
}
}
如果要放入ListView
一个ScrollView
,我们可以ListView
用作一个ScrollView
。这必须是在物联网ListView
可以在里面放ListView
。ListView
通过在的页眉和页脚中添加布局,可以放置顶部和底部的其他布局ListView
。因此,整个过程ListView
将为您提供滚动体验。
在很多情况下,将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();
}
在每个嵌入式listview上调用setListViewHeightBasedOnChildren(listview)。
ListView实际上已经能够测量自身高度,以显示所有项目,但是当您仅指定wrap_content(MeasureSpec.UNSPECIFIED)时,它不会执行此操作。当使用MeasureSpec.AT_MOST给定高度时,它将执行此操作。有了这些知识,您可以创建一个非常简单的子类来解决此问题,该子类比上面发布的任何解决方案要好得多。您仍应将此子类与wrap_content一起使用。
public class ListViewForEmbeddingInScrollView extends ListView {
public ListViewForEmbeddingInScrollView(Context context) {
super(context);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
}
}
将heightMeasureSpec设置为具有非常大的尺寸(Integer.MAX_VALUE >> 4)的AT_MOST会导致ListView测量其所有子级,直到给定(非常大)的高度,并相应地设置其高度。
由于以下几个原因,它比其他解决方案更好:
不利的一面是,您可能会认为这样做是依赖于SDK中未记录的行为,该行为可能会发生变化。另一方面,您可能会争辩说这是wrap_content应该真正与ListView一起工作的方式,并且当前wrap_content行为刚刚被破坏。
如果您担心将来行为会发生变化,则只需将onMeasure函数和相关函数复制出ListView.java并复制到您自己的子类中,然后使onMeasure的AT_MOST路径也运行为未运行。
顺便说一句,我认为当您处理少量列表项时,这是一种非常有效的方法。与LinearLayout相比,它可能效率不高,但是当项目数较少时,使用LinearLayout就是不必要的优化,因此也就没有必要的复杂性。
有一个内置设置。在ScrollView上:
android:fillViewport="true"
在Java中,
mScrollView.setFillViewport(true);
罗曼·盖伊(Romain Guy)在这里进行了深入的解释:http : //www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
您创建不滚动的自定义ListView
public class NonScrollListView extends ListView {
public NonScrollListView(Context context) {
super(context);
}
public NonScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
在布局资源文件中
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- com.Example Changed with your Package name -->
<com.Example.NonScrollListView
android:id="@+id/lv_nonscroll_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.Example.NonScrollListView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/lv_nonscroll_list" >
<!-- Your another layout in scroll view -->
</RelativeLayout>
</RelativeLayout>
在Java文件中
创建您的customListview而不是ListView的对象,例如:NonScrollListView non_scroll_list =(NonScrollListView)findViewById(R.id.lv_nonscroll_list);
我们不能同时使用两次滚动。我们将获得ListView的总长度并以总高度展开listview。然后我们可以直接在ScrollView中添加ListView或使用LinearLayout来添加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,Good Guy Greg和Paul的答案的结合。我发现在尝试将其与自定义列表视图适配器和非标准列表项一起使用时,所有这些都是必需的,否则列表视图会使应用程序崩溃(也使Nex的答案崩溃):
public void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
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);
}
您不应该将ListView放在ScrollView中,因为ListView已经是 ScrollView。因此,这就像将ScrollView放入ScrollView中一样。
你想达到什么目的?
我将@DougW转换Utility
为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,当我不得不使用OtherPeople'sCode时,这使我陷入了困境。:-)
setListViewHeightBasedOnChildren()
方法?因为它对我而言并非一直有效。
之前不可能。但是随着新的Appcompat库和Design库的发布,这可以实现。
您只需要使用NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
我不知道它是否可以与Listview一起使用,但可以与RecyclerView一起使用。
代码段:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.widget.NestedScrollView>
嘿,我有一个类似的问题。我想显示一个不会滚动的列表视图,我发现操纵参数有效,但是效率低下,并且在不同设备上的行为会有所不同。.因此,这是我的日程表代码的一部分,实际上非常有效。
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();
}
});
在ScrollView中使用ListView时有两个问题。
1- ListView必须完全扩展到其子级高度。此ListView解决此问题:
public class ListViewExpanded extends ListView
{
public ListViewExpanded(Context context, AttributeSet attrs)
{
super(context, attrs);
setDividerHeight(0);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST));
}
}
分频器的高度必须为0,而应在行中使用填充。
2-ListView消耗触摸事件,因此ScrollView无法像往常一样滚动。此ScrollView解决了此问题:
public class ScrollViewInterceptor extends ScrollView
{
float startY;
public ScrollViewInterceptor(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e)
{
onTouchEvent(e);
if (e.getAction() == MotionEvent.ACTION_DOWN) startY = e.getY();
return (e.getAction() == MotionEvent.ACTION_MOVE) && (Math.abs(startY - e.getY()) > 50);
}
}
这是我发现的最好方法!
感谢Vinay的代码,这是我的代码,当您无法在滚动视图中使用listview却需要类似的东西时
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内,因此所有内容均可滚动:)
public static void setListViewHeightBasedOnChildren(ListView listView)
{
ListAdapter listAdapter = listView.getAdapter();
if(listAdapter == null) return;
if(listAdapter.getCount() <= 1) 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);
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();
}
试试这个,这对我有用,我忘记了我在哪里找到它,在堆栈溢出的某个地方,我不是在这里解释它为什么不起作用的原因,但这就是答案:)。
final ListView AturIsiPulsaDataIsiPulsa = (ListView) findViewById(R.id.listAturIsiPulsaDataIsiPulsa);
AturIsiPulsaDataIsiPulsa.setOnTouchListener(new ListView.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
// Handle ListView touch events.
v.onTouchEvent(event);
return true;
}
});
AturIsiPulsaDataIsiPulsa.setClickable(true);
AturIsiPulsaDataIsiPulsa.setAdapter(AturIsiPulsaDataIsiPulsaAdapter);
编辑!,我终于找到了代码所在。这里 !:ScrollView中的ListView在Android上不滚动
尽管建议的setListViewHeightBasedOnChildren()方法在大多数情况下都可以使用,但在某些情况下,特别是对于很多项目,我注意到没有显示最后一个元素。因此,我决定模仿一个简单的ListView行为版本,以便重用任何Adapter代码,这是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);
}
}
}
}
所有这些答案都是错误的!如果试图将列表视图置于滚动视图中,则应重新考虑您的设计。您正在尝试将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;
}
}
列表适配器可以处理所有内容,因为它仅呈现可见的内容。
如果LinearLayout具有setAdapter方法,那么整个问题就会消失,因为那样的话,当您告诉某人使用它时,替代方法将变得微不足道。
如果您实际上想要在另一个滚动视图中滚动一个ListView,这将无济于事,但是,这至少会给您一个想法。
您需要创建一个自定义适配器,以合并要滚动的所有内容,并将ListView的适配器设置为此。
我没有示例代码,但是如果您需要类似的代码。
<ListView/>
(other content)
<ListView/>
然后,您需要创建一个代表所有内容的适配器。ListView / Adapters足够聪明,可以处理不同的类型,但是您需要自己编写适配器。
android UI API尚不如其他任何东西成熟,因此它不具有与其他平台相同的优点。另外,在android上做某事时,您需要处于android(unix)思维定势中,在这里您可能希望做任何事情,您可能必须组装较小零件的功能并编写一堆自己的代码才能将其导入工作。
该库是解决该问题的最简单,最快的方法。
这是我的计算列表视图总高度的代码版本。这对我有用:
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();
}