我如何把一个ListView放入一个ScrollView而不崩溃?

我四处寻找这个问题的解决方案,我能找到的唯一答案似乎是“不要把ListView放到ScrollView中”。不过,我还没有看到任何关于为什么的真正解释。我能找到的唯一原因似乎是谷歌认为你不应该这么做。我知道,所以我做了。

问题是,如何将ListView放到ScrollView中而不缩到最小高度?

249719 次浏览

你不应该把ListView放在ScrollView中,因为ListView已经一个ScrollView。这就像把一个ScrollView放到一个ScrollView中。

你想要完成什么?

这是我的解决方案。我对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);
}
}

使用ListView使其不滚动是非常昂贵的,并且违背了ListView的全部目的。你应该这样做。只需使用LinearLayout即可。

嘿,我也有类似的问题。我想显示一个列表视图,不滚动,我发现操纵参数工作,但效率低,会在不同的设备上表现不同。因此,这是我的一段调度代码,它实际上非常有效地完成了这个任务。

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();


}


});

由于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中,所以它都是可滚动的:)

< p > 这肯定会工作............ < br > 你只需将布局XML文件中的<ScrollView ></ScrollView>替换为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会给你一个滚动的体验。

如果LinearLayout有一个setAdapter方法,整个问题就会消失,因为当你告诉别人使用它时,替代方案将是微不足道的。

如果你想要一个滚动的ListView在另一个滚动视图中,这不会有帮助,但至少会给你一个想法。

您需要创建一个自定义适配器来组合要滚动的所有内容,并将ListView的适配器设置为该内容。

我手头没有样本代码,但如果你想要。

<ListView/>


(other content)


<ListView/>

然后需要创建一个表示所有这些内容的适配器。ListView/Adapters也足够智能,可以处理不同的类型,但是您需要自己编写适配器。

android的UI API并不像其他平台那么成熟,所以它不像其他平台那么精致。此外,当你在android上做一些事情时,你需要以android (unix)的心态来做任何事情,你可能不得不将更小的部分的功能组装起来,并编写一堆自己的代码来让它工作。

很多的情况下,在ScrollView中有很多意义。

下面是基于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)。

这是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);
}

下面是对@djunod回答的一个小修改,我需要使它完美地工作:

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();
}

下面是我的计算列表视图总高度的代码版本。这个对我很有用:

   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();
}

虽然建议的setListViewHeightBasedOnChildren ()方法在大多数情况下都有效,但在某些情况下,特别是对于很多项,我注意到最后一个元素不显示。所以我决定模仿列表视图行为的简单的版本,以便重用任何适配器代码,这里是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);


}
}
}
}

试试这个,这对我有用,我忘了我在哪里找到它,在堆栈溢出的某个地方, 我不是在这里解释为什么它不工作,但这是答案:)

    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);

编辑!,我终于找到了我从哪里得到的代码。这里!: 在Android上,ScrollView中的ListView不能滚动

在ScrollView中使用ListView有两个问题。

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);
}
}

这是我发现的最好的方法!

我将@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,当我不得不使用其他人的代码时,这让我摆脱了困境。:-)

我们不能同时使用两个滚动。我们将获得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);
}

它有一个内置的设置。在ScrollView中:

android:fillViewport="true"

在Java中,

mScrollView.setFillViewport(true);

Romain Guy在这里深入解释:http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/

当我们把ListView放在ScrollView里面时,会出现两个问题。一个是ScrollView在未指定的模式下测量它的子元素,因此ListView设置自己的高度以只容纳一个元素(我不知道为什么),另一个是ScrollView拦截触摸事件,因此ListView不滚动。

但是我们可以ListView放置在ScrollView中,并使用了一些变通方法。这篇文章,由我,解释了解决方案。通过这个解决方案,我们也可以保留ListView的回收功能。

ListView实际上已经能够测量自身的高度以显示所有项,但是当您简单地指定wrap_content (measurespect . unspecified)时,它不能这样做。当给出一个带有measurespect . 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为AT_MOST,具有非常大的大小(整数。MAX_VALUE >> 4)导致ListView测量它的所有子节点直到给定的(非常大的)高度,并相应地设置它的高度。

这比其他解决方案更好,原因如下:

  1. 它可以正确测量所有内容(填充,分隔线)
  2. 它在测量过程中测量ListView
  3. 由于#2,它正确地处理宽度或项目数量的变化,而不需要任何额外的代码

缺点是,您可能会认为这样做依赖于SDK中未记录的行为,而这些行为可能会更改。另一方面,你可能认为这就是wrap_content与ListView一起工作的方式,而当前的wrap_content行为只是被破坏了。

如果你担心行为可能会在未来发生变化,你应该简单地复制onMeasure函数和相关函数从ListView.java和到你自己的子类,然后使AT_MOST路径通过onMeasure运行为未指定的以及。

顺便说一下,我相信当您处理少量列表项时,这是一种非常有效的方法。与线性布局相比,它可能效率较低,但当项目数量较少时,使用线性布局是不必要的优化,因此也会造成不必要的复杂性。

我使用的一个解决方案是,添加ScrollView的所有内容(应该在listView的上面和下面)作为listView中的headerView和footerView。

它的工作原理是,convertview按它应该的方式重新使用。

这些答案都是错的!! 如果你想把一个列表视图放在滚动视图中,你应该重新考虑你的设计。你试图把一个ScrollView放到一个ScrollView中。干扰列表将损害列表性能。

如果你真的想让列表和其他元素在同一个滚动中,你所要做的就是在适配器中使用一个简单的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;
}




}

列表适配器可以处理所有内容,因为它只呈现可见的内容。

不是把listview放在Scrollview里面,而是把其余的内容放在listview和Scrollview的开头之间,作为一个单独的视图,并将该视图设置为listview的头部。所以你最终将只有列表视图负责滚动。

你创建了一个自定义的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)

这是唯一对我有效的方法:

你可以在棒棒糖上使用

yourtListView.setNestedScrollingEnabled(true);

启用或禁用该视图的嵌套滚动 如果你需要向后兼容旧版本的操作系统,你必须使用RecyclerView.

以前这是不可能的。但是随着新的Appcompat库和Design库的发布,这可以实现。

你只需要使用NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html < / p >

我不知道它将与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>

永远不要在scrollview中使用listview。相反,你应该使用NestedScrollView作为父元素,并在....中使用RecyclerView因为它处理了很多滚动问题