Представление списка Android в представлении прокрутки


268

У меня есть макет Android, который имеет scrollViewнесколько элементов с в нем. В нижней части у scrollViewменя есть, listViewкоторый затем заполняется адаптером.

Проблема, которую я испытываю, заключается в том, что Android исключает listViewиз, scrollViewпоскольку scrollViewуже имеет функцию прокрутки. Я хочу, listViewчтобы содержимое было таким же, как и содержимое, и чтобы представление основного прокрутки имело возможность прокрутки.

Как я могу добиться этого поведения?

Вот мой основной макет:

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="2"
    android:fillViewport="true"
    android:gravity="top" >

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

</ScrollView>

Затем я программно добавить свои компоненты в linearlayour с идентификатором: foodItemActvity_linearLayout_fragments. Ниже приведено одно из представлений, загруженных в этот линейный макет. Это тот, кто доставляет мне неприятности со свитками.

<?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="wrap_content"
    android:orientation="vertical" >

    <TextView
       android:id="@+id/fragment_dds_review_textView_label"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Reviews:"
       android:textAppearance="?android:attr/textAppearanceMedium" />

   <ListView
       android:id="@+id/fragment_dds_review_listView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
   </ListView>
</LinearLayout>

Мой адаптер затем заполняет этот список.

Вот изображение из средства просмотра иерархии Android, когда я нажимаю на главный scrollView:

Android List View внутри прокрутки

Как видите, это исключение списка просмотра отзывов.

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



я получаю решение на: androidhub4you.com/2012/12/…
Md Imran Choudhury

Вот. Вы можете найти полную описательную информацию: stackoverflow.com/questions/20116381/…
Фаррух Хабибуллаев

Это очень легко использовать RecycleView от имени ListView
Ананд Радж Мехта

Я надеюсь, что это будет работать для вас stackoverflow.com/a/62011087/11554604
S Кумар

Ответы:


559

Самое короткое и простое решение для любого ChildView для прокрутки внутри ScrollView . Что-нибудь вроде ListView, RecyclerView и т. Д. Вам не нужно делать ничего особенного в коде.

Просто замените ScrollView на android.support.v4.widget.NestedScrollView в текущем xml, и тогда произойдет волшебство.

Ниже приведен пример XML-кода:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:paddingBottom="20dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Recycler View inside a Scroll View"
            android:textColor="@color/black"
            android:textSize="@dimen/_20sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="Below is a Recycler View as an example."
            android:textSize="16sp" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toBottomOf="@id/et_damaged_qty" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="This text automatically goes below the Recycler View."
            android:textSize="16sp" />
    </android.support.v7.widget.LinearLayoutCompat>
</android.support.v4.widget.NestedScrollView>

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

Время играть. Черт, даааааааааааааааа!

введите описание изображения здесь


1
@JeetenParmar уже указал эту проблему, опять же, должен сказать - это хороший хак, но он не работает, когда в TextView есть несколько строк. Аршу - ваше более позднее решение для Джитена также не работает (Джитен уже уточнил). Если вы найдете какое-либо решение для этого, пожалуйста, напишите здесь. Мне очень нужно решение.
Хобайб

4
Я нашел это решение, которое отлично работает в моем случае, т.е. поддерживает элементы списка с переменной высотой - stackoverflow.com/a/17503823/1433187
Хобайб,

3
Пожалуйста, удалите избыточный requestLayout()- метод setLayoutParams уже делает это.
Алексей Малованый

2
Измерение FIXview.measure(MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.AT_MOST),MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
Алексей Малованый

2
Мне нужно сделать то же самое с gridview .. Любое предложение?
Кролик

223

Ответ прост, и я удивлен, что здесь еще нет ответа.

Используйте Header Viewили или и Footer Viewв самом списке. Не смешивайте ScrollViewс ListViewили что-нибудь, что может прокрутить. Он предназначен для использования с верхними и нижними колонтитулами :)

По сути, возьмите все содержимое над ListView, поместите его в другой файл .xml в качестве макета, а затем в коде надуйте его и добавьте в список в качестве представления заголовка.

т.е.

View header = getLayoutInflater().inflate(R.layout.header, null);
View footer = getLayoutInflater().inflate(R.layout.footer, null);
listView.addHeaderView(header);
listView.addFooterView(footer);

2
@ericosg, но я не хочу, поэтому я ищу решение.
Джитен Пармар

13
Если вы добавите представление заголовка, позиция int param в onListItemClick будет +1. Таким образом, вы должны справиться с этим. (первый элемент в списке будет иметь позицию 1, а не 0)
CoPLaS

