J'ai rencontré un problème lors de l'intégration d'un ListView dans un ScrollView, ou du moins c'est de là que vient le problème. L'élément ListView est assez simple:
<?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>
Cependant, lorsque j'intègre une liste de tels éléments dans une ScrollView, entre d'autres éléments, les lignes ne sont pas entièrement affichées, elles sont coupées (voir l'image ci-dessous) si le texte est renvoyé à la ligne. Le ListView est instancié comme suit dans le 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>
Si la hauteur de ListView est définie sur "wrap_content", seul le premier élément est affiché. C'est pourquoi j'utilise une méthode pour calculer la hauteur des lignes de la liste:
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;
}
}
Malheureusement, dans le cas où le texte à l'intérieur de TextView est enveloppé, même sur plusieurs lignes, la hauteur de l'élément row renvoyée par la méthode getMeasuredHeight () est constante. De même, la méthode getLineCount () appelée sur le TextView dans l'élément de ligne retourne 1 même si le texte est renvoyé à la ligne.
Par contre, si cette ListView est intégrée à un LinearLayout, tout fonctionne correctement et la liste complète est affichée sans découpage.
Avez-vous des suggestions quant à ce qui pourrait être faux ici? Je n'aime vraiment pas l'idée de mesurer manuellement la hauteur des éléments de la liste et cela ne fonctionne apparemment pas, mais pourquoi Android ne parvient-il pas à étirer correctement le ListView dans le ScrollView pour l'adapter à tout cela?
Liste coupée:
C'est unBADpratique pour encapsuler ListView
dans un ScrollView
car ListView lui-même contient des fonctionnalités de défilement. Vous devez implémenter une solution qui ne contient pas une telle hiérarchie de vues et j'espère que cela va faire la magie :)
Utilisez cette méthode créée par 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);
}
J'ai eu le même problème dans mon projet. Vous devez créer LinearLayout simple dans ScrollView . Après cela, vous devez créer new View with votre élément listview xml using LayoutInflater . Après la création, placez toutes les données dans new View et ajoutez-les à LinearLayout en tant que vue enfant :
linearLayot.addView(newView, position_you_need).
J'espère que cela vous aiderait!
Voici la ressource de la disposition principale avec 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>
Voici le code pour insérer des éléments:
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);
}
J'ai pris la recommandation de ne pas utiliser d'élément ListView à l'intérieur d'un ScrollView et j'ai décidé d'utiliser une méthode de force brute légère pour obtenir ce dont j'avais besoin. Puisqu'il y a un nombre constant d'au plus cinq lignes de liste à afficher, j'ai supprimé l'instanciation ListView du fichier xml et l'ai remplacée par cinq instances de lignes:
<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" />
Dans la classe d'activité, je déclare cinq espaces réservés pour ces vues:
private RelativeLayout mChatMessages[] = new RelativeLayout[COMMENTS_NUMBER];
et les initialiser avec:
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);
Ensuite, chaque fois qu'un nouveau message est reçu, j'utilise ChatAdapter (le même que j'ai utilisé pour ListView auparavant) et appelle sa méthode 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);
}
}
}
Je ne gonfle plus les vues pariculat car la seule chose qui change est le contenu de chaque ligne, pas la mise en page. Cela signifie qu'il n'y a pas de pénalité de performance ici.
Il s’agit d’une implémentation manuelle d’un ListView avec un nombre maximum d’éléments. Cette fois, cependant, ScrollView est capable de les ajuster parfaitement et rien n’est écrêté.
Pour un nombre dynamique de lignes, l'approche suggérée par Layko pourrait être utilisée, les vues étant instanciées par programme et ajoutées à LinearLayout à l'intérieur de ScrollView.
Ça marche pour moi
<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>
essayez-le ...__ après avoir créé toutes les vues, ajoutez la ligne ci-dessous pour définir l'emplacement de ScrollView (x, y)
ScrollView scrollView = (ScrollView)findViewById(R.id.scrollView);
scrollView.smoothScrollTo(0,0);// top location zero index
Je peux voir que ListView se trouve dans un ViewPager; Une autre solution simple pour résoudre ce problème consiste à ajouter app:layout_behavior="@string/appbar_scrolling_view_behavior"
au ViewPager de votre layout xml, comme indiqué ci-dessous.
<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"/>
Pour éviter le même comportement en bas de la liste, vous pouvez également ajouter Android:layout_marginBottom="?attr/actionBarSize"
au ViewPager comme suit
<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"/>
Cela arrive tard, mais j'espère que cela aidera toute autre personne.
J'avais un problème similaire. j'ai un
RelativeLayout
listView
includeLayout
où j'inclus quelques bas nav sous la listeVoir avec cette
<include
Android:id="@+id/includeLayout"
layout="@layout/bottom_nav_bar"
et mon listView a été coupé - ne prenant pas toute la hauteur disponible entre l'en-tête et la navigation du bas. J'ai essayé divers paramètres xml suggérés dans ce sujet et d'autres, mais ce qui a bien fonctionné pour moi a été d'ajouter
Android:layout_alignBottom="@+id/includeLayout"
à ma liste Cela semblait faire descendre la liste dans le haut de la liste de navigation, de sorte que la liste utilise maintenant toute la hauteur disponible (et défile au besoin).