ListView внутри ScrollView не прокручивается на Android
У меня проблемы с прокруткой ListView
внутри ScrollView
, У меня есть Activity, которая имеет несколько EditTexts в верхней части, а затем узел вкладок с двумя вкладками, которые имеют по одному ListView каждая. Когда представления EditText сфокусированы, появляется программная клавиатура, и, когда у меня ScrollView, содержимое прокручивается. Но проблема возникает, когда в ListViews больше элементов (которые находятся на вкладках), я не могу прокрутить ListView, даже если есть больше элементов.
Ниже приведен макет XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="?backgroundImage"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_margin="10dip"
android:id="@+id/buttons">
<Button
android:text="Save"
android:layout_margin="2dip"
android:textSize="20dip"
android:id="@+id/btnSaveorUpdate"
android:layout_height="wrap_content"
android:layout_width="145dip"></Button>
<Button
android:text="Cancel"
android:layout_margin="2dip"
android:textSize="20dip"
android:id="@+id/btnCancelorDelete"
android:layout_height="wrap_content"
android:layout_width="145dip"></Button>
</LinearLayout>
<ScrollView
android:layout_above="@id/buttons"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_margin="10dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="10dip">
<TextView
android:text="Bill details"
android:textColor="?textColorDark"
android:layout_alignParentTop="true"
android:id="@+id/txtEnterDetails"
android:textSize="25dip"
android:textStyle="bold"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginBottom="2dip"></TextView>
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0dip"
android:layout_height="0dip" />
<EditText
android:layout_width="fill_parent"
android:hint="Enter data"
android:inputType="numberDecimal"
android:id="@+id/txtSample"
android:textSize="@dimen/editText"
android:layout_height="@dimen/editTextHeight"
android:text=""></EditText>
<EditText
android:layout_width="fill_parent"
android:id="@+id/txtDescription"
android:hint="Enter description"
android:textSize="@dimen/editText"
android:layout_height="@dimen/editTextHeight"
android:inputType="text"
android:text=""></EditText>
<EditText
android:layout_width="fill_parent"
android:id="@+id/txtComment"
android:hint="Enter comment (if any)"
android:textSize="@dimen/editText"
android:layout_height="@dimen/editTextHeight"
android:inputType="text"
android:text=""></EditText>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtDate"
android:layout_width="wrap_content"
android:text=""
android:textSize="20dip"
android:textColor="?textColorDark"
android:layout_marginLeft="10dip"
android:layout_height="@dimen/editTextHeight"
android:layout_gravity="center_vertical" />
<Button
android:id="@+id/btnPickDate"
android:layout_width="wrap_content"
android:layout_height="@dimen/editTextHeight"
android:text="Select date"
android:layout_margin="2dip"
android:textSize="15dip"
android:layout_gravity="center_vertical" />
</LinearLayout>
<TabHost
android:id="@+id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@android:id/tabs"></TabWidget>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@android:id/tabcontent">
<ScrollView
android:layout_above="@id/buttons"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:id="@+id/tab1">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TableRow
android:id="@+id/tableRow1"
android:layout_marginLeft="2dip"
android:layout_marginRight="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:src="@drawable/ic_menu_invite"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_gravity="center_vertical"></ImageView>
<TextView
android:text="Add friend"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_centerVertical="true"
android:textColor="?textColorDark"
android:textSize="@dimen/editText"
android:layout_gravity="center_vertical" />
</LinearLayout>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip">
<TextView
android:id="@+id/txtData1"
android:layout_width="170dip"
android:layout_height="wrap_content"
android:text="Data"
android:textSize="14dip"
android:textStyle="bold"
android:textColor="#000000">
</TextView>
<TextView
android:id="@+id/txtData2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample"
android:textSize="13dip"
android:textColor="#000000"></TextView>
</TableRow>
</TableLayout>
<ListView
android:cacheColorHint="#00000000"
android:id="@+id/ListView01"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</LinearLayout>
</ScrollView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:id="@+id/tab2"
android:orientation="vertical">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TableRow
android:id="@+id/tableRow2"
android:layout_marginLeft="2dip"
android:layout_marginRight="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:src="@drawable/ic_menu_invite"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_gravity="center_vertical"></ImageView>
<TextView
android:text="Sample"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_centerVertical="true"
android:textColor="?textColorDark"
android:textSize="@dimen/editText"
android:layout_gravity="center_vertical" />
</LinearLayout>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip">
<TextView
android:id="@+id/txtUser1"
android:layout_width="170dip"
android:layout_height="wrap_content"
android:text="User"
android:textSize="14dip"
android:textStyle="bold"
android:textColor="#000000">
</TextView>
<TextView
android:id="@+id/txtUserData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UserData"
android:textSize="13dip"
android:textColor="#000000"></TextView>
</TableRow>
</TableLayout>
<ListView
android:cacheColorHint="#00000000"
android:id="@+id/ListView02"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
</ScrollView>
</RelativeLayout>
Пожалуйста, кто-нибудь может сказать мне, в чем здесь проблема? У меня есть еще один пост о ListView внутри проблемы ScrollView, но они были бесполезны в моем случае.
27 ответов
Вы не должны ставить ListView
внутри ScrollView
поскольку ListView
класс реализует собственную прокрутку и просто не получает жесты, потому что все они обрабатываются родителем ScrollView
, Я настоятельно рекомендую вам как-то упростить ваш макет. Например, вы можете добавить представления, которые вы хотите прокрутить в ListView
как верхние или нижние колонтитулы.
ОБНОВЛЕНИЕ:
Начиная с API уровня 21 (Lollipop), вложенные контейнеры прокрутки официально поддерживаются Android SDK. Есть куча методов в View
а также ViewGroup
классы, которые предоставляют эту функциональность. Чтобы заставить вложенную прокрутку работать на Lollipop, вы должны включить ее для дочернего представления прокрутки, добавив android:nestedScrollingEnabled="true"
к его объявлению XML или путем явного вызова setNestedScrollingEnabled(true)
,
Если вы хотите, чтобы вложенная прокрутка работала на устройствах, предшествующих Lollipop, что вы, вероятно, делаете, вы должны использовать соответствующие служебные классы из библиотеки поддержки. Сначала вы должны заменить вас ScrollView
с NestedScrollView. Последний реализует как NestedScrollingParent, так и NestedScrollingChild, поэтому он может использоваться как родительский или дочерний контейнер прокрутки.
Но ListView
не поддерживает вложенную прокрутку, поэтому вам нужно разделить ее на подклассы и реализовать NestedScrollingChild
, К счастью, библиотека поддержки предоставляет класс NestedScrollingChildHelper, поэтому вам просто нужно создать экземпляр этого класса и вызвать его методы из соответствующих методов вашего класса представления.
Я нашел решение, которое отлично работает и может прокрутить ListView
без проблем:
ListView lv = (ListView)findViewById(R.id.myListView); // your listview inside scrollview
lv.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;
}
});
Что это делает, это отключить TouchEvent
на ScrollView
и сделать ListView
перехватить их. Это просто и работает все время.
У меня также есть одно решение. Я всегда использую этот метод. Попробуй это
<ScrollView
android:id="@+id/createdrill_scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp" >
<net.thepaksoft.fdtrainer.NestedListView
android:id="@+id/crewList"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_weight="1"
android:background="@drawable/round_shape"
android:cacheColorHint="#00000000" >
</net.thepaksoft.fdtrainer.NestedListView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp" >
<net.thepaksoft.fdtrainer.NestedListView
android:id="@+id/benchmarksList"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_weight="1"
android:background="@drawable/round_shape"
android:cacheColorHint="#00000000" >
</net.thepaksoft.fdtrainer.NestedListView>
</LinearLayout>
</ScrollView>
Класс NestedListView.java:
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;
}
}
Вы должны просто заменить свой <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;
}
}
У меня была такая же проблема, и пока я гуглил, я нашел твой вопрос. Да, помеченный ответ работал и для меня, но была некоторая проблема.
В любом случае я нашел другое решение. который отлично работает, не делая никаких жонглирования.
list.setOnTouchListener(new OnTouchListener() {
// Setting on Touch Listener for handling the touch inside ScrollView
@Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
Я знаю, что этот вопрос задан давно, но кто когда-либо застрянет, может решить эту проблему, добавив эту строку в свой ListView
android:nestedScrollingEnabled="true"
Например -
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true" />
Вот точный метод использования Listview в Scrollview. Все, что мы должны обрабатывать сенсорные события.
lstvNextTracks.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.e("Lisview *************", "focused");
SCView.requestDisallowInterceptTouchEvent(true);
return false;
}
});
SCView.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
int arr[] = new int[] { 1, 2 };
lstvNextTracks.getLocationOnScreen(arr);
/* Get bounds of child Listview*/
int lstvTop = arr[0];
int lstvBottom = arr[1] + lstvNextTracks.getHeight();
int lstvLeft = arr[1];
int lstvRight = arr[0] + lstvNextTracks.getWidth();
float x = event.getRawX();
float y = event.getRawY();
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
/*check if child ListView bounds are touched*/
if (x > lstvTop && x < lstvBottom && y > lstvLeft && y < lstvRight)
{
SCView.clearFocus();
/*This statement tells the ScrollView to do not handle this touch event, so the child Listview will handle this touch event and will scroll */
SCView.requestDisallowInterceptTouchEvent(true);
/*The child Listview isFocusable attribute must be set to true otherwise it will not work*/
lstvNextTracks.requestFocus();
return true;
} else
return false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE)
{
if (x > lstvTop && x < lstvBottom && y > lstvLeft && y < lstvRight)
{
SCView.clearFocus();
SCView.requestDisallowInterceptTouchEvent(true);
lstvNextTracks.requestFocus();
return true;
} else
return false;
} else if (event.getAction() == MotionEvent.ACTION_UP)
{
SCView.clearFocus();
SCView.requestDisallowInterceptTouchEvent(true);
lstvNextTracks.requestFocus();
return false;
} else
{
return false;
}
}
});
Используйте следующий метод и наслаждайтесь!
private void setListViewScrollable(final ListView list) {
list.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
listViewTouchAction = event.getAction();
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
list.scrollBy(0, 1);
}
return false;
}
});
list.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
list.scrollBy(0, -1);
}
}
});
}
listViewTouchAction является глобальным целочисленным значением. Если вы можете заменить линию
list.scrollBy(0, 1);
с чем-то еще, пожалуйста, поделитесь этим с нами.
Наслаждайтесь!
Это плохая практика иметь два разных вида прокрутки вместе. У самого ListView есть своя собственная функция прокрутки, а высота автоматически настраивается в соответствии с настройками адаптера для ваших элементов строки (помните, что мы не устанавливаем конкретную высоту для ListView в нашем XML-формате Layout). Однако в вашем случае вы можете заменить ListView классом, и это отрегулирует высоту для вашего ListView, имея в виду, что ваш ListView находится внутри ScrollView.
Это поможет вам:
public class ExpandableHeightListview extends ListView
{
boolean expanded = false;
public ExpandableHeightListview(Context context)
{
super(context);
}
public ExpandableHeightListview(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ExpandableHeightListview(Context context, AttributeSet attrs,int defStyle)
{
super(context, attrs, defStyle);
}
public boolean isExpanded()
{
return expanded;
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// Calculate entire height by providing a very large height hint.
// But do not use the highest 2 bits of this integer; those are
// reserved for the MeasureSpec mode.
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
Теперь расширьте свой ListView этим классом, просто измените тэг ListView с вашего ресурса xml на что-то вроде этого,
<yourpackagename.ExpandableHeightListview
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/White"
android:scrollbars="none"
android:orientation="vertical"
android:fadingEdge="none">
</cyourpackagename.ExpandableHeightListview>
Это решит проблему с прокруткой ListView, поскольку теперь родительская прокрутка управляется ScrollView, а не ListView.
У меня похожая проблема, и она решена путем создания пользовательского класса путем расширения с помощью ListView.
ScrollableListView.java
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
public class ScrollableListView extends ListView {
public ScrollableListView (Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollableListView (Context context) {
super(context);
}
public ScrollableListView (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
Использование:
<com.my.package.ScrollableListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Вышеуказанное решение @Shailesh Rohit прекрасно работает. Некоторые трюки должны быть сделаны.
Если вы помещаете вспомогательный класс в тот же класс (основной класс), тогда делайте класс Helper статическим, а getListViewSize () не статичным.
Самое главное, напишите "Helper.getListViewSize(listView);" оператор после установки адаптера в первый раз, например "listView.setAdapter(myAdapter);" а также когда вы когда-либо используете "myAdapter.notifyDataSetChanged();"
Использование показано ниже.
listView = (ListView) findViewById (R.id.listView); myAdapter = new ArrayAdapter (this, android.R.layout.simple_list_item_1, listValues); listView.setAdapter (myAdapter); Helper.getListViewSizelistView(ListView);
myAdapter.notifyDataSetChanged (); Helper.getListViewSizelistView(ListView);
Я попробовал и протестировал почти все методы, упомянутые выше, поверьте мне, после полного бегства от RecyclerView, я заменил свой ListView на RecyclerView, и он работал отлично. Не нужно было какой-либо сторонней библиотеки для ExtendedHeightListView и всего, просто и просто RecyclerView.
Итак, вот мой файл Layout перед recyclerView:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="5dp">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/relativeLayoutre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
tools:context="com.example.android.udamovappv3.activities.DetailedActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/my_toolbar_detail"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="top"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<TextView
android:id="@+id/title_name"
android:layout_width="fill_parent"
android:layout_height="128dp"
android:layout_alignParentStart="true"
android:layout_marginTop="59dp"
android:background="#079ED9"
android:gravity="left|center"
android:padding="25dp"
android:text="Name"
android:textColor="#ffffff"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/my_toolbar_detail"
app:layout_constraintVertical_bias="0.0"
tools:layout_editor_absoluteX="0dp" />
<ImageView
android:id="@+id/iv_poster"
android:layout_width="131dp"
android:layout_height="163dp"
android:layout_alignStart="@+id/my_toolbar_detail"
android:layout_below="@+id/title_name"
android:layout_marginBottom="15dp"
android:layout_marginRight="8dp"
android:layout_marginTop="15dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="@mipmap/ic_launcher" />
<Button
android:id="@+id/bt_mark_as_fav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/iv_poster"
android:layout_alignParentEnd="true"
android:layout_marginBottom="11dp"
android:layout_marginEnd="50dp"
android:background="#079ED9"
android:text="Mark As \n Favorite"
android:textSize="10dp" />
<TextView
android:id="@+id/tv_runTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/tv_rating"
android:layout_below="@+id/tv_releaseDate"
android:layout_marginTop="11dp"
android:text="TextView"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_releaseDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/tv_runTime"
android:layout_alignTop="@+id/iv_poster"
android:text="TextView"
android:textSize="25dp" />
<TextView
android:id="@+id/tv_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/bt_mark_as_fav"
android:layout_below="@+id/tv_runTime"
android:layout_marginTop="11dp"
android:text="TextView" />
<TextView
android:id="@+id/tv_overview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/iv_poster"
android:layout_centerHorizontal="true"
android:layout_marginBottom="5dp"
android:foregroundGravity="center"
android:text="adasdasdfadfsasdfasdfasdfasdfnb agfjuanfalsbdfjbdfklbdnfkjasbnf;kasbdnf;kbdfas;kdjabnf;lbdnfo;aidsnfl';asdfj'plasdfj'pdaskjf'asfj'p[asdfk"
android:textColor="#000000"
/>
<RelativeLayout
android:id="@+id/foodItemActvity_linearLayout_fragments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_below="@+id/tv_overview">
<TextView
android:id="@+id/fragment_dds_review_textView_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reviews:"
android:textAppearance="?android:attr/textAppearanceMedium" />
<com.github.paolorotolo.expandableheightlistview.ExpandableHeightListView
android:id="@+id/expandable_listview"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/fragment_dds_review_textView_label"
android:padding="8dp">
</com.github.paolorotolo.expandableheightlistview.ExpandableHeightListView>
</RelativeLayout>
</RelativeLayout>
</ScrollView>
ЭТО ПОСЛЕ ЗАМЕНЫ МОЕГО СПИСКА С ОДИН ИЗ МНОГИХ РЕШЕНИЙ, О КОТОРЫХ ПРОИСШЕСТВУЕТ ВЫШЕ Таким образом, проблема заключалась в том, что просмотр списка не работал должным образом из-за ошибки 2 scrollview (может быть, не ошибка) в Android.
Я заменил представление с переработчиком, чтобы сформировать мой окончательный макет.
Это мой видоискатель:
public class TrailerAdapter extends RecyclerView.Adapter<TrailerAdapter.TrailerAdapterViewHolder> {
private ArrayList<String> Youtube_URLS;
private Context Context;
public TrailerAdapter(Context context, ArrayList<String> Youtube_URLS){
this.Context = context;
this.Youtube_URLS = Youtube_URLS;
}
@Override
public TrailerAdapter.TrailerAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.trailer_layout, parent, false);
return new TrailerAdapterViewHolder(view);
}
@Override
public void onBindViewHolder(TrailerAdapter.TrailerAdapterViewHolder holder, int position) {
Picasso.with(Context).load(R.drawable.ic_play_arrow_black_24dp).into(holder.iv_playbutton);
holder.item_id.setText(Youtube_URLS.get(position));
}
@Override
public int getItemCount() {
if(Youtube_URLS.size()==0){
return 0;
}else{
return Youtube_URLS.size();
}
}
public class TrailerAdapterViewHolder extends RecyclerView.ViewHolder {
ImageView iv_playbutton;
TextView item_id;
public TrailerAdapterViewHolder(View itemView) {
super(itemView);
iv_playbutton = (ImageView)itemView.findViewById(R.id.play_button);
item_id = (TextView)itemView.findViewById(R.id.tv_trailer_sequence);
}
}
}
И это мой собственный макет RecyclerView:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="56dp"
android:padding="6dip" >
<ImageView
android:id="@+id/play_button"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_marginRight="6dip"
android:layout_marginStart="12dp"
android:src="@drawable/ic_play_arrow_black_24dp"
android:layout_centerVertical="true"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/tv_trailer_sequence"
android:layout_width="wrap_content"
android:layout_height="26dip"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/play_button"
android:ellipsize="marquee"
android:gravity="center"
android:maxLines="1"
android:text="Description"
android:textSize="12sp" />
</RelativeLayout>
И VOILA, я получил желаемый эффект ListView(теперь RecyclerView) в scollview. Вот окончательное изображение пользовательского интерфейса
В заключение отметим, что я считаю, что замена RecyclerView была для меня лучшим выбором, так как это улучшило общую стабильность приложения, а также помогло мне лучше понять RecyclerView. Если бы я предложил решение, я бы сказал, замените ваш ListView на RecyclerView.
Demo_ListView_In_ScrollView
==============================
package com.app.custom_seekbar;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
public class Demo_ListView_In_ScrollView extends Activity
{
ListView listview;
ArrayList<String> data=null;
listview_adapter adapter=null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
super.setContentView(R.layout.demo_listview_in_scrollview_activity);
init();
set_data();
set_adapter();
}
public void init()
{
listview=(ListView)findViewById(R.id.listView1);
data=new ArrayList<String>();
}
public void set_data()
{
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
}
public void set_adapter()
{
adapter=new listview_adapter(Demo_ListView_In_ScrollView.this,data);
listview.setAdapter(adapter);
Helper.getListViewSize(listview); // set height of listview according to Arraylist item
}
}
========================
listview_adapter
==========================
package com.app.custom_seekbar;
import java.util.ArrayList;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
public class listview_adapter extends ArrayAdapter<String>
{
private final Activity context;
ArrayList<String>data;
class ViewHolder
{
public TextView tv_name;
public ScrollView scroll;
public LinearLayout l1;
}
public listview_adapter(Activity context, ArrayList<String> all_data) {
super(context, R.layout.item_list_xml, all_data);
this.context = context;
data=all_data;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
ViewHolder viewHolder;
if (rowView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.item_list_xml, null);
viewHolder = new ViewHolder();
viewHolder.tv_name=(TextView)rowView.findViewById(R.id.textView1);
rowView.setTag(viewHolder);
}
else
viewHolder = (ViewHolder) rowView.getTag();
viewHolder.tv_name.setText(data.get(position).toString());
return rowView;
}
}
===================================
Хелпер класс
====================================
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
public class Helper {
public static void getListViewSize(ListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
//do nothing return null
return;
}
//set listAdapter in loop for getting final size
int totalHeight = 0;
for (int size = 0; size < myListAdapter.getCount(); size++) {
View listItem = myListAdapter.getView(size, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
//setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
params.height = totalHeight + (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
Log.i("height of listItem:", String.valueOf(totalHeight));
}
}
========================
demo_listview_in_scrollview_activity.xml
========================
<?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:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
</ScrollView>
</LinearLayout>
================
item_list_xml.xml
==================
<?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" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="TextView"
android:textSize="14sp" />
</LinearLayout>
Вот лучший пример
Добавить NestedScrollView вместо Scrollview
Добавьте эту строку в ListView
android:nestedScrollingEnabled="true"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"
/>
</androidx.core.widget.NestedScrollView>
Лучшее решение - использовать NestedScrollVew с RecyclerView или, если вы хотите использовать Listview, вы можете добавить к этому представление верхнего и нижнего колонтитула. Например:
View footerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.outofoffice_footer_view, null, false);
infoListView.addFooterView(footerView);
Лучший код
<android.support.v4.widget.NestedScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/btmlyt"
android:layout_below="@+id/deshead_tv">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/des_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btmlyt"
android:background="@android:color/white"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:scrollbars="vertical"
android:paddingTop="3dp"
android:text="description"
android:textColor="@android:color/black"
android:textSize="18sp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
requestDisallowInterceptTouchEvent (логическое значение disallowIntercept)
Вызывается, когда дочерний элемент не хочет, чтобы этот родитель и его предки перехватывали события касания с помощью onInterceptTouchEvent(MotionEvent). Этот родитель должен передать этот вызов своим родителям. Этот родитель должен выполнять этот запрос в течение всего времени касания (то есть, снимать флажок только после того, как этот родитель получил up или отмену.
Попробуйте этот ответ,
listview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
scrollView.requestDisallowInterceptTouchEvent(true);
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
scrollView.requestDisallowInterceptTouchEvent(false);
break;
}
return false;
}
});
У меня была эта ошибка. И мое решение выглядит следующим образом:
1. Создайте собственный вид списка, который нельзя прокручивать
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();
}
}
2. Используйте вышеуказанный пользовательский класс для XML-файла
<com.Example.NonScrollListView
android:id="@+id/lv_nonscroll_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.Example.NonScrollListView>
Надеюсь, что лучше для вас.
Замените ScrollView на android.support.v4.widget.NestedScrollView внутри xml. это работает
1) Использование в XML:::: android.support.v4.widget.NestedScrollView
вместо:::: ScrollView
2) И использовать для представления списка таким образом, используя NonScrollListView в файле CS:
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();
}
}
3) Наконец, используйте этот код для идентификации scrollview в файле cs:
NonScrollListView listView = (NonScrollListView) view.findViewById(R.id.listview);
Попробуйте это с ScrollView, а не с ListView.
public class xScrollView extends ScrollView
{
;
;
@Override
public boolean onInterceptTouchEvent (MotionEvent ev)
{
return false;
}
}
Замените ListView на RecycleView внутри ScrollView. он работает без дополнительного исходного кода:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.hung.recycleviewtest.MainActivityFragment"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="@android:color/darker_gray"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle_view_a"
android:layout_marginTop="40dp"
android:layout_below="@id/recycle_view"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="@android:color/darker_gray"/>
</RelativeLayout>
</ScrollView>
Как по мне, пока вы используете setOnTouchListener om parent или child, остановите прокрутку родительского элемента, когда вы касаетесь дочернего элемента, иначе прекратите прокрутку дочернего элемента, когда вы касаетесь родительского элемента.
Для ListView внутри ScrollView используйте NestedScrollView, он может очень легко справиться с этой функциональностью:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dip"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
Я нашел решение для этого,вместо использования scrollview, вы можете использовать addHeaderview и addFooterview listview
Вот мой фрагмент,
// create separate layout and add it dynamically
scrollview=getLayoutInflater().inflate(R.layout.yourlayout,null);
lv=(ListView)listview.findViewById(R.id.listView2);
lv.addHeaderView(scrollview);
lv.setContentView(lv);
Теперь при просмотре списка ваш макет также можно прокручивать. Наслаждайся этим!!!
Не показывать прокрутку ListView
Потому что у него есть эта настройка по умолчанию
<ListView
android:cacheColorHint="#00000000"
android:id="@+id/ListView01"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
Вы не можете добавить ListView в представление с прокруткой, так как представление списка также прокручивается, и возникает проблема синхронизации между прокруткой просмотра списка и прокруткой просмотра прокрутки. Вы можете создать представление CustomList и добавить в него этот метод.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* Prevent parent controls from stealing our events once we've gotten a touch down
*/
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
ViewParent p = getParent();
if (p != null) {
p.requestDisallowInterceptTouchEvent(true);
}
}
return false;
}
Используйте этот метод, и ваш просмотр списка станет прокручиваемым внутри прокрутки:-
ListView lstNewsOffer.setAdapter(new ViewOfferAdapter(
ViewNewsDetail.this, viewOfferList));
getListViewSize(lstNewsOffer);
void getListViewSize(ListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
// do nothing return null
return;
}
// set listAdapter in loop for getting final size
int totalHeight = 0;
for (int size = 0; size < myListAdapter.getCount(); size++) {
View listItem = myListAdapter.getView(size, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
// setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
params.height = totalHeight
+ (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
Log.i("height of listItem:", String.valueOf(totalHeight));
}