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

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

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

Ответ 1

Использование ListView, чтобы сделать его не прокруткой, чрезвычайно дорого и противоречит целям ListView. Вы должны НЕ сделать это. Просто используйте LinearLayout вместо этого.

Ответ 2

Вот мое решение. Я новичок в платформе 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);
    }
}

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

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 как AT_MOST с очень большим размером (Integer.MAX_VALUE → 4) заставляет ListView измерять все его дочерние элементы до заданной (очень большой) высоты и соответственно устанавливать ее высоту.

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

  • Он правильно измеряет все (отступы, разделители)
  • Он измеряет ListView во время прохождения меры
  • Из-за # 2 он корректно обрабатывает изменения в ширине или количестве элементов без дополнительного кода

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

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

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

Ответ 8

Мы не могли бы использовать две прокрутки одновременно. Мы получим общую длину ListView и раскройте listview с общей высотой. Затем мы можем добавить ListView в ScrollView напрямую или с помощью LinearLayout, потому что ScrollView имеет непосредственно один ребенок. скопируйте метод setListViewHeightBasedOnChildren (lv) в свой код и разверните listview, после чего вы можете использовать listview внутри scrollview. \ layout xml file

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

Ответ 9

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

Ответ 10

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

Ответ 11

Я преобразовал @DougW Utility в С# (используется в 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'Code.: -)

Ответ 12

Вы не должны помещать ListView в ScrollView, потому что ListView уже является ScrollView. Таким образом, это будет похоже на создание ScrollView в ScrollView.

Что вы пытаетесь выполнить?

Ответ 13

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

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

            }

        });

Ответ 14

Есть две проблемы при использовании 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);
    }
}

Это лучший способ найти трюк!

Ответ 15

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

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

yourtListView.setNestedScrollingEnabled(true);

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

Ответ 16

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

Ответ 17

Ниже приведена небольшая модификация @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();
}

Ответ 18

Хотя предлагаемые методы 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);

        }
    }
}
}

Ответ 19

попробуйте это, это работает для меня, я забыл, где я его нашел, где-то в переполнении стека, Я не здесь, чтобы объяснить это, почему это не работает, но это ответ:).

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

EDIT!, я наконец узнал, где я получил код. Вот!: ListView внутри ScrollView не прокручивается на Android

Ответ 20

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

Таким образом, он работает так же, как и конвертирование, как это должно быть.

Ответ 21

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


}

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

Ответ 22

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

Вам просто нужно использовать NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

Я не знаю, что он будет работать со списком или нет, но работает с 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>

Ответ 23

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

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

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

У меня нет примерного кода, но если вы хотите что-то вроде.

<ListView/>

(other content)

<ListView/>

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

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

Ответ 24

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

Но мы можем разместить ListView внутри ScrollView с помощью некоторого обходного пути. Этот пост, я объясняю обходным путем. К этому решению мы также можем сохранить функцию утилизации ListView.

Ответ 25

Вместо того чтобы помещать список в Scrollview, поместите остальную часть содержимого между списком и открытием Scrollview в виде отдельного представления и установите это представление как заголовок списка. Таким образом, вы, наконец, закончите только просмотр списка с учетом прокрутки.

Ответ 26

Эта библиотека является самым простым и быстрым решением проблемы.

Ответ 27

Вот моя версия кода, которая вычисляет общую высоту списка. Это работает для меня:

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