Я хотел бы, чтобы был заголовок для ViewPager.
Хасан

2
Хотелось бы, чтобы был заголовок для GridView
Someone Somewhere

1
этот подход подходит, если вам не нужен edittext в заголовке. Edittext не сохраняет фокус, когда присутствует в просмотре списка
Balwinder SIngh

40

Я знаю, что это было так долго, но я тоже получил эту проблему, попробовал это решение, и оно работает. Поэтому я думаю, что это может помочь и другим.

Я добавляю android: fillViewport = "true" в XML-макет для scrollView. Так что в целом мой ScrollView будет таким.

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scrollView6" 
    android:fillViewport="true">

И это работает как волшебство для меня. ListView, который находится внутри моего ScrollView, снова расширяется до своего размера.

Вот полный пример кода для ScrollView и ListView.

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scrollView6" android:fillViewport="true">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        ....
        <ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/lv_transList" android:layout_gravity="top"
            android:layout_marginTop="5dp"/>
        ....
    </LinearLayout>
</ScrollView>

4
Он отключает режим прокрутки ListView, поэтому вы не можете прокрутить представление списка, если элементы больше, чем размер экрана.
Даруш

3
Это отключает возможности прокрутки ScrollView
Pranav Mahajan

Это решение не работает, потому что, если просмотр списка занимает весь экран, элементы под списком недоступны
Yash Jain

24

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

В вашем файле ресурсов макета

     <?xml version="1.0" encoding="utf-8"?>
        <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fadingEdgeLength="0dp"
            android:fillViewport="true"
            android:overScrollMode="never"
            android:scrollbars="none" >

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

        </ScrollView>

В Java-файле создайте объект вашего customListview вместо ListView, например: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);


или можете поделиться просто ссылкой
чудо-доу

Это заставляет scrollview прокручивать вверху списка. неожиданное поведение
Бхавик Мехта

8
    public static void setListViewHeightBasedOnChildren(ListView listView) {
    // 获取ListView对应的Adapter
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        return;
    }

    int totalHeight = 0;
    for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(0, 0); // 计算子项View 的宽高
        totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    // listView.getDividerHeight()获取子项间分隔符占用的高度
    // params.height最后得到整个ListView完整显示需要的高度
    listView.setLayoutParams(params);
}

Вы можете использовать этот код для просмотра списка в scrollview


Будет ли это отключить Listviews встроенный прокрутки?
Zapnologica

Это также будет работать ListViewвнутри, RecyclerViewчтобы показать больше, чем 1-й элемент.
сандал

8

Вы можете решить это, добавив android:fillViewport="true"в свой ScrollView.

<ScrollView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@color/white"
      android:fillViewport="true"
      android:scrollbars="vertical">

<ListView
      android:id="@+id/statusList"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:animationCache="false"
      android:divider="@null"
      android:scrollingCache="false"
      android:smoothScrollbar="true" />

</ScrollView>


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


Android: scrollingCache = "false" больше не поддерживается для новых версий Android выше v8.
бухта

7

Ничего не делать в родительском ScrollView. Сделайте это только для дочернего ListView. Все будет отлично работать.

mListView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mScrollView.requestDisallowInterceptTouchEvent(true);
               int action = event.getActionMasked();
                switch (action) {
                    case MotionEvent.ACTION_UP:
                        mScrollView.requestDisallowInterceptTouchEvent(false);
                        break;
                }
                return false;
            }
        });

2
Это должен быть принятый ответ. Это просто и умно. Просто отключите вид прокрутки, когда вы касаетесь listiview, и включите его снова, когда вы поднимаете палец
Юнус Кулиев,

Работал отлично. Надеюсь, что другие прокрутить вниз к этому ответу тоже!
Кундж Мехта

6

Этот код решит вашу проблему, если вы внедрили в код только ListView.

Если вы используете RelativeLayout в качестве дочернего элемента ListView, этот код возвращает здесь исключение NullPointerException listItem.measure (0, 0); , из-за RelativeLayout. И решение помещает ваш Relativelayout в LinearLayout, и он будет работать нормально.

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

Если у вас есть отступы в вашем списке, вы должны добавить это тоже: - int padding = listView.getPaddingTop () + listView.getPaddingBottom ();
Дэвид

Да, относительная компоновка создает проблемы при расчете высоты. Спасибо за объяснение Относительной проблемы расположения
Анил Равсахеб Годэйк

5

