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:
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 :)
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);
}
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!
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);
}
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.
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>
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
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.
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).