35

listviewitem内にlistviewを配置しようとしています。内側のリストビューはスクロール可能であってはなりませんが、すべての行を表示するために必要なすべてのサイズを取ります。これにもっと良い方法はありますか?テーブル、グリッド、...?私が今直面している問題は、内側のリストビューが必要なスペースをとらないため、最初のリストアイテムのほぼ終わりでカットされることです。スクロールしようとすると、外側のリストビューだけがスクロールします。これはまさに私が望むものです。

how_it_should_look_like ありがとう、私の最終的な解決策は

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

5 に答える 5

39

Androidのドキュメントから-ListviewListViewは、スクロール可能なアイテムのリストを表示するビューグループです。

その内側のリストビューを実際にスクロールするのではなく、外側のリストビューをスクロールする必要があります。ただし、内部リストビューは、含まれる要素の量によって異なる場合があると思います。

内部リストビューの代わりに、

線形レイアウトの場合(いくつかのサンプルコード):

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

線形レイアウトをビューホルダーに保存する必要があります(ビューホルダーパターンを参照)。removeAllViews()現在の行の内部行が再利用された行よりも少ない場合にのみ必要になると思うので、ビューホルダーの行数も節約します。

内部行の最大数がそれほど多くない場合は、それらをビューホルダーにキャッシュして、膨張とfindByViewId(たとえばArrayList)を回避することも検討できます。

于 2012-07-25T15:23:51.187 に答える
7

アプリでも同じ問題が発生しますが、ListViewを使用する必要がありました。これは、共有アイテムであり、同等のコンポーネントを複製したくないためです。つまり、すべての行を表示するようにプログラムで内部ListViewのサイズを修正しました。問題が解決しました:

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();
于 2014-09-23T12:14:07.910 に答える
7

たぶん誰かが私の解決策が役に立つと思うでしょう。これは@ChrLippの回答に基づいており、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"
    />
于 2015-02-15T10:38:51.883 に答える
1

この正確な構造(のListView内部ListView)を作成しようとしましたが、内部の最初のアイテムのみが表示されるという同じ問題がありましたListViewlayout_height内部リストのをからmatch_parentセットに変更して修正しましたdp

思った通りに動作したようです。

于 2014-07-10T21:59:49.470 に答える
0

@このネストされたクラスを試す

listViewこれは、内側のスクロールまたは同じlistView2秒で機能しますlistviewactivity

        <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;
}
}
于 2015-10-17T10:23:52.587 に答える