Я оставлю это здесь на случай, если кто-то столкнется с той же проблемой. Я должен был поместить ListView внутри ScrollView. ListView с заголовком не был вариантом по ряду причин. Также не было возможности использовать LinearLayout вместо ListView. Поэтому я следовал принятому решению, но оно не сработало, потому что элементы в списке имели сложную компоновку с несколькими строками, а каждый элемент списка имел переменную высоту. Высота была измерена не правильно. Решением было измерить каждый элемент внутри метода getView () адаптера ListView.

@Override
public View getView(int position, View view, ViewGroup parent) {
    ViewHolder holder;
    if (view == null) {
        . . .
        view.setTag(holder);
    } else holder = (ViewHolder)view.getTag();
    . . .

    // measure ListView item (to solve 'ListView inside ScrollView' problem)
    view.measure(View.MeasureSpec.makeMeasureSpec(
                    View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    return view;
}

5

Вы можете легко поместить ListView в ScrollView! Просто нужно высоту изменения в ListView программно , например:

    ViewGroup.LayoutParams listViewParams = (ViewGroup.LayoutParams)listView.getLayoutParams();
    listViewParams.height = 400;
    listView.requestLayout();

Это работает отлично!


3
Это то, что делает принятый ответ , но вместо магического определения его 400, он вычисляет точную высоту. Таким образом, вам не нужно угадывать.
Йерун Ванневел

Что ты имеешь в виду под магией "ровно высота"? Какой именно высоты должна быть, выберет только разработчик - 400px или половина экрана. В любом случае, если вам нужно получить ListView в полноэкранном режиме, есть очень простой способ получить высоту, просто вычислить высоту экрана с помощью DisplayMetrics и поместить это число в высоту ListView. XD
Тарас Окунев

4

Сделано после большого количества исследований и разработок:

Fragment_one.xml должен выглядеть так:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scrollViewParent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="400dip" >

            <ListView
                android:id="@+id/listView"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <View
                android:id="@+id/customView"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="@android:color/transparent" />
        </RelativeLayout>

        <!-- Your other elements are here -->

    </LinearLayout>

</ScrollView>

Ваш Java-класс FragmentOne.java выглядит следующим образом:

private ListView listView;
private View customView

onCreateView

listView = (ListView) rootView.findViewById(R.id.listView);
scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent);
customView = (View)rootView.findViewById(R.id.customView);

customView.setOnTouchListener(new View.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.
                        scrollViewParent.requestDisallowInterceptTouchEvent(true);
                        // Disable touch on transparent view
                        return false;

                    case MotionEvent.ACTION_UP:
                        // Allow ScrollView to intercept touch events.
                        scrollViewParent.requestDisallowInterceptTouchEvent(false);
                        return true;

                    case MotionEvent.ACTION_MOVE:
                        scrollViewParent.requestDisallowInterceptTouchEvent(true);
                        return false;

                    default:
                        return true;
                }
            }
        });

4

У меня была такая же проблема, как и у оригинального плаката - как сделать прокрутку списка внутри прокрутки - и этот ответ решил мою проблему. Отключить прокрутку ListView, содержащегося в ScrollView

Я не вызывал новые фрагменты в существующие макеты или что-то подобное, как это делал OP, поэтому мой код выглядел бы примерно так:

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="2"
    android:fillViewport="true"
    android:gravity="top" >

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


    <TextView
       android:id="@+id/fragment_dds_review_textView_label"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Reviews:"
       android:textAppearance="?android:attr/textAppearanceMedium" />

   <ListView
       android:id="@+id/my_listView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
   </ListView>

</LinearLayout>

</ScrollView>

По сути, я проверяю длину списка перед тем, как я его вызываю, и когда я его называю, я делаю его на такую ​​длину. В вашем Java-классе используйте эту функцию:

public static void justifyListViewHeightBasedOnChildren (ListView listView) {

    ListAdapter adapter = listView.getAdapter();

    if (adapter == null) {
        return;
    }
    ViewGroup vg = listView;
    int totalHeight = 0;
    for (int i = 0; i < adapter.getCount(); i++) {
        View listItem = adapter.getView(i, null, vg);
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

    ViewGroup.LayoutParams par = listView.getLayoutParams();
    par.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1));
    listView.setLayoutParams(par);
    listView.requestLayout();
}

И вызвать функцию следующим образом:

justifyListViewHeightBasedOnChildren(listView);

Результатом является представление списка без полосы прокрутки, отображаемой по всей длине просмотра списка, которое прокручивается с помощью полосы прокрутки просмотра прокрутки.


3

Как уже упоминали другие, не используйте ListView внутри ScrollView.

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

Вы можете использовать этот класс в качестве замены LinearLayout, которая поддерживает адаптеры

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;

