私はこの問題の解決策を探しましたが、私が見つけることができる唯一の答えは「ListViewをScrollViewに入れないでください」のようです。しかし、その理由についての本当の説明はまだ見ていません。私が見つけたと思われる唯一の理由は、Googleがあなたがそうしたいとは思わないということです。そうですね、そうしました。
したがって、問題は、ListViewを最小の高さまで折りたたむことなくScrollViewに配置するにはどうすればよいかということです。
私はこの問題の解決策を探しましたが、私が見つけることができる唯一の答えは「ListViewをScrollViewに入れないでください」のようです。しかし、その理由についての本当の説明はまだ見ていません。私が見つけたと思われる唯一の理由は、Googleがあなたがそうしたいとは思わないということです。そうですね、そうしました。
したがって、問題は、ListViewを最小の高さまで折りたたむことなくScrollViewに配置するにはどうすればよいかということです。
これが私の解決策です。私は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);
}
}
を使用しListView
てスクロールしないようにすると、非常にコストがかかり、の目的全体に反しListView
ます。これを行うべきではありません。LinearLayout
代わりに使用してください。
これは間違いなく機能します............レイアウト内の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;
}
}
ListView
の中に入れるのではなく、としてScrollView
使用できます。中に入れなければならないものは、中に入れることができます。のヘッダーとフッターにレイアウトを追加することで、上部と下部の他のレイアウトを配置できます。したがって、全体でスクロールを体験できます。ListView
ScrollView
ListView
ListView
ListView
ListView
ListView
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)を呼び出します。
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は、指定された(非常に大きな)高さまでのすべての子を測定し、それに応じて高さを設定します。
これは、いくつかの理由で他のソリューションよりもうまく機能します。
欠点としては、これを行うことは、変更される可能性のあるSDKの文書化されていない動作に依存していると主張することができます。一方、これがwrap_contentが実際にListViewで機能する方法であり、現在のwrap_contentの動作が壊れていると主張することもできます。
動作が将来変更される可能性がある場合は、onMeasure関数と関連関数をListView.javaから独自のサブクラスにコピーしてから、onMeasureを介したAT_MOSTパスをUNSPECIFIEDに対して実行する必要があります。
ちなみに、これは少数のリストアイテムを扱う場合には完全に有効なアプローチだと思います。LinearLayoutと比較すると非効率的かもしれませんが、アイテムの数が少ない場合、LinearLayoutを使用することは不必要な最適化であり、したがって不必要な複雑さです。
組み込みの設定があります。ScrollViewの場合:
android:fillViewport="true"
Javaでは、
mScrollView.setFillViewport(true);
Romain Guyは、ここで詳細に説明しています:http ://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
スクロールできないカスタム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);
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);
}
これは私のために働いた唯一のものです:
ロリポップ以降では使用できます
yourtListView.setNestedScrollingEnabled(true);
これにより、RecyclerViewを使用する必要がある古いバージョンのOSとの下位互換性が必要な場合に、このビューのネストされたスクロールを有効または無効にします。
ListViewはすでにScrollViewであるため、ListViewをScrollViewに配置しないでください。つまり、これはScrollViewをScrollViewに配置するようなものです。
何を達成しようとしていますか?
これは、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);
}
@ 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を使用する必要が生じたときに、狭い場所から抜け出すことができました。:-)
それが不可能だった前に。しかし、新しい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>
ねえ、私は同様の問題を抱えていました。スクロールしないリストビューを表示したかったのですが、パラメーターの操作は機能しましたが、非効率的で、デバイスによって動作が異なることがわかりました。その結果、これは実際にこれを非常に効率的に行うスケジュールコードの一部です。 。
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();
}
});
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);
}
}
これは私がトリックをするために見つけた最良の方法です!
私が使用する解決策は、ScrollViewのすべてのコンテンツ(listViewの上下にある必要があります)をListViewのheaderViewおよびfooterViewとして追加することです。
したがって、それは次のように機能します。また、convertviewは本来あるべき方法で再発行されます。
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内にとどまるため、すべてがスクロール可能になります:)
@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();
}
提案された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);
}
}
}
}
これを試してみてください、これは私にとってはうまくいきます、私はそれを見つけた場所を忘れました、スタックオーバーフローのどこかで、私はそれがうまくいかない理由を説明するためにここにいませんが、これが答えです:)。
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でスクロールしていません
これらの答えはすべて間違っています!!! リストビューをスクロールビューに配置しようとしている場合は、デザインを再考する必要があります。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;
}
}
リストアダプタは、表示されているものだけをレンダリングするため、すべてを処理できます。
この問題全体は、LinearLayoutにsetAdapterメソッドがある場合に解消されます。これは、誰かに代わりにそれを使用するように指示した場合、代替手段が簡単になるためです。
別のスクロールビュー内にスクロールするListViewが実際に必要な場合、これは役に立ちませんが、そうでない場合は、少なくともアイデアが得られます。
スクロールするすべてのコンテンツを結合するカスタムアダプタを作成し、ListViewのアダプタをそれに設定する必要があります。
便利なサンプルコードはありませんが、次のようなものが必要な場合は。
<ListView/>
(other content)
<ListView/>
次に、そのすべてのコンテンツを表すアダプターを作成する必要があります。ListView / Adaptersは、さまざまなタイプも処理できるほど賢いですが、アダプターを自分で作成する必要があります。
android UI APIは、他のほとんどすべてのものほど成熟していないため、他のプラットフォームと同じ優れた機能はありません。また、Androidで何かを行うときは、Android(unix)の考え方を身に付ける必要があります。この考え方では、小さなパーツの機能をアセンブルし、独自のコードを記述して、それを実現する必要があります。仕事。
ListView
内部に配置すると、ScrollView
2つの問題が発生します。1つはScrollView
、子をUNSPECIFIEDモードで測定するためListView
、1つのアイテムのみを収容するように独自の高さを設定し(理由はわかりません)、もう1つはScrollView
、タッチイベントをインターセプトして、ListView
スクロールしないようにします。
ただし、いくつかの回避策を使用して内部に配置できます。この投稿では、私が回避策を説明しています。この回避策により、のリサイクル機能も保持できます。ListView
ScrollView
ListView
リストビューをスクロールビュー内に配置する代わりに、残りのコンテンツをリストビューとスクロールビューの開始の間に別のビューとして配置し、そのビューをリストビューのヘッダーとして設定します。したがって、最終的にはスクロールを担当するリストビューのみになります。
このライブラリは、問題に対する最も簡単で迅速な解決策です。
listview
内部では絶対に使用しないでくださいscrollview
。代わりに、そのNestedScrollView
中の親およびRecyclerViewとして使用する必要があります....多くのスクロールの問題を処理するため
これが、リストビューの全高を計算する私のバージョンのコードです。これは私のために働きます:
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();
}