358

私はこの問題の解決策を探しましたが、私が見つけることができる唯一の答えは「ListViewをScrollViewに入れないでください」のようです。しかし、その理由についての本当の説明はまだ見ていません。私が見つけたと思われる唯一の理由は、Googleがあなたがそうしたいとは思わないということです。そうですね、そうしました。

したがって、問題は、ListViewを最小の高さまで折りたたむことなくScrollViewに配置するにはどうすればよいかということです。

4

28 に答える 28

263

これが私の解決策です。私はAndroidプラットフォームにかなり慣れていないので、特に.measureを直接呼び出してLayoutParams.heightプロパティを直接設定する部分では、これは少しハックだと思いますが、機能します。

呼び出すUtility.setListViewHeightBasedOnChildren(yourListView)だけで、アイテムの高さに正確に合わせてサイズが変更されます。

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);
    }
}
于 2010-08-16T18:04:16.787 に答える
198

を使用しListViewてスクロールしないようにすると、非常にコストがかかり、の目的全体に反しListViewます。これを行うべきではありませんLinearLayout代わりに使用してください。

于 2010-08-16T18:19:48.733 に答える
89

これは間違いなく機能します............レイアウト内のXMLファイルを次のよう
に置き換える必要があります<ScrollView ></ScrollView>Custom ScrollView<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;
    }
}
于 2012-12-10T06:40:39.933 に答える
25

ListViewの中に入れるのではなく、としてScrollView使用できます。中に入れなければならないものは、中に入れることができます。のヘッダーとフッターにレイアウトを追加することで、上部と下部の他のレイアウトを配置できます。したがって、全体でスクロールを体験できます。ListViewScrollViewListViewListViewListViewListViewListView

于 2012-12-31T12:50:13.543 に答える
21

ScrollViewにListViewを含めることが非常に理にかなっている状況はたくさんあります。

DougWの提案に基づくコードは次のとおりです...フラグメントで動作し、メモリの消費量が少なくなります。

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

埋め込まれた各リストビューでsetListViewHeightBasedOnChildren(listview)を呼び出します。

于 2013-07-20T18:46:49.857 に答える
17

ListViewは、実際には、すべてのアイテムを表示するのに十分な高さになるようにそれ自体を測定することができますが、単にwrap_content(MeasureSpec.UNSPECIFIED)を指定した場合はこれを行いません。MeasureSpec.AT_MOSTで高さを指定すると、これが実行されます。この知識があれば、この問題を解決するための非常に単純なサブクラスを作成できます。これは、上記のどのソリューションよりもはるかにうまく機能します。このサブクラスでは、引き続きwrap_contentを使用する必要があります。

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

heightMeasureSpecを非常に大きなサイズ(Integer.MAX_VALUE >> 4)でAT_MOSTに操作すると、ListViewは、指定された(非常に大きな)高さまでのすべての子を測定し、それに応じて高さを設定します。

これは、いくつかの理由で他のソリューションよりもうまく機能します。

  1. すべてを正しく測定します(パディング、ディバイダー)
  2. 測定パス中にListViewを測定します
  3. #2により、追加のコードなしでアイテムの幅や数の変更を正しく処理します

欠点としては、これを行うことは、変更される可能性のあるSDKの文書化されていない動作に依存していると主張することができます。一方、これがwrap_contentが実際にListViewで機能する方法であり、現在のwrap_contentの動作が壊れていると主張することもできます。

動作が将来変更される可能性がある場合は、onMeasure関数と関連関数をListView.javaから独自のサブクラスにコピーしてから、onMeasureを介したAT_MOSTパスをUNSPECIFIEDに対して実行する必要があります。

ちなみに、これは少数のリストアイテムを扱う場合には完全に有効なアプローチだと思います。LinearLayoutと比較すると非効率的かもしれませんが、アイテムの数が少ない場合、LinearLayoutを使用することは不必要な最適化であり、したがって不必要な複雑さです。

于 2015-04-17T20:01:25.983 に答える
13

組み込みの設定があります。ScrollViewの場合:

android:fillViewport="true"

Javaでは、

mScrollView.setFillViewport(true);

Romain Guyは、ここで詳細に説明しています:http ://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/

于 2014-08-04T05:50:14.580 に答える
10

スクロールできないカスタムListViewを作成します

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

レイアウトリソースファイル内

<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>

Javaファイルの場合

次のように、ListViewの代わりにcustomListviewのオブジェクトを作成します。NonScrollListViewnon_scroll_list =(NonScrollListView)findViewById(R.id.lv_nonscroll_list);