public class AdaptableLinearLayout extends LinearLayout {

private BaseAdapter mAdapter;

private int mItemCount = 0;

private boolean mDisableChildrenWhenDisabled = false;

private int mWidthMeasureSpec;
private int mHeightMeasureSpec;


public AdaptableLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}

public BaseAdapter getAdapter() {
    return mAdapter;
}

public void setAdapter(BaseAdapter adapter) {
    mAdapter = adapter;
    adapter.registerDataSetObserver(new DataSetObserver() {
        @Override
        public void onChanged() {
            updateLayout();
            super.onChanged();
        }

        @Override
        public void onInvalidated() {
            updateLayout();
            super.onInvalidated();
        }
    });
    updateLayout();
}

private void updateLayout() {
    mItemCount = mAdapter.getCount();
    requestLayout();
    invalidate();
}

/**
 * set size for the current View
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mWidthMeasureSpec = widthMeasureSpec;
    mHeightMeasureSpec = heightMeasureSpec;

    removeAllViewsInLayout();
    for (int i = 0; i < mItemCount; i++) {
        makeAndAddView(i);
    }
}

private View makeAndAddView(int position) {
    View child;

    // Nothing found in the recycler -- ask the adapter for a view
    child = mAdapter.getView(position, null, this);

    // Position the view
    setUpChild(child, position);

    return child;

}

private void setUpChild(View child, int position) {

    ViewGroup.LayoutParams lp = child.getLayoutParams();
    if (lp == null) {
        lp = generateDefaultLayoutParams();
    }
    addViewInLayout(child, position, lp);

    // Get measure specs
    int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, getPaddingTop() + getPaddingBottom(), lp.height);
    int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, getPaddingLeft() + getPaddingRight(), lp.width);

    // Measure child
    child.measure(childWidthSpec, childHeightSpec);

    int childLeft;
    int childRight;

    // Position vertically based on gravity setting
    int childTop = getPaddingTop() + ((getMeasuredHeight() - getPaddingBottom() - getPaddingTop() - child.getMeasuredHeight()) / 2);
    int childBottom = childTop + child.getMeasuredHeight();

    int width = child.getMeasuredWidth();
    childLeft = 0;
    childRight = childLeft + width;

    child.layout(childLeft, childTop, childRight, childBottom);

    if (mDisableChildrenWhenDisabled) {
        child.setEnabled(isEnabled());
    }
}
}

это управляет переработкой? или адаптер отвечает за переработку просмотров?
Рене М

Я реализовал этот класс довольно давно, поэтому я думаю, что с целью dev.speed я не добавил поддержку утилизации. Как я вижу в коде прямо сейчас, класс предполагает, что переработчик пуст
А.А. Аверин

3

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="0dip" android:layout_weight="0.8">

    <LinearLayout
        android:id="@+id/seTaskActivityRoot"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/taskName" />


        <Spinner
            android:id="@+id/seTaskPrioritiesSP"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/taskTargetInNumeric" />

        <Spinner
            android:id="@+id/seTaskUnitsSP"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/newTaskCurrentStatus" />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:hint="@string/addTaskCurrentStatus"
            android:inputType="numberDecimal" />


    </LinearLayout>
</ScrollView>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0dip"
    android:orientation="vertical" android:layout_weight="0.2">

    <TextView
        android:id="@+id/textView8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />

    <ListView
        android:id="@+id/logList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>


3

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

http://developer.android.com/reference/android/widget/ScrollView.html


3

Мое требование - включить ListView элементов одинакового размера в ScrollView. Я попробовал несколько других решений, перечисленных здесь, но ни одно из них не соответствовало правильному размеру ListView (либо слишком мало места, либо слишком много). Вот что сработало для меня:

    public static void expandListViewHeight(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null)
        return;

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    listView.measure(0, 0);
    params.height = listView.getMeasuredHeight() * listAdapter.getCount() + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
}

Надеюсь, это кому-нибудь поможет.


2

НИКОГДА не кладите ListViewвнутрь ScrollView! Вы можете найти больше информации на эту тему в Google . В вашем случае используйте LinearLayoutвместо ListViewи добавьте элементы программно.


3
О, хорошо, я вижу, могу ли я использовать аналогичную концепцию адаптера для заполнения линейного макета?
Запнологика

2

Обновить

<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:fillViewport="true"
android:gravity="top" >

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

в

<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:fillViewport="true"
android:gravity="top" >

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

Дело в том, что вы пытаетесь установить высоту 0dp (исправлено)


Это так, что веса влияют на это.
Запнологика

Вы хотите, чтобы изображение продукта и левый текст на верхней стороне были прокручиваемыми? Если это так , вы должны эти два элемента внутри вашей точки зрения прокрутки , как я могу видеть , в настоящее время они не являются
Rajnish Мишра

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

2

нашел решение для scrollview -> viewpager -> FragmentPagerAdapter -> фрагмент -> динамический просмотр списка, но я не автор. есть некоторые ошибки, но, по крайней мере, это работает

public class CustomPager extends ViewPager {

    private View mCurrentView;

    public CustomPager(Context context) {
        super(context);
    }

    public CustomPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mCurrentView == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        int height = 0;
        mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = mCurrentView.getMeasuredHeight();
        if (h > height) height = h;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void measureCurrentView(View currentView) {
        mCurrentView = currentView;
        this.post(new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        });
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}


public class MyPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    private int mCurrentPosition = -1;


    public MyPagerAdapter(FragmentManager fm) {
        super(fm);//or u can set them separately, but dont forget to call notifyDataSetChanged()
        this.fragments = new ArrayList<Fragment>();
        fragments.add(new FirstFragment());
        fragments.add(new SecondFragment());
        fragments.add(new ThirdFragment());
        fragments.add(new FourthFragment());
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        if (position != mCurrentPosition) {
            Fragment fragment = (Fragment) object;
            CustomPager pager = (CustomPager) container;
            if (fragment != null && fragment.getView() != null) {
                mCurrentPosition = position;
                pager.measureCurrentView(fragment.getView());
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

макет фрагментов может быть любым

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
    android:layout_height="match_parent" tools:context="nevet.me.wcviewpagersample.FirstFragment">


    <ListView
        android:id="@+id/lv1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#991199"/>
</LinearLayout>

тогда где-то просто

lv = (ListView) view.findViewById(R.id.lv1);
        lv.setAdapter(arrayAdapter);
        setListViewHeightBasedOnChildren(lv);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        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,
                        LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }

2
  • Невозможно использовать представление прокрутки в представлении списка, так как представление списка уже имеет свойство прокрутки.
  • Чтобы использовать просмотр списка внутри Scroll-view, вы можете выполнить следующие шаги, которые работали для меня:

    1) Создайте Java-файл NonScrollListView, который отключает свойство прокрутки по умолчанию для просмотра списка. и код ниже

    package your-package-structure;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.ViewGroup;
    import android.widget.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();
      }
    }

    2) Теперь создайте XML-файл, который имеет NestedScrollViewи внутри этого использования NonScrollListViewдля перечисления ваших предметов. Это заставит весь ваш экран прокручивать все просмотры.

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical">
                <ViewFlipper
    
                    android:id="@+id/v_flipper"
                    android:layout_width="match_parent"
                    android:layout_height="130dp">
                </ViewFlipper>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
    
                    android:text="SHOP"
                    android:textSize="15dp"
                    android:textStyle="bold"
                    android:gravity="center"
                    android:padding="5dp"
                    android:layout_marginTop="15dp"
                    android:layout_marginBottom="5dp"
                    android:layout_marginLeft="8dp"
                    android:layout_marginRight="8dp"/>
                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
    
                    android:layout_marginBottom="8dp"
                    android:layout_marginLeft="8dp"
                    android:layout_marginRight="8dp"
                    android:background="#ddd"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_weight="1"
                >
                <com.abc.xyz.NonScrollListView
                    android:id="@+id/listview"
    
                    android:divider="@null"
                    android:layout_width="match_parent"
                    android:layout_marginBottom="10dp"
                    android:layout_height="match_parent"
                    android:padding="8dp">
                </com.abc.xyz.NonScrollListView>
            </LinearLayout>
    
           <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
    
                android:gravity="bottom">
                <include layout="@layout/footer" />
            </LinearLayout>
    
        </LinearLayout>

    3) Теперь в Java-классе, т. Е. Home.java определить NonScrollListViewвместо Listview.

    package comabc.xyz.landscapeapp;
    import android.content.Intent;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.v4.app.Fragment;
    import android.os.Bundle;
    import android.support.v4.app.FragmentTransaction;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import android.widget.ListView;
    import android.widget.Toast;
    import android.widget.Toolbar;
    import android.widget.ViewFlipper;

    публичный класс дома расширяет Fragment {int pos = 0; ViewFlipper v_flipper;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_home, container, false);
        return view;
    }
    
    @Override
    public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
        NonScrollListView listView = (NonScrollListView) view.findViewById(R.id.listview);
        customAdapter customAdapter = new customAdapter(getActivity());
        listView.setAdapter(customAdapter);
        listView.setFocusable(false);
    
        customAdapter.notifyDataSetChanged();
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Log.d("listview click", "onItemClick: ");
               /* FragmentTransaction fr = getFragmentManager().beginTransaction().replace(R.id.fragment_container, new productdisplay());
    
                fr.putExtra("Position", position);
                fr.addToBackStack("tag");
                fr.commit();*/
                Intent intent = new Intent(getActivity(), productdisplay.class);
                intent.putExtra("Position", position);
                startActivity(intent);
            }
        });
    
    
        //image slider
        int images[] = {R.drawable.slide1, R.drawable.slide2, R.drawable.slide3};
        v_flipper = view.findViewById(R.id.v_flipper);
        for (int image : images) {
            flipperImages(image);
    
        }
    }
    
    private void flipperImages(int image) {
        ImageView imageView = new ImageView(getActivity());
        imageView.setBackgroundResource(image);
    
        v_flipper.addView(imageView);
        v_flipper.setFlipInterval(4000);
        v_flipper.setAutoStart(true);
    
        v_flipper.setInAnimation(getActivity(), android.R.anim.slide_in_left);
        v_flipper.setOutAnimation(getActivity(), android.R.anim.slide_out_right);
    }
    }

    Примечание: я использовал Fragmentsздесь.


