J'ai cherché des solutions à ce problème, et la seule réponse que je puisse trouver semble être " ne mettez pas de ListView dans un ScrollView ". Je n'ai pas encore vu de véritable explication pour pourquoi cependant. La seule raison pour laquelle je peux sembler trouver est que Google ne pense pas que vous devriez vouloir faire cela. Eh bien oui, alors je l’ai fait.
La question est donc, comment pouvez-vous placer un ListView dans un ScrollView sans qu'il s'effondre à sa hauteur minimale?
Utiliser un ListView
pour ne pas faire défiler est extrêmement coûteux et va à l’encontre de l’objet de ListView
. Vous devriez PAS faire ceci. Utilisez simplement un LinearLayout
à la place.
Voici ma solution. Je suis assez nouveau sur la plate-forme Android, et je suis sûr que c'est un peu hackish, en particulier pour ce qui est d'appeler directement .measure et de définir directement la propriété LayoutParams.height
, mais travaux.
Tout ce que vous avez à faire est d'appeler Utility.setListViewHeightBasedOnChildren(yourListView)
et il sera redimensionné pour s'adapter à la hauteur de ses éléments.
public class Utility {
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
}
Cela fonctionnera certainement ............
Vous devez simplement remplacer votre <ScrollView ></ScrollView>
dans le fichier XML de présentation par ce Custom ScrollView
comme <com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
package com.tmd.utils;
import Android.content.Context;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.MotionEvent;
import Android.widget.ScrollView;
public class VerticalScrollview extends ScrollView{
public VerticalScrollview(Context context) {
super(context);
}
public VerticalScrollview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
Log.i("VerticalScrollview", "onInterceptTouchEvent: DOWN super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
Log.i("VerticalScrollview", "onInterceptTouchEvent: CANCEL super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
Log.i("VerticalScrollview", "onInterceptTouchEvent: UP super false" );
return false;
default: Log.i("VerticalScrollview", "onInterceptTouchEvent: " + action ); break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() );
return true;
}
}
Au lieu de mettre ListView
dans un ScrollView
, nous pouvons utiliser ListView
comme ScrollView
. Les choses qui doivent être dans ListView
peuvent être placées à l'intérieur de ListView
. D'autres dispositions en haut et en bas de ListView
peuvent être ajoutées en ajoutant des dispositions à l'en-tête et au pied de page de ListView
. Ainsi, l'ensemble ListView
vous donnera une expérience de défilement.
Il y a beaucoup de situations où il est très logique d'avoir ListView dans un ScrollView.
Voici un code basé sur la suggestion de DougW ... fonctionne dans un fragment, prend moins de mémoire.
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
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, LayoutParams.WRAP_CONTENT));
}
view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += view.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
appelez setListViewHeightBasedOnChildren (listview) sur chaque listview incorporée.
ListView est en fait déjà capable de se mesurer suffisamment grand pour afficher tous les éléments, mais ne le fait pas lorsque vous spécifiez simplement wrap_content (MeasureSpec.UNSPECIFIED). Cela se fera si on lui donne une hauteur avec MeasureSpec.AT_MOST. Avec cette connaissance, vous pouvez créer une sous-classe très simple pour résoudre ce problème qui fonctionne beaucoup mieux que n’importe laquelle des solutions présentées ci-dessus. Vous devriez toujours utiliser wrap_content avec cette sous-classe.
public class ListViewForEmbeddingInScrollView extends ListView {
public ListViewForEmbeddingInScrollView(Context context) {
super(context);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
}
}
Manipuler la heightMeasureSpec pour qu'il soit AT_MOST avec une très grande taille (Integer.MAX_VALUE >> 4) force le ViewView à mesurer tous ses enfants jusqu'à la hauteur donnée (très grande) et à définir sa hauteur en conséquence.
Cela fonctionne mieux que les autres solutions pour plusieurs raisons:
Par contre, vous pourriez faire valoir que cela revient à s’appuyer sur un comportement non documenté dans le SDK, qui pourrait changer. D'autre part, vous pourriez soutenir que c'est ainsi que wrap_content devrait réellement fonctionner avec ListView et que le comportement actuel de wrap_content est simplement rompu.
Si vous craignez que le comportement ne change à l'avenir, vous devez simplement copier la fonction onMeasure et les fonctions connexes dans ListView.Java et dans votre propre sous-classe, puis indiquez également le chemin AT_MOST via onMeasure pour UNSPECIFIED.
En passant, j'estime qu'il s'agit d'une approche parfaitement valable lorsque vous travaillez avec un petit nombre d'éléments de liste. Cela peut paraître inefficace par rapport à LinearLayout, mais lorsque le nombre d'éléments est faible, l'utilisation de LinearLayout est une optimisation inutile, donc une complexité inutile.
Il y a un paramètre intégré pour cela. Sur le ScrollView:
Android:fillViewport="true"
En Java,
mScrollView.setFillViewport(true);
Romain Guy l'explique en détail ici: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
Vous créez un ListView personnalisé qui n'est pas Scrollable
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();
}
}
Dans votre fichier de ressources de mise en page
<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>
Dans le fichier Java
Créez un objet de votre customListview au lieu de ListView comme suit: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);
Nous ne pouvons pas utiliser deux défilement simultanés. Nous aurons une longueur totale de ListView et développons listview avec la hauteur totale. Ensuite, nous pouvons ajouter ListView dans ScrollView directement ou utiliser LinearLayout, car ScrollView a directement un enfant. copiez la méthode setListViewHeightBasedOnChildren (lv) dans votre code et développez listview pour pouvoir ensuite utiliser listview dans scrollview.\layout xml file
<?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="match_parent"
Android:orientation="vertical" >
<ScrollView
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:background="#1D1D1D"
Android:orientation="vertical"
Android:scrollbars="none" >
<LinearLayout
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:background="#1D1D1D"
Android:orientation="vertical" >
<TextView
Android:layout_width="fill_parent"
Android:layout_height="40dip"
Android:background="#333"
Android:gravity="center_vertical"
Android:paddingLeft="8dip"
Android:text="First ListView"
Android:textColor="#C7C7C7"
Android:textSize="20sp" />
<ListView
Android:id="@+id/first_listview"
Android:layout_width="260dp"
Android:layout_height="wrap_content"
Android:divider="#00000000"
Android:listSelector="#ff0000"
Android:scrollbars="none" />
<TextView
Android:layout_width="fill_parent"
Android:layout_height="40dip"
Android:background="#333"
Android:gravity="center_vertical"
Android:paddingLeft="8dip"
Android:text="Second ListView"
Android:textColor="#C7C7C7"
Android:textSize="20sp" />
<ListView
Android:id="@+id/secondList"
Android:layout_width="260dp"
Android:layout_height="wrap_content"
Android:divider="#00000000"
Android:listSelector="#ffcc00"
Android:scrollbars="none" />
</LinearLayout>
</ScrollView>
</LinearLayout>
méthode onCreate dans la classe d'activité:
import Java.util.ArrayList;
import Android.app.Activity;
import Android.os.Bundle;
import Android.view.Menu;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.ArrayAdapter;
import Android.widget.ListAdapter;
import Android.widget.ListView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_inside_scrollview);
ListView list_first=(ListView) findViewById(R.id.first_listview);
ListView list_second=(ListView) findViewById(R.id.secondList);
ArrayList<String> list=new ArrayList<String>();
for(int x=0;x<30;x++)
{
list.add("Item "+x);
}
ArrayAdapter<String> adapter=new ArrayAdapter<String>(getApplicationContext(),
Android.R.layout.simple_list_item_1,list);
list_first.setAdapter(adapter);
setListViewHeightBasedOnChildren(list_first);
list_second.setAdapter(adapter);
setListViewHeightBasedOnChildren(list_second);
}
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);
}
Ceci est une combinaison des réponses de DougW, Good Guy Greg et Paul. J'ai constaté que tout cela était nécessaire lorsque vous tentiez d'utiliser ceci avec un adaptateur Listview personnalisé et des éléments de liste non standard, sinon Listview plantait l'application (ainsi que la réponse de Nex):
public void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup)
listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
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 converti Utility
de DougW en C # (utilisé dans Xamarin). Ce qui suit fonctionne bien pour les éléments à hauteur fixe dans la liste, et le sera dans la plupart des cas, ou du moins, pour un bon début, si seulement certains des éléments sont un peu plus gros que l'élément standard.
// You will need to put this Utility class into a code file including various
// libraries, I found that I needed at least System, Linq, Android.Views and
// Android.Widget.
using System;
using System.Linq;
using Android.Views;
using Android.Widget;
namespace UtilityNamespace // whatever you like, obviously!
{
public class Utility
{
public static void setListViewHeightBasedOnChildren (ListView listView)
{
if (listView.Adapter == null) {
// pre-condition
return;
}
int totalHeight = listView.PaddingTop + listView.PaddingBottom;
for (int i = 0; i < listView.Count; i++) {
View listItem = listView.Adapter.GetView (i, null, listView);
if (listItem.GetType () == typeof(ViewGroup)) {
listItem.LayoutParameters = new LinearLayout.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
}
listItem.Measure (0, 0);
totalHeight += listItem.MeasuredHeight;
}
listView.LayoutParameters.Height = totalHeight + (listView.DividerHeight * (listView.Count - 1));
}
}
}
Merci @DougW, cela m'a permis de sortir d'une situation difficile lorsque j'ai dû travailler avec OtherPeople's Code. :-)
Vous ne devriez pas placer un ListView dans un ScrollView, car un ListView est déjà est un ScrollView. Donc, ce serait comme mettre un ScrollView dans un ScrollView.
Qu'est-ce que vous essayez d'accomplir?
Il y a deux problèmes lorsque vous utilisez un ListView dans un ScrollView.
1- ListView doit être complètement étendu à la hauteur de ses enfants. ce ListView résoudre ceci:
public class ListViewExpanded extends ListView
{
public ListViewExpanded(Context context, AttributeSet attrs)
{
super(context, attrs);
setDividerHeight(0);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST));
}
}
La hauteur du séparateur doit être 0, utilisez plutôt un rembourrage dans les lignes.
2- Le ListView consomme des événements tactiles, il est donc impossible de faire défiler ScrollView comme d'habitude. Cette ScrollView résout ce problème:
public class ScrollViewInterceptor extends ScrollView
{
float startY;
public ScrollViewInterceptor(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e)
{
onTouchEvent(e);
if (e.getAction() == MotionEvent.ACTION_DOWN) startY = e.getY();
return (e.getAction() == MotionEvent.ACTION_MOVE) && (Math.abs(startY - e.getY()) > 50);
}
}
C'est le meilleur moyen que j'ai trouvé de faire le tour!
Ceci est la seule chose qui a fonctionné pour moi:
sur Lollipop, vous pouvez utiliser
yourtListView.setNestedScrollingEnabled(true);
Cela active ou désactive le défilement imbriqué pour cette vue si vous avez besoin d'une compatibilité ascendante avec les versions antérieures du système d'exploitation, vous devrez utiliser RecyclerView.
hé j'ai eu un problème similaire. Je voulais afficher une liste qui ne défilait pas et j'ai constaté que la manipulation des paramètres fonctionnait mais était inefficace et se comportait différemment sur différents périphériques. Par conséquent, il s'agit d'un élément de mon code de programme qui le fait très efficacement. .
db = new dbhelper(this);
cursor = db.dbCursor();
int count = cursor.getCount();
if (count > 0)
{
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layoutId);
startManagingCursor(YOUR_CURSOR);
YOUR_ADAPTER(**or SimpleCursorAdapter **) adapter = new YOUR_ADAPTER(this,
R.layout.itemLayout, cursor, arrayOrWhatever, R.id.textViewId,
this.getApplication());
int i;
for (i = 0; i < count; i++){
View listItem = adapter.getView(i,null,null);
linearLayout.addView(listItem);
}
}
Remarque: si vous utilisez ceci, notifyDataSetChanged();
ne fonctionnera pas comme prévu, car les vues ne seront pas redessinées. Faites cela si vous avez besoin d'un travail autour
adapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
removeAndRedrawViews();
}
});
Une solution que j'utilise est d'ajouter tout le contenu de ScrollView (ce qui devrait être au-dessus et sous le listView) comme headerView et footerView dans ListView.
Donc, cela fonctionne comme si la convertview était restituée telle quelle.
Toutes ces réponses sont fausses !!! Si vous essayez de placer une liste dans une vue défilante, vous devriez repenser votre conception. Vous essayez de placer une ScrollView dans une ScrollView. Interférer avec la liste nuira aux performances de la liste. Il a été conçu pour être comme ça par Android.
Si vous souhaitez vraiment que la liste se trouve dans le même défilement que les autres éléments, il vous suffit d'ajouter les autres éléments en haut de la liste à l'aide d'une simple instruction switch dans votre adaptateur:
class MyAdapter extends ArrayAdapter{
public MyAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewItem viewType = getItem(position);
switch(viewType.type){
case TEXTVIEW:
convertView = layouteInflater.inflate(R.layout.textView1, parent, false);
break;
case LISTITEM:
convertView = layouteInflater.inflate(R.layout.listItem, parent, false);
break; }
return convertView;
}
}
L'adaptateur de liste peut tout gérer puisqu'il ne rend que ce qui est visible.
Avant ce n'était pas possible. Mais avec la sortie de nouvelles bibliothèques Appcompat et de bibliothèques Design, cet objectif peut être atteint.
Vous devez simplement utiliser NestedScrollView https://developer.Android.com/reference/Android/support/v4/widget/NestedScrollView.html
Je ne suis pas au courant que cela fonctionnera avec Listview ou non, mais fonctionne avec RecyclerView.
Extrait de code:
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.v7.widget.RecyclerView
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
</Android.support.v4.widget.NestedScrollView>
Voici une petite modification sur @ djunodréponse que je dois le faire fonctionner parfaitement:
public static void setListViewHeightBasedOnChildren(ListView listView)
{
ListAdapter listAdapter = listView.getAdapter();
if(listAdapter == null) return;
if(listAdapter.getCount() <= 1) return;
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
int totalHeight = 0;
View view = null;
for(int i = 0; i < listAdapter.getCount(); i++)
{
view = listAdapter.getView(i, view, listView);
view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += view.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
Bien que les méthodes suggérées setListViewHeightBasedOnChildren () fonctionnent dans la plupart des cas, dans certains cas, spécialement avec beaucoup d'éléments, j'ai remarqué que les derniers éléments ne sont pas affichés. J'ai donc décidé d'imiter une version simple du comportement ListView afin de réutiliser un code de l'adaptateur, voici l'alternative ListView. :
import Android.content.Context;
import Android.database.DataSetObserver;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.View;
import Android.widget.LinearLayout;
import Android.widget.ListAdapter;
public class StretchedListView extends LinearLayout {
private final DataSetObserver dataSetObserver;
private ListAdapter adapter;
private OnItemClickListener onItemClickListener;
public StretchedListView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);
this.dataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
syncDataFromAdapter();
super.onChanged();
}
@Override
public void onInvalidated() {
syncDataFromAdapter();
super.onInvalidated();
}
};
}
public void setAdapter(ListAdapter adapter) {
ensureDataSetObserverIsUnregistered();
this.adapter = adapter;
if (this.adapter != null) {
this.adapter.registerDataSetObserver(dataSetObserver);
}
syncDataFromAdapter();
}
protected void ensureDataSetObserverIsUnregistered() {
if (this.adapter != null) {
this.adapter.unregisterDataSetObserver(dataSetObserver);
}
}
public Object getItemAtPosition(int position) {
return adapter != null ? adapter.getItem(position) : null;
}
public void setSelection(int i) {
getChildAt(i).setSelected(true);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public ListAdapter getAdapter() {
return adapter;
}
public int getCount() {
return adapter != null ? adapter.getCount() : 0;
}
private void syncDataFromAdapter() {
removeAllViews();
if (adapter != null) {
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
View view = adapter.getView(i, null, this);
boolean enabled = adapter.isEnabled(i);
if (enabled) {
final int position = i;
final long id = adapter.getItemId(position);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(null, v, position, id);
}
}
});
}
addView(view);
}
}
}
}
merci à code de Vinay voici mon code pour quand vous ne pouvez pas avoir de liste dans un scrollview mais que vous avez besoin de quelque chose comme ça
LayoutInflater li = LayoutInflater.from(this);
RelativeLayout parent = (RelativeLayout) this.findViewById(R.id.relativeLayoutCliente);
int recent = 0;
for(Contatto contatto : contatti)
{
View inflated_layout = li.inflate(R.layout.header_listview_contatti, layout, false);
inflated_layout.setId(contatto.getId());
((TextView)inflated_layout.findViewById(R.id.textViewDescrizione)).setText(contatto.getDescrizione());
((TextView)inflated_layout.findViewById(R.id.textViewIndirizzo)).setText(contatto.getIndirizzo());
((TextView)inflated_layout.findViewById(R.id.textViewTelefono)).setText(contatto.getTelefono());
((TextView)inflated_layout.findViewById(R.id.textViewMobile)).setText(contatto.getMobile());
((TextView)inflated_layout.findViewById(R.id.textViewFax)).setText(contatto.getFax());
((TextView)inflated_layout.findViewById(R.id.textViewEmail)).setText(contatto.getEmail());
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
if (recent == 0)
{
relativeParams.addRule(RelativeLayout.BELOW, R.id.headerListViewContatti);
}
else
{
relativeParams.addRule(RelativeLayout.BELOW, recent);
}
recent = inflated_layout.getId();
inflated_layout.setLayoutParams(relativeParams);
//inflated_layout.setLayoutParams( new RelativeLayout.LayoutParams(source));
parent.addView(inflated_layout);
}
le relativeLayout reste dans une ScrollView pour que tout devienne défilable :)
essayez ceci, cela fonctionne pour moi, j'ai oublié où je l'ai trouvé, quelque part dans le débordement de pile, je ne suis pas ici pour expliquer pourquoi cela ne fonctionne pas, mais c'est la réponse :).
final ListView AturIsiPulsaDataIsiPulsa = (ListView) findViewById(R.id.listAturIsiPulsaDataIsiPulsa);
AturIsiPulsaDataIsiPulsa.setOnTouchListener(new ListView.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.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
// Handle ListView touch events.
v.onTouchEvent(event);
return true;
}
});
AturIsiPulsaDataIsiPulsa.setClickable(true);
AturIsiPulsaDataIsiPulsa.setAdapter(AturIsiPulsaDataIsiPulsaAdapter);
EDIT!, J'ai enfin découvert où j'avais trouvé le code. ici ! : ListView dans ScrollView ne défile pas sur Android
Cette bibliothèque est la solution la plus simple et la plus rapide au problème.
Tout ce problème disparaîtrait simplement si LinearLayout avait une méthode setAdapter, car si vous demandiez à quelqu'un de l'utiliser, la solution de rechange serait triviale.
Si vous voulez réellement un ListView à défilement dans une autre vue défilante, cela ne vous aidera pas, mais sinon, cela vous donnera au moins une idée.
Vous devez créer un adaptateur personnalisé pour combiner tout le contenu que vous souhaitez faire défiler et définir l'adaptateur de ListView sur celui-ci.
Je n'ai pas d'exemple de code à portée de main, mais si vous voulez quelque chose comme.
<ListView/>
(other content)
<ListView/>
Ensuite, vous devez créer un adaptateur qui représente tout ce contenu. ListView/Adapters est suffisamment intelligent pour gérer différents types, mais vous devez écrire l'adaptateur vous-même.
L'API UI Android n'est pas aussi mature que tout le reste, elle n'a donc pas les mêmes subtilités que les autres plates-formes. De plus, lorsque vous faites quelque chose sur Android, vous devez être dans un état d'esprit Android (unix) où vous vous attendez à ce que vous fassiez quoi que ce soit pour lequel vous devrez probablement assembler les fonctionnalités de parties plus petites. et écrivez un tas de votre propre code pour le faire fonctionner.
Au lieu de placer la liste dans la liste, placez le reste du contenu entre la liste et l'ouverture de la fenêtre en tant que vue distincte et définissez cette vue comme en-tête de la liste. Donc, vous allez finir par ne voir que la liste en prenant en charge Scroll.
Lorsque nous plaçons ListView
à l'intérieur ScrollView
, deux problèmes se posent. L'un est ScrollView
mesure ses enfants en mode NON SPÉCIFIÉ, donc ListView
définit sa propre hauteur pour accueillir un seul élément (je ne sais pas pourquoi), un autre est ScrollView
intercepte l'événement tactile de manière à ListView
ne défile pas.
Mais nous pouvons placer ListView
à l'intérieur de ScrollView
avec une solution de contournement. Ce post , par moi, explique la solution de contournement. Par cette solution de contournement, nous pouvons également conserver la fonction de recyclage de ListView
.