于 2016-05-24T10:28:39.147 に答える
8

2つのスクロールを同時に使用することはできませんでした。ListViewの全長を取得し、listviewを合計の高さで展開します。次に、ScrollViewには直接1つの子があるため、直接またはLinearLayoutを使用してListViewを追加できます。コード内のsetListViewHeightBasedOnChildren(lv)メソッドをコピーし、listviewを展開すると、scrollview内でlistviewを使用できます。\layoutxmlファイル

<?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>

ActivityクラスのonCreateメソッド:

 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);
      }
于 2014-07-12T06:37:49.617 に答える
6

これは私のために働いた唯一のものです:

ロリポップ以降では使用できます

yourtListView.setNestedScrollingEnabled(true);

これにより、RecyclerViewを使用する必要がある古いバージョンのOSとの下位互換性が必要な場合に、このビューのネストされたスクロールを有効または無効にします。

于 2016-11-07T07:30:27.730 に答える
4

ListViewはすでにScrollViewであるため、ListViewをScrollViewに配置しないでください。つまり、これはScrollViewをScrollViewに配置するようなものです。

何を達成しようとしていますか?

于 2010-08-16T18:02:45.290 に答える
4

これは、DougW、Good Guy Greg、およびPaulによる回答の組み合わせです。カスタムリストビューアダプタと非標準のリストアイテムでこれを使用しようとすると、すべてが必要であることがわかりました。そうしないと、リストビューがアプリケーションをクラッシュさせました(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);
    }
于 2013-08-04T19:29:25.030 に答える
3

@ DougWUtilityをC#(Xamarinで使用)に変換しました。以下は、リスト内の固定高さのアイテムに対して正常に機能し、一部のアイテムのみが標準アイテムよりも少し大きい場合は、ほとんど正常であるか、少なくとも良いスタートになります。

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

@DougWに感謝します。これにより、OtherPeople'sCodeを使用する必要が生じたときに、狭い場所から抜け出すことができました。:-)

于 2014-07-09T04:31:51.393 に答える
3

それが不可能だった前に。しかし、新しいAppcompatライブラリとDesignライブラリのリリースにより、これを実現できます。

NestedScrollViewhttps://developer.android.com/reference/android/support/v4/widget/NestedScrollView.htmlを使用する必要があり ます

Listviewで動作するかどうかはわかりませんが、RecyclerViewでは動作します。

コードスニペット:

<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>
于 2017-10-10T05:25:33.170 に答える
2

ねえ、私は同様の問題を抱えていました。スクロールしないリストビューを表示したかったのですが、パラメーターの操作は機能しましたが、非効率的で、デバイスによって動作が異なることがわかりました。その結果、これは実際にこれを非常に効率的に行うスケジュールコードの一部です。 。

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

注:これを使用notifyDataSetChanged();すると、ビューが再描画されないため、意図したとおりに機能しません。回避策が必要な場合はこれを行ってください

adapter.registerDataSetObserver(new DataSetObserver() {

            @Override
            public void onChanged() {
                super.onChanged();
                removeAndRedrawViews();

            }

        });
于 2012-05-11T15:59:22.933 に答える
2

ScrollView内でListViewを使用する場合、2つの問題があります。

1- ListViewは、子の高さまで完全に拡張する必要があります。このListViewはこれを解決します:

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

分周器の高さは0でなければなりません。代わりに、行のパディングを使用してください。

2- ListViewはタッチイベントを消費するため、ScrollViewは通常どおりスクロールできません。このScrollViewは、この問題を解決します。

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

これは私がトリックをするために見つけた最良の方法です!

于 2014-03-31T00:37:21.413 に答える
2

私が使用する解決策は、ScrollViewのすべてのコンテンツ(listViewの上下にある必要があります)をListViewのheaderViewおよびfooterViewとして追加することです。

したがって、それは次のように機能します。また、convertviewは本来あるべき方法で再発行されます。

于 2015-07-24T07:52:01.107 に答える
1

Vinayのコードのおかげで、スクロールビュー内にリストビューを含めることができないが、そのようなものが必要な場合の私のコードがここにあります

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

RelativeLayoutはScrollView内にとどまるため、すべてがスクロール可能になります:)

于 2012-06-22T14:01:55.960 に答える
1

@djunod回答を少し変更して、完全に機能させる必要があります。

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();
}
于 2013-09-23T18:39:06.737 に答える
1