1

Хорошо, вот мой ответ. Метод, который фиксирует высоту ListView, достаточно закрыт, но не идеален. В случае, если большинство предметов имеют одинаковую высоту, это работает хорошо. Но если это не так, то есть большая проблема. Я пытался много раз, и когда я поместил в список значения listItem.getMeasureHeight и listItem.getMeasuerWidth, я увидел, что значения ширины сильно меняются, чего здесь не ожидается, поскольку все элементы в одном и том же ListView должны имеют одинаковую ширину. И там ошибка:

Некоторые использовали меру (0, 0), которая фактически делала представление свободным как в направлении, так и в ширину. Некоторые пытались получить ширину listView, но потом возвращали 0, бессмысленно.

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

На этот раз я использую getViewTreeObserver в ListView, который я хочу зафиксировать высоту, а затем addOnGlobalLayoutListener. Внутри этого метода я объявляю новый OnGlobalLayoutListener, в котором на этот раз getWidth возвращает фактическую ширину ListView.

private void getLayoutWidth(final ListView lv, final int pad){
        //final ArrayList<Integer> width = new ArrayList<Integer>();

        ViewTreeObserver vto = lv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                lv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                //width.add(layout.getMeasuredWidth());
                int width = lv.getMeasuredWidth();
                ListUtils.setDynamicHeight(lv, width, pad);
            }
        });
    }

