web-dev-qa-db-fra.com

android: listview dans listview

j'essaye de placer une listview dans un listviewitem. la vue de liste intérieure ne doit pas être défilable mais prendre toute la taille dont elle a besoin pour afficher toutes ses lignes. existe-t-il une meilleure façon de procéder? table, grille, ...? le problème auquel je suis confronté en ce moment est que la vue de liste intérieure ne prend pas l'espace dont elle a besoin, elle est donc coupée à la fin du premier élément de liste. si j'essaie de faire défiler, juste la liste extérieure défile, ce qui est exactement ce que je veux.

how_it_should_look_like merci, ma solution finale est

LinearLayout layout = (LinearLayout) row.findViewById(R.id.LLBroadcasts);
layout.removeAllViews();

for (Item b : bs.getItems()) {

  View child = _inflater.inflate(R.layout.item_row, null);

  TextView tvTitle = (TextView) child.findViewById(R.id.TVItemTitle);
  tvTitle.setText(b.getTitle());

  TextView tvDesc = (TextView) child.findViewById(R.id.TVItemDescription);
  tvDesc.setText(b.getDescription());
  layout.addView(child);
}
34
kopi_b

À partir de la Android - Listview : ListView est un groupe de vues qui affiche une liste d'éléments déroulants

Vous ne voulez pas vraiment faire défiler cette vue de liste intérieure, vous voulez faire défiler la vue de liste extérieure. Cependant, je suppose que la liste interne peut varier en fonction de la quantité d'éléments qu'elle contient.

Au lieu de la vue de liste interne, vous pouvez utiliser un

Pour la disposition linéaire (un exemple de code):

// access your linear layout
LinearLayout layout = (LinearLayout)findViewById(R.id.layout);
// load the xml structure of your row
View child = getLayoutInflater().inflate(R.layout.row);
// now fill the row as you would do with listview
//e.g. (TextView) child.findViewById(...
...
// and than add it
layout.addView(child);

Vous devez enregistrer la disposition linéaire dans un support de vue (voir Modèle de support de vue ). Je pense que la removeAllViews() n'est nécessaire que lorsque la ligne actuelle a moins de lignes internes que celle réutilisée, donc je voudrais également enregistrer le nombre de lignes dans le support de vue.

Si le nombre maximal de lignes internes n'est pas trop élevé, vous pouvez également penser à les mettre en cache dans le support de vue pour éviter le gonflement et findByViewId (disons dans une liste de tableaux).

38
ChrLipp

J'ai le même problème dans mon application, mais je devais utiliser un ListView car c'était un élément partagé et je ne voulais pas répliquer des composants égaux. Donc .. Je viens de fixer la taille de ListView interne par programme pour afficher toutes les lignes et .. le tour est joué! Problème résolu:

ViewGroup.LayoutParams layoutParams = innerListView.getLayoutParams();
layoutParams.height = (int) context.getResources().getDimension(R.dimen.rowheight) * innerListView.getCount();
innerListView.setLayoutParams(layoutParams);
CustomAdapter adapter = new CustomAdapter(context, blabla..);
innerListView.setAdapter(adapter);

rowListView.invalidate();
6
Ian Holing

Peut-être que quelqu'un trouvera ma solution utile. Il est basé sur la réponse @ChrLipp et utilise LinearLayout.

public class NotScrollableListView extends LinearLayout {

private ListAdapter adapter;
private DataChangeObserver dataChangeObserver;
private Drawable divider;
private int dividerHeight;

private List<View> reusableViews = new ArrayList<>();

public NotScrollableListView(Context context) {
    super(context);
}

public NotScrollableListView(Context context, AttributeSet attrs) {
    super(context, attrs);

    setAttributes(attrs);
}

public NotScrollableListView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    setAttributes(attrs);
}

public ListAdapter getAdapter() {
    return adapter;
}

public void setAdapter(ListAdapter adapter) {
    if (this.adapter != null && dataChangeObserver != null) {
        this.adapter.unregisterDataSetObserver(dataChangeObserver);
    }

    this.adapter = adapter;
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    if (adapter != null) {
        dataChangeObserver = new DataChangeObserver();
        adapter.registerDataSetObserver(dataChangeObserver);

        fillContents();
    }
}

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();

    if (adapter != null) {
        adapter.unregisterDataSetObserver(dataChangeObserver);
        dataChangeObserver = null;
    }
}