提案されたsetListViewHeightBasedOnChildren()メソッドはほとんどの場合に機能しますが、場合によっては、特に多くの項目で、最後の要素が表示されないことに気付きました。そこで、アダプタコードを再利用するために、 ListViewの動作の単純なバージョンを模倣することにしました。これが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);

        }
    }
}
}
于 2014-02-19T11:08:08.260 に答える
1

これを試してみてください、これは私にとってはうまくいきます、私はそれを見つけた場所を忘れました、スタックオーバーフローのどこかで、私はそれがうまくいかない理由を説明するためにここにいませんが、これが答えです:)。

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

編集!、私はついに私がコードをどこで手に入れたのかを知りました。ここ !:ScrollView内のListViewはAndroidでスクロールしていません

于 2014-03-03T03:51:27.183 に答える
1

これらの答えはすべて間違っています!!! リストビューをスクロールビューに配置しようとしている場合は、デザインを再考する必要があります。ScrollViewをScrollViewに配置しようとしています。リストに干渉すると、リストのパフォーマンスが低下します。これはAndroidによってこのように設計されました。

リストを他の要素と同じスクロールに表示したい場合は、アダプターの単純なswitchステートメントを使用して、リストの一番上に他の項目を追加するだけです。

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


}

リストアダプタは、表示されているものだけをレンダリングするため、すべてを処理できます。

于 2016-02-10T20:56:27.360 に答える
0

この問題全体は、LinearLayoutにsetAdapterメソッドがある場合に解消されます。これは、誰かに代わりにそれを使用するように指示した場合、代替手段が簡単になるためです。

別のスクロールビュー内にスクロールするListViewが実際に必要な場合、これは役に立ちませんが、そうでない場合は、少なくともアイデアが得られます。

スクロールするすべてのコンテンツを結合するカスタムアダプタを作成し、ListViewのアダプタをそれに設定する必要があります。

便利なサンプルコードはありませんが、次のようなものが必要な場合は。

<ListView/>

(other content)

<ListView/>

次に、そのすべてのコンテンツを表すアダプターを作成する必要があります。ListView / Adaptersは、さまざまなタイプも処理できるほど賢いですが、アダプターを自分で作成する必要があります。

android UI APIは、他のほとんどすべてのものほど成熟していないため、他のプラットフォームと同じ優れた機能はありません。また、Androidで何かを行うときは、Android(unix)の考え方を身に付ける必要があります。この考え方では、小さなパーツの機能をアセンブルし、独自のコードを記述して、それを実現する必要があります。仕事。

于 2013-01-13T19:41:41.227 に答える
0

ListView内部に配置すると、ScrollView2つの問題が発生します。1つはScrollView、子をUNSPECIFIEDモードで測定するためListView、1つのアイテムのみを収容するように独自の高さを設定し(理由はわかりません)、もう1つはScrollView、タッチイベントをインターセプトして、ListViewスクロールしないようにします。

ただし、いくつかの回避策を使用して内部に配置できます。この投稿では、私が回避策を説明しています。この回避策により、のリサイクル機能も保持できます。ListViewScrollViewListView

于 2014-10-24T04:36:43.907 に答える
0

リストビューをスクロールビュー内に配置する代わりに、残りのコンテンツをリストビューとスクロールビューの開始の間に別のビューとして配置し、そのビューをリストビューのヘッダーとして設定します。したがって、最終的にはスクロールを担当するリストビューのみになります。

于 2016-03-14T14:55:30.387 に答える
0

このライブラリは、問題に対する最も簡単で迅速な解決策です。

于 2017-01-25T02:31:29.193 に答える
0

listview内部では絶対に使用しないでくださいscrollview。代わりに、そのNestedScrollView中の親およびRecyclerViewとして使用する必要があります....多くのスクロールの問題を処理するため

于 2021-01-31T09:08:40.917 に答える
-1

これが、リストビューの全高を計算する私のバージョンのコードです。これは私のために働きます:

   public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null || listAdapter.getCount() < 2) {
        // pre-condition
        return;
    }

    int totalHeight = 0;
    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(BCTDApp.getDisplaySize().width, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        if (listItem instanceof ViewGroup) listItem.setLayoutParams(lp);
        listItem.measure(widthMeasureSpec, heightMeasureSpec);
        totalHeight += listItem.getMeasuredHeight();
    }

    totalHeight += listView.getPaddingTop() + listView.getPaddingBottom();
    totalHeight += (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight;
    listView.setLayoutParams(params);
    listView.requestLayout();
}
于 2014-02-13T23:15:46.600 に答える