public static class ListUtils {
        //private static final int UNBOUNDED = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        public static void setDynamicHeight(ListView mListView, int width, int pad) {
            ListAdapter mListAdapter = mListView.getAdapter();
            mListView.getParent();
            if (mListAdapter == null) {
                // when adapter is null
                return;
            }
            int height = 0;


            int desiredWidth = View.MeasureSpec.makeMeasureSpec(width - 2*pad, View.MeasureSpec.EXACTLY);
            for (int i = 0; i < mListAdapter.getCount(); i++) {
                View listItem = mListAdapter.getView(i, null, mListView);

                listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
                //listItem.measure(UNBOUNDED, UNBOUNDED);
                height += listItem.getMeasuredHeight() + 2*pad;
                Log.v("ViewHeight :", mListAdapter.getClass().toString() + " " + listItem.getMeasuredHeight() + "--" + listItem.getMeasuredWidth());
            }
            ViewGroup.LayoutParams params = mListView.getLayoutParams();
            params.height = height + (mListView.getDividerHeight() * (mListAdapter.getCount() - 1));
            mListView.setLayoutParams(params);
            mListView.requestLayout();
        }
    }

Панель значений - это отступ, который я установил в макете ListView.


1

Если по какой-то причине вы не хотите использовать addHeaderViewи addFooterView, например, когда у вас есть несколько списков, хорошей идеей будет повторное использование ListAdapterдля заполнения простого, LinearLayoutчтобы не было функции прокрутки.

Если у вас уже есть целый фрагмент, полученный из, ListFragmentи вы хотите LinearLayoutвместо этого преобразовать его в аналогичный фрагмент с простым без прокрутки (например, чтобы поместить его в ScrollView), вы можете реализовать фрагмент адаптера следующим образом:

// converts listFragment to linearLayout (no scrolling)
// please call init() after fragment is inflated to set listFragment to convert
public class ListAsArrayFragment extends Fragment {
    public ListAsArrayFragment() {}

    private ListFragment mListFragment;
    private LinearLayout mRootView;