private void fillContents() {

    // clearing contents
    this.removeAllViews();

    final int count = adapter.getCount();   // item count
    final int reusableCount = reusableViews.size(); // count of cached reusable views

    // calculating of divider properties
    ViewGroup.LayoutParams dividerLayoutParams = null;
    if (divider != null && dividerHeight > 0) {
        dividerLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dividerHeight);
    }

    // adding items
    for (int i = 0; i < count; i++) {
        // adding item
        View converView = null;
        if (i < reusableCount) {    // we have cached view
            converView = reusableViews.get(i);
        }
        View view = adapter.getView(i, converView, this);

        if (i >= reusableCount) {   // caching view
            reusableViews.add(view);
        }

        addView(view);

        // adding divider
        if (divider != null && dividerHeight > 0) {
            if (i < count - 1) {
                ImageView dividerView = new ImageView(getContext());
                dividerView.setImageDrawable(divider);
                dividerView.setLayoutParams(dividerLayoutParams);
                addView(dividerView);
            }
        }
    }
}

private void setAttributes(AttributeSet attributes) {
    int[] dividerAttrs = new int[]{Android.R.attr.divider, Android.R.attr.dividerHeight};

    TypedArray a = getContext().obtainStyledAttributes(attributes, dividerAttrs);
    try {
        divider = a.getDrawable(0);
        dividerHeight = a.getDimensionPixelSize(1, 0);
    } finally {
        a.recycle();
    }

    setOrientation(VERTICAL);
}

private class DataChangeObserver extends DataSetObserver {
    @Override
    public void onChanged() {
        super.onChanged();

        fillContents();
    }

    @Override
    public void onInvalidated() {
        super.onInvalidated();

        fillContents();
    }
}
    }

    <com.sample.ui.view.NotScrollableListView
    Android:id="@+id/internalList"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:divider="@color/list_divider_color"
    Android:dividerHeight="@dimen/list_divider_width"
    />
6
lobzik

J'ai essayé de créer cette structure exacte (un ListView à l'intérieur d'un ListView) et j'ai eu le même problème en ne montrant que le premier élément du ListView intérieur. Je l'ai corrigé en changeant le layout_height de la liste intérieure de match_parent à un ensemble dp.

Cela semblait fonctionner exactement comme je le voulais.

0
Fiberwire

@Essayez cette classe imbriquée

cela fonctionne pour le défilement listView à l'intérieur listView Ou 2 listviews dans le même activity

        <com.example.taskgrptaskslistview.NestedListView
            Android:id="@+id/listviewTasks"
            Android:layout_width="0dip"
            Android:layout_height="wrap_content"
            Android:layout_marginBottom="2dp"
            Android:layout_weight="1"
            Android:cacheColorHint="#00000000" >
        </com.example.taskgrptaskslistview.NestedListView>
    </LinearLayout>

NestedListView:

import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.view.View;
import Android.view.View.OnTouchListener;
import Android.view.ViewGroup;
import Android.widget.AbsListView;
import Android.widget.AbsListView.OnScrollListener;
import Android.widget.ListAdapter;
import Android.widget.ListView;

public class NestedListView extends ListView implements OnTouchListener, OnScrollListener {

private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;

public NestedListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    listViewTouchAction = -1;
    setOnScrollListener(this);
    setOnTouchListener(this);
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
    if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
        if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
            scrollBy(0, -1);
        }
    }
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int newHeight = 0;
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    if (heightMode != MeasureSpec.EXACTLY) {
        ListAdapter listAdapter = getAdapter();
        if (listAdapter != null && !listAdapter.isEmpty()) {
            int listPosition = 0;
            for (listPosition = 0; listPosition < listAdapter.getCount()
                    && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
                View listItem = listAdapter.getView(listPosition, null, this);
                //now it will not throw a NPE if listItem is a ViewGroup instance
                if (listItem instanceof ViewGroup) {
                    listItem.setLayoutParams(new LayoutParams(
                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                }
                listItem.measure(widthMeasureSpec, heightMeasureSpec);
                newHeight += listItem.getMeasuredHeight();
            }
            newHeight += getDividerHeight() * listPosition;
        }
        if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
            if (newHeight > heightSize) {
                newHeight = heightSize;
            }
        }
    } else {
        newHeight = getMeasuredHeight();
    }
    setMeasuredDimension(getMeasuredWidth(), newHeight);
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
        if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
            scrollBy(0, 1);
        }
    }
    return false;
}
}
0
madhu sudhan