web-dev-qa-db-ja.com

android listviewは、静的ヘッダーでスクロールせずに使用可能なすべてのアイテムを表示します

特定のレイアウトを機能させようとしているときに少し苦労しています。リストが欲しいです。リストはスクロール可能である必要はありませんが、完全に表示される必要があります。ただし、コンテンツ全体が画面よりも高くない場合は、ページ自体が(リストを含む)スクロールできる必要があります。

<ScrollView
     xmlns:Android="http://schemas.Android.com/apk/res/Android"
     Android:layout_width="fill_parent"
     Android:layout_height="wrap_content"
     >

     <LinearLayout
         xmlns:Android="http://schemas.Android.com/apk/res/Android"
         Android:id="@+id/linear_layout"
         Android:orientation="vertical"
         Android:layout_width="fill_parent"
         Android:layout_height="wrap_content"
         Android:layout_weight="1"
         Android:background="#ff181818"
         >
           <Textview Android:id="@+id/my_text" text="header contents goes here" Android:layout_width="fill_parent" Android:layout_height="wrap_content"/>
           <Textview Android:id="@+id/headertext" text="header contents goes here" Android:layout_width="fill_parent" Android:layout_height="wrap_content"/>

          <ListView
               Android:id="@+id/my_list1"
               Android:layout_height="wrap_content"
               Android:layout_width="fill_parent"
          /> 
     </LinearLayout> 

</ScrollView>

使用可能な高さを埋めるのではなく、画面のごく一部(リストごとに約2行)を使用するだけで、リスト自体をスクロールできます。リストを常に表示するようにレイアウトを変更し、画面をスクロール可能にするにはどうすればよいですか?

33
d-man

私が使用した解決策は、ListViewをLinearLayoutに置き換えることです。 LinearLayout内にすべてのアイテムを作成できます。それらはすべて表示されます。したがって、ListViewを使用する必要はありません。

LinearLayout list = (LinearLayout)findViewById(R.id.list_recycled_parts);
for (int i=0; i<products.size(); i++) {
  Product product = products.get(i);
  View vi = inflater.inflate(R.layout.product_item, null);
  list.addView(vi);
}
63
Fedor

@Alexが受け入れられた回答で指摘したように、LinearLayoutはほとんど置き換えになりません。 LinearLayoutがオプションではないという問題がありました。それは、この blog に出くわしたときです。参照用にここにコードを配置します。それが誰かに役立つことを願っています!

public class UIUtils {

    /**
     * Sets ListView height dynamically based on the height of the items.
     *
     * @param listView to be resized
     * @return true if the listView is successfully resized, false otherwise
     */
    public static boolean setListViewHeightBasedOnItems(ListView listView) {

        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter != null) {

            int numberOfItems = listAdapter.getCount();

            // Get total height of all items.
            int totalItemsHeight = 0;
            for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
                View item = listAdapter.getView(itemPos, null, listView);
                item.measure(0, 0);
                totalItemsHeight += item.getMeasuredHeight();
            }

            // Get total height of all item dividers.
            int totalDividersHeight = listView.getDividerHeight() *
                    (numberOfItems - 1);

            // Set list height.
            ViewGroup.LayoutParams params = listView.getLayoutParams();
            params.height = totalItemsHeight + totalDividersHeight;
            listView.setLayoutParams(params);
            listView.requestLayout();

            return true;

        } else {
            return false;
        }

    }
}

使用法:

//initializing the adapter
listView.setAdapter(adapter);
UIUtils.setListViewHeightBasedOnItems(listView);

//whenever the data changes
adapter.notifyDataSetChanged();
UIUtils.setListViewHeightBasedOnItems(listView);
39
HussoM

独自のカスタムリストビューを作成できます。 (ListView/ExpandableListView/GridViewを拡張できます)、これでonMeasureメソッドをオーバーライドします。これにより、関数などを呼び出す必要がなくなります。 xmlで使用するだけです。

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
            MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, expandSpec);
}
11
Francisco

レイアウトにListViewがあり、ListViewにラップするため、ここでScrollViewを処理できないライブラリを使用したいと考えました。私にとって最善の解決策は、ヒョードルの答えに基づいています。

すでにArrayAdapterListViewを取得しているので、再利用したかったのです。

LinearLayout listViewReplacement = (LinearLayout) findViewById(R.id.listViewReplacement);
NamesRowItemAdapter adapter = new NamesRowItemAdapter(this, namesInList);
for (int i = 0; i < adapter.getCount(); i++) {
    View view = adapter.getView(i, null, listViewReplacement);
    listViewReplacement.addView(view);
}

私にとっては、1〜5個の要素のさまざまな動的データを表示するだけでよいので、これはうまく機能します。独自の仕切りを追加する必要がありました。

11
Kai

それでも誰かに問題がある場合は、customListを作成し、実装したようにonMesure()メソッドを追加できます。