    // please call me!
    public void init(Activity activity, ListFragment listFragment){
        mListFragment = listFragment;
        mListFragment.onAttach(activity);
        mListFragment.getListAdapter().registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                refreshView();
            }
        });
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // create an empty vertical LinearLayout as the root view of this fragment
        mRootView = new LinearLayout(getActivity());
        mRootView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mRootView.setOrientation(LinearLayout.VERTICAL);
        return mRootView;
    }

    // reusing views for performance
    // todo: support for more than one view type
    ArrayList<View> mViewsToReuse = new ArrayList<>();
    ArrayList<View> mCurrentViews = new ArrayList<>();

    // re-add views to linearLayout
    void refreshView(){

        // remove old views from linearLayout and move them to mViewsToReuse
        mRootView.removeAllViews();
        mViewsToReuse.addAll(mCurrentViews);
        mCurrentViews.clear();

        // create new views
        for(int i=0; i<mListFragment.getListAdapter().getCount(); ++i){
            View viewToReuse = null;
            if(!mViewsToReuse.isEmpty()){
                viewToReuse = mViewsToReuse.get(mViewsToReuse.size()-1);
                mViewsToReuse.remove(mViewsToReuse.size()-1);
            }
            final View view = mListFragment.getListAdapter().getView(i, viewToReuse, mRootView);
            ViewGroup.LayoutParams oldParams = view.getLayoutParams();
            view.setLayoutParams(new LinearLayout.LayoutParams(oldParams.width, oldParams.height));
            final int finalI = i;

            // pass click events to listFragment
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListFragment.onListItemClick(null, view, finalI, finalI);
                }
            });
            mRootView.addView(view);
            mCurrentViews.add(view);
        }
    }

Вы можете также направить onCreate, onPause, onResumeи т.д. , для исходного фрагмента в зависимости от ваших потребностей или попробовать наследование вместо композиции (но переопределить некоторые методы настолько оригинален фрагмент фактически не прилагается к иерархии макета); но я хотел как можно больше выделить оригинальный фрагмент, потому что нам нужно только извлечь его ListAdapter. Если вы звоните исходный фрагмент setListAdapterв системе onAttach, достаточно вероятно.

Вот как использовать, ListAsArrayFragmentчтобы включить OriginalListFragmentбез прокрутки. В родительской деятельности onCreate:

ListAsArrayFragment fragment = (ListAsArrayFragment) getFragmentManager().findFragmentById(R.id.someFragmentId);
OriginalListFragment originalFragment = new OriginalListFragment();
fragment.init(this, originalFragment);

// now access originalFragment.getListAdapter() to modify list entries
// and remember to call notifyDatasetChanged()

1

нашел решение для scrollview -> viewpager -> FragmentPagerAdapter -> фрагмент -> динамический просмотр списка, но я не автор.

public class CustomPager extends ViewPager {

    private View mCurrentView;

    public CustomPager(Context context) {
        super(context);
    }

    public CustomPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mCurrentView == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        int height = 0;
        mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = mCurrentView.getMeasuredHeight();
        if (h > height) height = h;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void measureCurrentView(View currentView) {
        mCurrentView = currentView;
        this.post(new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        });
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}


