webentwicklung-frage-antwort-db.com.de

Android ListView-Zeilen in ScrollView werden nicht vollständig angezeigt - abgeschnitten

Beim Einbetten einer ListView in ein ScrollView bin ich auf ein Problem gestoßen, oder zumindest denke ich, dass das Problem damit zusammenhängt. Das ListView-Element ist ziemlich einfach:

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

Wenn ich jedoch eine Liste solcher Elemente in eine ScrollView einbettete, werden die Zeilen zwischen einigen anderen Elementen nicht vollständig angezeigt. Sie werden abgeschnitten (siehe Abbildung unten), wenn der Text umbrochen wird. Die ListView wird in der ScrollView wie folgt instanziiert:

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

Wenn die Höhe der ListView auf "wrap_content" gesetzt ist, wird nur das erste Element angezeigt. Deshalb verwende ich eine Methode, um die Höhe der Zeilen der Liste zu berechnen:

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

Unglücklicherweise ist die Höhe des Zeilenelements, das von der getMeasuredHeight () -Methode zurückgegeben wird, konstant, wenn der Text innerhalb der TextView-Datei auch über mehrere Zeilen verteilt wird. Auch das getLineCount (), das in der TextView innerhalb des Zeilenelements aufgerufen wird, gibt 1 zurück, selbst wenn der Text umbrochen wird.

Wenn diese ListView hingegen in ein LinearLayout eingebettet ist, funktioniert alles einwandfrei und die vollständige Liste wird ohne Beschneidung angezeigt.

Haben Sie Vorschläge, was hier falsch sein könnte? Ich mag die Idee, die Höhe der Listenelemente manuell zu messen, wirklich nicht und es funktioniert anscheinend nicht, aber warum kann Android die ListView-Ansicht in der ScrollView-Ansicht nicht so gut dehnen, dass sie alles darin einfügt?

Beschnittene Liste: see image

21
PawelPredki

Es ist eine SCHLECHTE - Praxis, ListView in einer ScrollView zu kapseln, da ListView selbst Bildlauffunktionen enthält. Sie sollten eine Lösung implementieren, die keine solche Hierarchie von Ansichten enthält, und ich hoffe, es wird die Magie sein :)

11
waqaslam

Verwenden Sie diese von https://stackoverflow.com/users/205192/dougw - erstellte Methode.

 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);
    }
40
Rajesh Wadhwa

Ich hatte das gleiche Problem in meinem Projekt. Sie müssen einfaches LinearLayout in ScrollView erstellen. Danach müssen Sie new View mit Ihren Listview-Eintrag xml erstellen, indem Sie LayoutInflater verwenden. Nach der Erstellung alle Daten in new View einfügen und als untergeordnete Ansicht zu LinearLayout hinzufügen :

linearLayot.addView(newView, position_you_need).

Hoffe es würde dir helfen!

2
Layko Andrey

Hier Ressource des Hauptlayouts mit 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>

Hier der Code zum Einfügen von Artikeln:  

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

}       
2
Layko Andrey

Ich nahm die Empfehlung an, kein ListView-Element in einer ScrollView zu verwenden, und entschied mich für eine etwas rohe Methode, um das zu erreichen, was ich brauche. Da es eine konstante Anzahl von bis zu fünf Listenzeilen gibt, die angezeigt werden müssen, habe ich die ListView-Instantiation aus der XML-Datei entfernt und durch fünf Instanzen von Zeilen ersetzt:

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

In der Activity-Klasse deklariere ich fünf Platzhalter für diese Ansichten:

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

und initialisieren sie mit:

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

Immer dann, wenn eine neue Nachricht empfangen wird, verwende ich den ChatAdapter (derselbe, den ich zuvor für die ListView verwendet habe) und rufe seine getView () -Methode auf:

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

Ich vergrößere die Ansichten der Parikulatore nie wieder, da sich nur der Inhalt jeder Zeile ändert, nicht das Layout. Dies bedeutet, dass es hier keine Leistungsstrafe gibt. 

Dies ist im Grunde eine manuelle Implementierung einer ListView mit einer begrenzten maximalen Anzahl von Elementen. Diesmal kann ScrollView sie jedoch gut anpassen, und es wird nichts abgeschnitten.

Für eine dynamische Anzahl von Zeilen könnte der von Layko vorgeschlagene Ansatz verwendet werden, wobei die Ansichten programmgesteuert instanziiert und dem LinearLayout in der ScrollView hinzugefügt werden.

1
PawelPredki

Das funktioniert für mich

<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>
0
Nouman Ch

probieren Sie es aus .. Nachdem Sie alle Ansichten erstellt haben, fügen Sie unter der Zeile für die ScrollView-Position auf dem Bildschirm die Option hinzu (x, y).

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

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

Ich kann sehen, dass sich die ListView in einem ViewPager befindet. Ein anderer einfacher Weg, um dieses Problem zu beheben, besteht darin, dem ViewPager in Ihrer Layout-XML-Datei app:layout_behavior="@string/appbar_scrolling_view_behavior" hinzuzufügen (siehe unten).

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

Um das gleiche Verhalten am Ende der Liste zu verhindern, können Sie dem ViewPager auch Android:layout_marginBottom="?attr/actionBarSize" hinzufügen

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

Das kommt spät, aber ich hoffe, es hilft jeder anderen Person.

0
Cletus Ajibade

Ich hatte ein ähnliches Problem. Ich habe ein 

RelativeLayout
  listView
  includeLayout  

hier füge ich einige untere Navis unter der ListView hinzu

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

und meine listView wurde abgeschnitten - nicht die volle Höhe zwischen Kopf- und unterem Navigationsbereich. Ich habe verschiedene in diesen und anderen Threads vorgeschlagene XML-Einstellungen ausprobiert, aber für mich funktionierte das Hinzufügen

Android:layout_alignBottom="@+id/includeLayout"

zu meiner listView. Dies schien die listView an den oberen Rand des unteren Navigationsbereichs zu ziehen, so dass die listView jetzt die gesamte verfügbare Höhe verwendet (und nach Bedarf scrollen kann).

0
John Leasia