Подтвердить что ты не робот

Строки списка Android ListView в ScrollView не отображаются полностью - обрезаны

Я столкнулся с проблемой при встраивании ListView внутри ScrollView или, по крайней мере, в том месте, где я предполагаю, что проблема возникает. Элемент ListView довольно простой:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/general_background_list_middle" 
    android:paddingTop="4dp"
    android:paddingBottom="4dp"
    android:paddingRight="0dp"
    android:paddingLeft="0dp">

    <ImageView
        android:id="@+id/chat_friends_avatar"       
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_marginLeft="7dp"
        android:layout_marginRight="8dp"
        android:paddingRight="0dp" 
        android:paddingLeft="0dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/friends_icon_avatar_default"/>

    <TextView
        android:id="@+id/chat_message_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/chat_friends_avatar"
        android:layout_alignParentTop="true"
        android:layout_marginRight="35dp"
        android:maxLines="10"
        android:textSize="12dp"/>

    <TextView
        android:id="@+id/chat_friend_name"
        android:layout_width="140dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="3dp"
        style="@style/SubText"
        android:layout_toRightOf="@id/chat_friends_avatar"      
        android:layout_below="@id/chat_message_text" />

    <TextView
        android:id="@+id/chat_message_time"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="8dp"
        android:layout_marginTop="3dp"
        style="@style/SubText"
        android:layout_alignParentRight="true"
        android:layout_below="@id/chat_message_text" />

</RelativeLayout>   

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

<ListView
android:id="@+id/info_chat_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:cacheColorHint="@color/frame_background_color"
android:clickable="false"
android:divider="@null"
android:footerDividersEnabled="false"
android:focusable="false" >
</ListView> 

Если высота ListView установлена ​​на "wrap_content", отображается только первый элемент. Вот почему я использую метод для вычисления высоты строк списка:

private int getCommentsListHeight() {
        if (mChatAdapter != null && mChatAdapter.getCount() != 0) {
            if (mChatList != null) {// && mCommentsListItemHeight == 0) {
                mCommentsListItemHeight = 0;
                for (int i = 0; i < mChatAdapter.getCount(); i++) {
                    // Get view item height
                    View viewItem = mChatAdapter
                            .getView(i, new View(OnAirActivity.this), mChatList);
                    viewItem.measure(0, 0);
                    Logger.d(LOGTAG, "View " + i + " measured height = " + viewItem.getMeasuredHeight());
                    mCommentsListItemHeight += viewItem.getMeasuredHeight();
                }
            }
            //return mChatAdapter.getCount() * mCommentsListItemHeight;
            return mCommentsListItemHeight;
        } else {
            return 0;
        }
    }

К сожалению, в случае, если текст внутри TextView обернут, даже в нескольких строках, высота элемента строки, возвращаемого методом getMeasuredHeight(), является постоянной. Также getLineCount(), вызываемый в TextView внутри элемента строки, возвращает 1, даже если текст завернут.

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

Есть ли у вас какие-либо предложения относительно того, что может быть неправильным здесь? Мне действительно не нравится идея ручного измерения высоты элементов списка, и это, по-видимому, не работает, но почему не может андроид красиво растянуть ListView внутри ScrollView, чтобы вместить все это там?

Вырезанный список: see image

4b9b3361

Ответ 1

Это BAD практика для инкапсуляции ListView в ScrollView, потому что ListView сам содержит возможности прокрутки. Вы должны реализовать решение, которое не содержит такой иерархии представлений, и я надеюсь, что он сделает магию:)

Ответ 2

Используйте этот метод, созданный https://stackoverflow.com/users/205192/dougw

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

Ответ 3

У меня была такая же проблема в моем проекте. Вам нужно создать простой LinearLayout внутри ScrollView. После этого вам нужно создать новый View с помощью вашего элемента списка xml, используя LayoutInflater. После создания поместите все данные в новый View и добавьте LinearLayout в виде дочернего представления:

linearLayot.addView(newView, position_you_need).

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

Ответ 4

Здесь ресурс основного макета с ScrollView:

<ScrollView android:layout_height="fill_parent" android:layout_width="fill_parent">
<LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/parentLayout"/>
</ScrollView>

Здесь код для вставки элементов:

parentLayout.removeAllViews();
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = comments.size() - 1; i >= 0; i--) {
CommentInfo comment = comments.get(i);
View view = inflater.inflate(your_resource_id, null, false);

TextView commentsContent =(TextView)view.findViewById(R.id.commentContent);
if (commentsContent != null) {
    String data = String.format("%s (by %s, %s)",  comment.getCommentText(), comment.getUserName(),
        commentsContent.setTextSize(st.getTextSize());
    commentsContent.setText(data);

}

parentLayout.addView(view, 0);

}       

Ответ 5

Я принял рекомендацию не использовать элемент ListView внутри ScrollView в сердце и решил использовать метод немного грубой силы для достижения того, что мне нужно. Поскольку существует постоянное число до пяти строк списка, которые необходимо отобразить, я удалил экземпляр ListView из xml файла и заменил его на пять экземпляров строк:

<include android:id="@+id/info_comment_1" layout="@layout/chat_single_message" />
<include android:id="@+id/info_comment_2" layout="@layout/chat_single_message" />
<include android:id="@+id/info_comment_3" layout="@layout/chat_single_message" />
<include android:id="@+id/info_comment_4" layout="@layout/chat_single_message" />
<include android:id="@+id/info_comment_5" layout="@layout/chat_single_message" />

В классе Activity я объявляю пять заполнителей для этих просмотров:

private RelativeLayout mChatMessages[] = new RelativeLayout[COMMENTS_NUMBER];

и инициализируйте их:

mChatMessages[0] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_1);
mChatMessages[1] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_2);
mChatMessages[2] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_3);
mChatMessages[3] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_4);
mChatMessages[4] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_5);

Затем, всякий раз, когда получено новое сообщение, я использую ChatAdapter (тот же, что использовался ранее для ListView), и вызываю его метод getView():

protected void updateChatMessages() {
  int msgCount = mChatAdapter.getCount();
  for (int i = 0; i < COMMENTS_NUMBER; i++) {
    if (msgCount <= i) {
      mChatMessages[i].setVisibility(View.GONE);
    } else {
      mChatMessages[i] = (RelativeLayout) mChatAdapter.getView(i, mChatMessages[i], null); 
      mChatMessages[i].setVisibility(View.VISIBLE);
    }   
  }
}

Я не раздуваю взгляды pariculat еще раз, поскольку единственное, что меняется, - это содержимое каждой строки, а не макета. Это означает, что здесь нет штрафа за производительность.

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

Для динамического числа строк подход, предложенный Layko, может быть использован с запрограммированными представлениями и добавлен в LinearLayout внутри ScrollView.

Ответ 6

Я вижу, что ListView находится внутри ViewPager; еще один простой подход к решению этой проблемы - добавить app:layout_behavior="@string/appbar_scrolling_view_behavior" в ViewPager в вашем макете xml, как показано ниже.

<android.support.v4.view.ViewPager
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

Чтобы предотвратить такое же поведение в нижней части списка, вы также можете добавить android:layout_marginBottom="?attr/actionBarSize" в ViewPager так

<android.support.v4.view.ViewPager
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:layout_marginBottom="?attr/actionBarSize"/>

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

Ответ 7

попробуйте. после создания всех представлений добавить строку ниже для местоположения ScrollView на экране (x, y)

  ScrollView scrollView = (ScrollView)findViewById(R.id.scrollView);

  scrollView.smoothScrollTo(0,0);// top location zero index

Ответ 8

У меня была аналогичная проблема. У меня есть

RelativeLayout
  listView
  includeLayout  

где я включаю некоторый нижний nav под listView с этим

<include
    android:id="@+id/includeLayout"
    layout="@layout/bottom_nav_bar"

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

android:layout_alignBottom="@+id/includeLayout"

в мой списокView. Похоже, что listView попал в верхнюю часть нижней навигационной панели, так что listView теперь использует полную доступную высоту (и она прокручивается по мере необходимости).

Ответ 9

Это работает для меня

<RelativeLayout                                          xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:padding="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="17sp"
        android:text="@string/text_list_devices" />

    <ListView
        android:id="@+id/lv_paired"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:cacheColorHint="#00000000"
        android:layout_above="@+id/signup_t"
        android:layout_below="@id/tv_status"
        />

    <Button

        android:id="@+id/signup_t"
        style="?android:textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textColor="@android:color/white"
        android:layout_alignParentBottom="true"
        android:text="Print All Records"
        android:typeface="sans"
        android:layout_marginLeft="45dp"
        android:layout_marginRight="45dp"
        android:textSize="24sp"
        android:background="@drawable/selector_for_button"
        android:textStyle="bold" />
</RelativeLayout>