public class MyPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    private int mCurrentPosition = -1;


    public MyPagerAdapter(FragmentManager fm) {
        super(fm);//or u can set them separately, but dont forget to call notifyDataSetChanged()
        this.fragments = new ArrayList<Fragment>();
        fragments.add(new FirstFragment());
        fragments.add(new SecondFragment());
        fragments.add(new ThirdFragment());
        fragments.add(new FourthFragment());
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        if (position != mCurrentPosition) {
            Fragment fragment = (Fragment) object;
            CustomPager pager = (CustomPager) container;
            if (fragment != null && fragment.getView() != null) {
                mCurrentPosition = position;
                pager.measureCurrentView(fragment.getView());
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

макет фрагментов может быть любым

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
    android:layout_height="match_parent" tools:context="nevet.me.wcviewpagersample.FirstFragment">


    <ListView
        android:id="@+id/lv1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#991199"/>
</LinearLayout>

тогда где-то просто

 lv = (ListView) view.findViewById(R.id.lv1);
        lv.setAdapter(arrayAdapter);
        setListViewHeightBasedOnChildren(lv);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        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,
                        LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }

1

с помощью этого ListView работал для меня

   package net.londatiga.android.widget;

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

   public class ExpandableHeightListView extends ListView
      {

    boolean expanded = false;

      public ExpandableHeightListView(Context context)
    {
    super(context);
}

public ExpandableHeightListView(Context context, AttributeSet attrs)
{
    super(context, attrs);
}

public ExpandableHeightListView(Context context, AttributeSet attrs,
        int defStyle)
{
    super(context, attrs, defStyle);
}

public boolean isExpanded()
{
    return expanded;
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    // HACK! TAKE THAT ANDROID!
    if (isExpanded())
    {
        // Calculate entire height by providing a very large height hint.
        // But do not use the highest 2 bits of this integer; those are
        // reserved for the MeasureSpec mode.
        int expandSpec = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);

        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
    else
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

public void setExpanded(boolean expanded)
{
    this.expanded = expanded;
}
}

и в XML

            <com.pakagename.ExpandableHeightListView
                android:id="@+id/expandableHeightListView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </com.Example.ExpandableHeightListView>

и в MainActivity

  ExpandableHeightListView listView = new ExpandableHeightListView(this);
    listview=(ExpandableHeightListView)findViewById(R.id.expandableHeightListView);
   listView.setAdapter(adapter); //set your adaper
   listView.setExpanded(true);

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


1

В xml:

<com.example.util.NestedListView
                    android:layout_marginTop="10dp"
                    android:id="@+id/listview"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:divider="@null"

                    android:layout_below="@+id/rl_delivery_type" >
                </com.example.util.NestedListView>

В Java:

public class NestedListView extends ListView implements View.OnTouchListener, AbsListView.OnScrollListener {

    private int listViewTouchAction;
    private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;

    public NestedListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        listViewTouchAction = -1;
        setOnScrollListener(this);
        setOnTouchListener(this);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                scrollBy(0, -1);
            }
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int newHeight = 0;
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) {
            ListAdapter listAdapter = getAdapter();
            if (listAdapter != null && !listAdapter.isEmpty()) {
                int listPosition = 0;
                for (listPosition = 0; listPosition < listAdapter.getCount()
                        && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
                    View listItem = listAdapter.getView(listPosition, null, this);
                    //now it will not throw a NPE if listItem is a ViewGroup instance
                    if (listItem instanceof ViewGroup) {
                        listItem.setLayoutParams(new LayoutParams(
                                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                    }
                    listItem.measure(widthMeasureSpec, heightMeasureSpec);
                    newHeight += listItem.getMeasuredHeight();
                }
                newHeight += getDividerHeight() * listPosition;
            }
            if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
                if (newHeight > heightSize) {
                    newHeight = heightSize;
                }
            }
        } else {
            newHeight = getMeasuredHeight();
        }
        setMeasuredDimension(getMeasuredWidth(), newHeight);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                scrollBy(0, 1);
            }
        }
        return false;
    }
}

0

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


0

Это сработало для меня ( ссылка 1 , ссылка 2 ):

  • Вы создаете пользовательский 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 = View.MeasureSpec.makeMeasureSpec(
                        Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
                super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
                ViewGroup.LayoutParams params = getLayoutParams();
                params.height = getMeasuredHeight();
            }
        }
  • В вашем файле макета

    <ScrollView 
     xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fillViewport="true">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
    
            <!-- com.Example Changed with your Package name -->
    
            <com.thedeveloperworldisyours.view.NonScrollListView
                android:id="@+id/lv_nonscroll_list"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </com.thedeveloperworldisyours.view.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>
    
    </ScrollView>
  • Создайте объект вашего customListview вместо ListView, например:

     NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);

0

Просто вызовите эту функцию после назначения адаптера для просмотра списка

public static void setListViewHeightBasedOnChildren
            (ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        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,
                    ViewGroup.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();

        params.height = totalHeight + (listView.getDividerHeight() *
                (listAdapter.getCount() - 1));

        listView.setLayoutParams(params);
        listView.requestLayout();
    } 

-1
listView.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
    scrollView.requestDisallowInterceptTouchEvent(true);

    int action = event.getActionMasked();

    switch (action) {
        case MotionEvent.ACTION_UP:
            scrollView.requestDisallowInterceptTouchEvent(false);
            break;
    }

    return false;
}
});

-1

лучший код

 <android.support.v4.widget.NestedScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/btmlyt"
    android:layout_below="@+id/deshead_tv">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
       android:orientation="vertical"
       >

    <TextView
        android:id="@+id/des_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/btmlyt"
        android:background="@android:color/white"
        android:paddingLeft="3dp"
        android:paddingRight="3dp"
        android:scrollbars="vertical"
        android:paddingTop="3dp"
        android:text="description"
        android:textColor="@android:color/black"
        android:textSize="18sp" />
    </LinearLayout>

</android.support.v4.widget.NestedScrollView>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.