ListView in Scroll View Мой просмотр прокрутки перемещается в начало списка. Как мне предотвратить это? - PullRequest
7 голосов
/ 22 февраля 2012

У меня есть представление списка в моем представлении прокрутки под почти прокручиваемой страницей до этого, но как только мой список просмотра заполняется, представление прокрутки перемещается к вершине представления списка.как я могу это исправить / предотвратить это?

ПРОСМОТР ПРОКРУТКИ XML:

<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <include 
            layout="@layout/a" />

        <include 
            layout="@layout/b" />

        <include 
            layout="@layout/c" />

        <include 
            layout="@layout/d" />


<ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

    </LinearLayout>
</ScrollView>

Я пытался выполнить sv.fullScroll (ScrollView.FOCUS_UP);и все такое в моем просмотре прокрутки, но это не работает

Ответы [ 13 ]

9 голосов
/ 03 сентября 2015

Мы никогда не должны помещать ListView в ScrollView.

Обход: когда ScrollView движется вверх / вниз из-за списка notifyDataSetChanged(), затем попробуйте,

scrollview.setEnabled(false);
listview.setFocusable(false);
adapter.notifyDataSetChanged();
scrollview.setEnabled(true);
8 голосов
/ 10 февраля 2014

Во-первых, возможно, вы уже слышали об этом, но на всякий случай: Никогда не следует помещать ListView внутри ScrollView, так как сам ListView уже получил ScrollView и этот дизайн противоречит всей идее ListView.Если вы убеждены, что вам нужно его использовать, возможно, есть лучший подход, и вам может понадобиться как-то упростить ваш код.

Теперь, даже если вы все еще хотите использовать что-то подобное, вы можете использоватьчто-то вроде этого:

package your.package.name;

import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;

public class ScrollingListView {
  public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter(); 
    if (listAdapter == null)
      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);
  }
}

Вы просто устанавливаете свой адаптер с помощью .setAdapter(), а затем вызываете ScrollingListView.setListViewHeightBasedOnChildren(your_listview).Это должно изменить размеры вашего окна в соответствии с вашим ListView ростом.

---- РЕДАКТИРОВАТЬ ----

Это, вероятно, самый уродливый обходной путь, но попробуйтеделаем следующее:

ScrollView sv = (ScrollView) findViewById(R.id.your_scrollview);
sv.setEnabled(false);
// Populate your ListView
sv.setEnabled(true);
3 голосов
/ 23 сентября 2016

Просто сделайте одну вещь, прежде чем добавлять элементы в ваш список

listview.setFocusable(false);

, после этого вы можете снова сделать это

listview.setFocusable(true);

при необходимости это будет работать наверняка

2 голосов
/ 16 февраля 2014

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

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

public class NonScrollableListView extends ListView {
    public NonScrollableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Do not use the highest two bits of Integer.MAX_VALUE because they are
        // reserved for the MeasureSpec mode
        int heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightSpec);
        getLayoutParams().height = getMeasuredHeight();
    }

}

Опять же, не рекомендуется использовать этот обходной путь

2 голосов
/ 22 февраля 2012

добавить:

android:transcriptMode="disabled"

в списке, который вы не хотите прокручивать

Из документов Android

2 голосов
/ 22 февраля 2012

Добавьте все элементы сверху как header в представление списка.

Теперь, когда я вижу код ... у вас может быть только одна ViewGroup внутри scrollview.Таким образом, вы бы перетянули два макета в другой, НО ListView автоматически имеет вид прокрутки, так что он действительно не будет работать.

Итак, вам нужно использовать представление addHeader в ListActivity (фрагмента) и накачать LinearLayout1 в упражнении из другого XML-файла.

1 голос
/ 17 февраля 2014

Вы можете достичь этого с помощью следующего:

 <LinearLayout 
......>
<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <include 
            layout="@layout/a" />

        <include 
            layout="@layout/b" />

        <include 
            layout="@layout/c" />

        <include 
            layout="@layout/d" />

    </LinearLayout>
</ScrollView>
<ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
 </LinearLayout>

Оберните ваш просмотр списка вне просмотра прокрутки, а также внутри просмотра прокрутки, потому что Вы никогда не должны использовать ScrollView с ListView, потому что ListView заботится о своей собственной вертикальной прокрутке. Что наиболее важно, выполнение этого снимает все важные оптимизации в ListView для работы с большими списками, поскольку фактически заставляет ListView отображать весь список элементов, чтобы заполнить бесконечный контейнер, предоставляемый ScrollView.

Исходные документы для Android

1 голос
/ 16 февраля 2014

Я сделал 2 или 3 изменения в вашем xml-файле

<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" 
        android:padding="10dp">  // This will let you see the scroll bar of list view
                                    when you scroll your list view.

        <include 
            layout="@layout/a" />
        <include 
            layout="@layout/b" />
        <include 
            layout="@layout/c" />
        <include 
            layout="@layout/d" />


    <ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="300dp" />// Instead of wraping up your list, if you wish
                                       you can give certain height to your list view.

    </LinearLayout>
</ScrollView>

Еще одна вещь, которая вам нужна - написать указанный код в вашем java-файле.

   onCreate()
  {
   ....
   ScrollView sView=(ScrollView)findViewById(R.id.tvscrollview);

   yourListView.setOnTouchListener(new OnTouchListener()
    {
        public boolean onTouch(View arg0, MotionEvent arg1) 
        {
            if(arg1.getAction() == MotionEvent.ACTION_DOWN ||   arg1.getAction() == MotionEvent.ACTION_MOVE)
            {
                sView.requestDisallowInterceptTouchEvent(true);
            }
            return false;
        }
    });

Надеюсь, это поможетвы.

1 голос
/ 12 февраля 2014

Я бы обернул список и другие макеты в RelativeLayout вместо LinearLayout

<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <include 
                layout="@layout/a" />

            <include 
                layout="@layout/b" />

            <include 
                layout="@layout/c" />

            <include 
                layout="@layout/d" />

        </LinearLayout>

        <ListView
            android:id="@+id/listview"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/container" />

    </RelativeLayout>
</ScrollView>

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

Вы не можете поместить включения непосредственно в RelativeLayout!Подробнее см. здесь .

0 голосов
/ 14 марта 2017

Я попробовал вышеуказанные ответы, но ни один из них не сработал.Ниже мое окончательное решение.Просто переопределите метод onFinishInflate , а затем отправьте сообщение в scrollTo (0, 0).

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
        this.post(new Runnable() {
            @Override
            public void run() {
                scrollTo(0, 0);
            }
        });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...