public class ScrolleDisabledListView extends ListView {

private int mPosition;

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

public ScrolleDisabledListView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public ScrolleDisabledListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;

    if (actionMasked == MotionEvent.ACTION_DOWN) {
        // Record the position the list the touch landed on
        mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
        return super.dispatchTouchEvent(ev);
    }

    if (actionMasked == MotionEvent.ACTION_MOVE) {
        // Ignore move events
        return true;
    }

    if (actionMasked == MotionEvent.ACTION_UP) {
        // Check if we are still within the same view
        if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
            super.dispatchTouchEvent(ev);
        } else {
            // Clear pressed state, cancel the action
            setPressed(false);
            invalidate();
            return true;
        }
    }

    return super.dispatchTouchEvent(ev);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
            MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, expandSpec);
}
}
3
Rojina

これをチェックしてください:

wrap_contentを無視するListView

Android:layout_heightとAndroid:layout_weightを使用して解決しました:

<ListView
    Android:layout_height="0dp"
    Android:layout_weight="1"
    />
2
tinsukE

ListViewの設定パラメーターを使用してそれをやった

public static void setListViewHeightBasedOnChildren(ListView listView) {

    //this comes from value from xml tag of each item
    final int HEIGHT_LARGE=75;
    final int HEIGHT_LARGE=50;
    final int HEIGHT_LARGE=35;
    ViewGroup.LayoutParams params = listView.getLayoutParams();

    int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;

    switch(screenSize) {

    case Configuration.SCREENLAYOUT_SIZE_LARGE:
         params.height =(int) (HEIGHT_LARGE*size);
         break;
    case Configuration.SCREENLAYOUT_SIZE_NORMAL:
         params.height =(int) (HEIGHT_NORMAL*size);
         break;
    case Configuration.SCREENLAYOUT_SIZE_SMALL:
          params.height =(int) (HEIGHT_SMALL*size);
          break;
    }
    listView.setLayoutParams(params);  
}
1
Ivan

ListViewクラスを拡張せずにこの問題の簡単な解決策が必要な場合、これはあなたのための解決策です。

 mListView.post(new Runnable() {
        @Override
        public void run() {
            int height = 0;
            for(int i = 0; i < mListView.getChildCount();i++)
                height += mListView.getChildAt(i).getHeight();
            ViewGroup.LayoutParams lParams = mListView.getLayoutParams();
            lParams.height = height;
            mListView.setLayoutParams(lParams);
        }
    });
0
Kvant

静的なヘッダーはありませんが、HussoMの投稿を手がかりとして使用して、ここで作業することができました。私のシナリオでは、リスト内のアイテムの高さは各アイテムの可変テキスト文のために不均一であり、高さにはwrap_contentを、幅にはmatch_parentを使用しています。

public class NonScrollableListView extends ListView {

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

  public NonScrollableListView(Context context, AttributeSet attrs) {
      super(context, attrs);
  }

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

  public NonScrollableListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
      super(context, attrs, defStyleAttr, defStyleRes);
  }

  /**
   * Measure the height of all the items in the list and set that to be the height of this
   * view, so it appears as full size and doesn't need to scroll.
   * @param widthMeasureSpec
   * @param heightMeasureSpec
   */
  @Override
  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      ListAdapter adapter = this.getAdapter();
      if (adapter == null) {
          // we don't have an adapter yet, so probably initializing.
          super.onMeasure(widthMeasureSpec, heightMeasureSpec);
          return;
      }

      int totalHeight = 0;

      // compute the height of all the items
      int itemCount = adapter.getCount();
      for (int index=0; index<itemCount; index++) {
          View item = adapter.getView(index, null, this);
          // set the width so it can figure out the height
          item.measure(widthMeasureSpec, 0);
          totalHeight += item.getMeasuredHeight();
      }

      // add any dividers to the height
      if (this.getDividerHeight() > 0) {
          totalHeight += this.getDividerHeight() * Math.max(0, itemCount - 1);
      }

      // make it so
      this.setMeasuredDimension(widthMeasureSpec,
              MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY));
  }

}

0
cmarcelk

Iamはこれを誰も見ていないことに驚いている。Uは同じレイアウト上に2つのスクロールを持つことはできない。最初に、スクロールビューがあり、次にリストがあります。そこで、いくつかのAndroidグッドプラクティスを削除しているに違いありません。

0
Catluc

すべてのアイテムの高さが同じ場合

        int totalItemsHeight = baseDictionaries.size() * item.getMeasuredHeight();
        int totalDividersHeight = listView.getDividerHeight() * (baseDictionaries.size() - 1);
        int totalPadding = listView.getPaddingBottom() + listView.getPaddingTop();

        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) listTranslationWords.getLayoutParams();
        lp.height = totalItemsHeight + totalDividersHeight + totalPadding;
        listTranslationWords.setLayoutParams(lp);
0
Vahe Gharibyan