Как я могу поместить ListView в ScrollView без его сворачивания?

Я искал решения этой проблемы, и единственный ответ, который я могу найти, кажется,"не помещайте ListView в ScrollView". Я до сих пор не вижу никакого реального объяснения почему хотя. Единственная причина, по которой я могу найти, заключается в том, что Google не думает, что вы должны хотеть этого. А я знаю, так и было.

Итак, вопрос в том, как вы можете поместить ListView в ScrollView без его сворачивания на минимальную высоту?

27 ответов


С помощью ListView сделать это не свиток, это очень дорого и идет против цели ListView. Вы должны не сделать это. Просто используйте LinearLayout вместо.


вот мое решение. Я довольно новичок в платформе Android, и я уверен, что это немного хакерский, особенно в части о вызове .измерьте непосредственно и установите 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);
    }
}

Это, безусловно, работать............
Вы должны просто заменить <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;
    }
}

Insted положить ListView внутри ScrollView , мы можем использовать ListView Как ScrollView. Вещи, которые должны быть в ListView можно поместить внутрь ListView. Другие макеты сверху и снизу ListView можно поместить, добавив макеты в верхний и Нижний колонтитулы ListView. Так вся ListView даст вам опыт скроллинга .


здесь много ситуаций, когда имеет смысл иметь ListView в 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) на каждый внедренный элемент управления ListView.


ListView фактически уже способен измерять себя, чтобы быть достаточно высоким, чтобы отображать все элементы, но он не делает этого, когда вы просто указываете wrap_content (MeasureSpec.НЕОПРЕДЕЛЕННЫЙ.) Он будет делать это, когда задана высота с 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 должен быть AT_MOST с очень большим размером (целое число.MAX_VALUE >> 4) заставляет ListView измерять все его дочерние элементы до заданной (очень большой) высоты и устанавливать ее высоту соответственно.

это работает лучше, чем другие решения по нескольким причинам:

  1. он измеряет все правильно (отступы, разделители)
  2. он измеряет ListView во время прохождения меры
  3. должный к #2, оно регулирует изменения в ширине или количестве деталей правильно без дополнительного кода

С другой стороны, вы можете утверждать, что это зависит от недокументированного поведения в SDK, которое может измениться. С другой стороны, вы можете утверждать, что именно так wrap_content должен действительно работать с ListView и что текущее поведение wrap_content просто нарушено.

Если вы беспокоитесь, что поведение может измениться в будущем, вы должны просто скопировать функцию onMeasure и связанные с ней функции из элемент управления ListView.java и в свой собственный подкласс, затем сделайте путь AT_MOST через onMeasure для неопределенного также.

кстати, я считаю, что это вполне допустимый подход, когда вы работаете с небольшим количеством элементов списка. Это может быть неэффективно по сравнению с LinearLayout, но когда количество элементов невелико, использование LinearLayout является ненужной оптимизацией и, следовательно, ненужной сложностью.


для него есть встроенная настройка. На ScrollView:

android:fillViewport="true"

В Java,

mScrollView.setFillViewport(true);

Ромен Гай подробно объясняет это здесь:http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/


мы не можем использовать две прокрутки simulteniuosly.Мы получим общую длину ListView и развернем listview с общей высотой .Затем мы можем добавить ListView в ScrollView напрямую или с помощью LinearLayout, потому что ScrollView имеет непосредственно одного ребенка . скопируйте метод setListViewHeightBasedOnChildren (lv) в свой код и разверните listview, затем вы можете использовать listview внутри scrollview. \макет 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>

метод onCreate в классе Activity:

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

вы создаете пользовательский 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);


Это совокупность ответов на DougW, хороший парень Грег, и Пол. Я обнаружил, что все это было необходимо при попытке использовать это с пользовательским адаптером listview и нестандартными элементами списка, иначе listview разбил приложение (также разбился с ответом 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);
    }

я сконвертировал @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 в ScrollView, потому что ListView уже is ScrollView. Так что это было бы похоже на размещение ScrollView в 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();

            }

        });

есть две проблемы при использовании ListView внутри ScrollView.

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

Это лучший способ я нашел, чтобы сделать трюк!


это единственное, что сработало для меня:

на леденец вперед вы можете использовать

yourtListView.setNestedScrollingEnabled(true);

включить или отключить вложенную прокрутку для этого представления если вам нужна обратная совместимость со старой версией ОС, вам придется использовать RecyclerView.


спасибо код вине вот мой код, когда вы не можете иметь listview внутри scrollview, но вам нужно что-то вроде этого

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, поэтому все становится прокручиваемым:)


вот небольшая модификация на @djunod ' s ответ что мне нужно, чтобы он работал отлично:

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

редактировать ! Наконец-то я узнал, откуда у меня код. сюда ! : ListView внутри ScrollView не прокручивается на Android


хотя предложил 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);

        }
    }
}
}

решение, которое я использую, чтобы добавить все содержимое ScrollView (что должно быть выше и под listView) в качестве headerView и footerView в ListView.

Так что это работает, как, также convertview resued, как это должно быть.


все эти ответы неверны!!! Если вы пытаетесь поместить listview в представление прокрутки, вы должны пересмотреть свой дизайн. Вы пытаетесь поместить 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;
    }


}

адаптер списка может обрабатывать все, так как он отображает только то, что видно.


раньше это было невозможно. Но с выпуском новых библиотек Appcompat и библиотек дизайна это может быть достигнуто.

вам просто нужно использовать 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>

вся эта проблема просто исчезнет, если LinearLayout имеет метод setAdapter, потому что тогда, когда вы сказали кому-то использовать его вместо этого, альтернатива будет тривиальной.

Если вы действительно хотите прокрутку ListView внутри другого прокрутки, это не поможет, но в противном случае это, по крайней мере, даст вам представление.

вам нужно создать пользовательский адаптер, чтобы объединить все содержимое, которое вы хотите прокрутить, и установить адаптер ListView на это.

I пока нет примера кода под рукой, но если вы хотите что-то подобное.

<ListView/>

(other content)

<ListView/>
вам нужно создать адаптер, который представляет все это содержимое. ListView / адаптеры достаточно умны для обработки различных типов, а также, но вам нужно написать адаптер самостоятельно.

API Android UI просто не так зрелый, как почти все остальное, поэтому у него нет таких же тонкостей, как у других платформ. Кроме того, при выполнении чего-то на android вам нужно быть в Android (unix) мышление, где вы ожидаете, что делать все, что вы, вероятно, придется собрать функциональность меньших частей и написать кучу собственного кода, чтобы заставить его работать.


когда мы ставим ListView внутри ScrollView возникают две проблемы. Один ScrollView измеряет своих детей в неуказанном режиме, поэтому ListView устанавливает свою собственную высоту для размещения только одного элемента (я не знаю, почему), другой ScrollView перехватывает событие касания так ListView не прокручивается.

а то can место ListView внутри ScrollView с некоторым обходным путем. этот пост по-моему, объясняет обходной путь. Этим обходным путем мы также можем сохранить ListView'ы особенность переработки, а также.


вместо того, чтобы помещать listview внутри Scrollview, поместите остальную часть содержимого между listview и открытием Scrollview в качестве отдельного представления и установите это представление в качестве заголовка 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();
}