NestedScrollView 内的 Recycler 视图导致滚动从中间开始
Recycler view inside NestedScrollView causes scroll to start in the middle
当我在 NestedScrollView 中添加 RecyclerView 时,出现奇怪的滚动行为。
发生的情况是,只要滚动视图的行数多于屏幕上可以显示的行数,一旦 activity 启动,NestedScrollView 就会从顶部开始偏移(图 1)。如果滚动视图中的项目很少,因此可以一次显示所有项目,则不会发生这种情况(图 2)。
我正在使用支持库的 23.2.0 版。
图片 1:错误 - 从顶部偏移开始
图 2:正确 - 回收站视图中的项目很少
我粘贴在我的布局代码下面:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title:"
style="@style/TextAppearance.AppCompat.Caption"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
style="@style/TextAppearance.AppCompat.Body1"
android:text="Neque porro quisquam est qui dolorem ipsum"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Subtitle:"
style="@style/TextAppearance.AppCompat.Caption"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Body1"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
我错过了什么吗?有人知道如何解决这个问题吗?
更新 1
如果我在初始化 Activity 时放置以下代码,它会正常工作:
sv.post(new Runnable() {
@Override
public void run() {
sv.scrollTo(0,0);
}
});
其中 sv 是对 NestedScrollView 的引用,但它看起来很乱。
更新 2
根据要求,这是我的适配器代码:
public abstract class ArrayAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
private List<T> mObjects;
public ArrayAdapter(final List<T> objects) {
mObjects = objects;
}
/**
* Adds the specified object at the end of the array.
*
* @param object The object to add at the end of the array.
*/
public void add(final T object) {
mObjects.add(object);
notifyItemInserted(getItemCount() - 1);
}
/**
* Remove all elements from the list.
*/
public void clear() {
final int size = getItemCount();
mObjects.clear();
notifyItemRangeRemoved(0, size);
}
@Override
public int getItemCount() {
return mObjects.size();
}
public T getItem(final int position) {
return mObjects.get(position);
}
public long getItemId(final int position) {
return position;
}
/**
* Returns the position of the specified item in the array.
*
* @param item The item to retrieve the position of.
* @return The position of the specified item.
*/
public int getPosition(final T item) {
return mObjects.indexOf(item);
}
/**
* Inserts the specified object at the specified index in the array.
*
* @param object The object to insert into the array.
* @param index The index at which the object must be inserted.
*/
public void insert(final T object, int index) {
mObjects.add(index, object);
notifyItemInserted(index);
}
/**
* Removes the specified object from the array.
*
* @param object The object to remove.
*/
public void remove(T object) {
final int position = getPosition(object);
mObjects.remove(object);
notifyItemRemoved(position);
}
/**
* Sorts the content of this adapter using the specified comparator.
*
* @param comparator The comparator used to sort the objects contained in this adapter.
*/
public void sort(Comparator<? super T> comparator) {
Collections.sort(mObjects, comparator);
notifyItemRangeChanged(0, getItemCount());
}
}
这是我的 ViewHolder:
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView txt;
public ViewHolder(View itemView) {
super(itemView);
txt = (TextView) itemView;
}
public void render(String text) {
txt.setText(text);
}
}
这里是 RecyclerView 中每个项目的布局(只是 android.R.layout.simple_spinner_item
- 此屏幕仅用于显示此错误的示例):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="inherit"/>
我有两个猜测。
首先:尝试将此行放在 NestedScrollView 上
app:layout_behavior="@string/appbar_scrolling_view_behavior"
第二:
使用
<android.support.design.widget.CoordinatorLayout
作为您的父视图
像这样
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title:"/>
<TextView
style="@style/TextAppearance.AppCompat.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum"/>
<TextView
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Subtitle:"/>
<TextView
style="@style/TextAppearance.AppCompat.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
我最后一个可能的解决方案。我发誓:)
在 Java 代码中,初始化您的 recyclerView 并设置适配器后,添加此行:
recyclerView.setNestedScrollingEnabled(false)
您也可以尝试使用 relativeLayout 包装布局,以便视图保持在相同位置,但 recyclerView(滚动)在 xml 层次结构中排在第一位。最后一个绝望的建议attempt:p
我遇到了同样的问题,并通过扩展 NestedScrollView 和禁用聚焦儿童来解决。出于某种原因,即使我刚刚打开和关闭抽屉,RecyclerView 也总是请求焦点。
public class DummyNestedScrollView extends NestedScrollView {
public DummyNestedScrollView(Context context) {
super(context);
}
public DummyNestedScrollView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public DummyNestedScrollView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Fixind problem with recyclerView in nested scrollview requesting focus
*
* @param child
* @param focused
*/
@Override
public void requestChildFocus(View child, View focused) {
Log.d(getClass().getSimpleName(), "Request focus");
//super.requestChildFocus(child, focused);
}
/**
*
* @param direction
* @param previouslyFocusedRect
* @return
*/
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
Log.d(getClass().getSimpleName(), "Request focus descendants");
//return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
return false;
}
}
我通过设置解决了这个问题:
<ImageView ...
android:focusableInTouchMode="true"/>
我在 RecyclerView 上方的视图(在不需要的滚动后被隐藏)。尝试将此 属性 设置为 RecyclerView 上方的 LinearLayout 或 RecyclerView 的容器 LinearLayout(在另一种情况下帮助了我)。
正如我在 NestedScrollView 源代码中看到的那样,它试图将第一个可能的 child 集中在 onRequestFocusInDescendants 中,如果只有 RecyclerView 是可聚焦的,它就会获胜。
编辑(感谢 Waran):为了平滑滚动,不要忘记设置 yourRecyclerView.setNestedScrollingEnabled(false);
在 NestedScrollView
之后的 LinearLayout
中,按以下方式使用 android:descendantFocusability
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"
android:descendantFocusability="blocksDescendants">
编辑
由于他们中的许多人认为此答案有用,因此还将提供解释。
使用descendantFocusability
给出here. And as of focusableInTouchMode
over here。
因此在 descendantFocusability
中使用 blocksDescendants
不允许它 child 在触摸时获得焦点,因此可以停止计划外的行为。
至于focusInTouchMode
,AbsListView
和RecyclerView
都默认在它们的构造函数中调用方法setFocusableInTouchMode(true);
,因此不需要在您的XML 布局。
并且对于 NestedScrollView
使用以下方法:
private void initScrollView() {
mScroller = ScrollerCompat.create(getContext(), null);
setFocusable(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setWillNotDraw(false);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
这里用setFocusable()
的方式代替了setFocusableInTouchMode()
的方式。但是根据这个 post,应该避免 focusableInTouchMode
除非在某些情况下,因为它破坏了与 Android 正常行为的一致性。游戏是一个很好的应用程序示例,可以很好地利用触摸模式下的可聚焦 属性。 MapView,如果像在 Google 地图中那样全屏使用,是另一个可以在触摸模式下正确使用可聚焦的好例子。
由于我回复晚了,但也许可以帮助到其他人。
只需在您的应用级别 build.gradle 中使用以下或更高版本即可解决问题。
compile com.android.support:recyclerview-v7:23.2.1
滚动到顶部,只需在 setcontentview
:
中调用
scrollView.SmoothScrollTo(0, 0);
android:descendantFocusability="blocksDescendants"
在 LinearLayout 内部为我工作。
在我的例子中,这段代码解决了我的问题
RecyclerView recyclerView = findViewById(R.id.recyclerView);
NestedScrollView nestedScrollView= findViewById(R.id.nestedScrollView);
recyclerView.setFocusable(false);
nestedScrollView.requestFocus();
//populate recyclerview here
我的布局包含一个 parent 布局作为 NestedScrollView,它有一个 child LinearLayout。 LinearLayout 的方向为 "vertical" 和 childs RecyclerView 和 EditText。
这个问题是由于回收视图焦点。
如果其尺寸扩展了屏幕尺寸,所有焦点将自动转到回收视图。
将 android:focusableInTouchMode="true"
添加到第一个 ChildView,如 TextView
、Button
等(而不是在 ViewGroup
上,如 Linear
、Relative
和依此类推)对解决问题有意义,但 API 25 级及以上的解决方案不起作用。
只需在您的 ChildView 中添加这两行,如 TextView
、Button
等(而不是在 ViewGroup
中,如 Linear
、Relative
等上)
android:focusableInTouchMode="true"
android:focusable="true"
我刚刚在 API 25 级遇到这个问题。我希望其他人不要在这上面浪费时间。
为了在 RecycleView 上平滑滚动添加这一行
android:nestedScrollingEnabled="false"
但添加此属性仅适用于 API 21 级或以上。如果您希望在 API 级别 25 以下进行平滑滚动,请将此行添加到您的 class
mList = findViewById(R.id.recycle_list);
ViewCompat.setNestedScrollingEnabled(mList, false);
只需在 NestedScrollView 内的 ViewGroup 上添加 android:descendantFocusability="blocksDescendants"
。
请不要使用
android:descendantFocusability="blocksDescendants"
因为 ViewGroup 会阻止其后代获得焦点。这是一个可访问性问题。
如果您想避免 nestedscrollview
获得焦点,您可以在 nestedscrollview
上方添加一个可聚焦的虚拟布局。
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:focusable="true"
android:focusableInTouchMode="true" />
在我的例子中,由于我在父线性布局中添加了 android:layout_gravity="center",因此滚动并聚焦到 recyclerview。
删除后可以正常使用。
当我在 NestedScrollView 中添加 RecyclerView 时,出现奇怪的滚动行为。
发生的情况是,只要滚动视图的行数多于屏幕上可以显示的行数,一旦 activity 启动,NestedScrollView 就会从顶部开始偏移(图 1)。如果滚动视图中的项目很少,因此可以一次显示所有项目,则不会发生这种情况(图 2)。
我正在使用支持库的 23.2.0 版。
图片 1:错误 - 从顶部偏移开始
图 2:正确 - 回收站视图中的项目很少
我粘贴在我的布局代码下面:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title:"
style="@style/TextAppearance.AppCompat.Caption"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
style="@style/TextAppearance.AppCompat.Body1"
android:text="Neque porro quisquam est qui dolorem ipsum"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Subtitle:"
style="@style/TextAppearance.AppCompat.Caption"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Body1"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
我错过了什么吗?有人知道如何解决这个问题吗?
更新 1
如果我在初始化 Activity 时放置以下代码,它会正常工作:
sv.post(new Runnable() {
@Override
public void run() {
sv.scrollTo(0,0);
}
});
其中 sv 是对 NestedScrollView 的引用,但它看起来很乱。
更新 2
根据要求,这是我的适配器代码:
public abstract class ArrayAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
private List<T> mObjects;
public ArrayAdapter(final List<T> objects) {
mObjects = objects;
}
/**
* Adds the specified object at the end of the array.
*
* @param object The object to add at the end of the array.
*/
public void add(final T object) {
mObjects.add(object);
notifyItemInserted(getItemCount() - 1);
}
/**
* Remove all elements from the list.
*/
public void clear() {
final int size = getItemCount();
mObjects.clear();
notifyItemRangeRemoved(0, size);
}
@Override
public int getItemCount() {
return mObjects.size();
}
public T getItem(final int position) {
return mObjects.get(position);
}
public long getItemId(final int position) {
return position;
}
/**
* Returns the position of the specified item in the array.
*
* @param item The item to retrieve the position of.
* @return The position of the specified item.
*/
public int getPosition(final T item) {
return mObjects.indexOf(item);
}
/**
* Inserts the specified object at the specified index in the array.
*
* @param object The object to insert into the array.
* @param index The index at which the object must be inserted.
*/
public void insert(final T object, int index) {
mObjects.add(index, object);
notifyItemInserted(index);
}
/**
* Removes the specified object from the array.
*
* @param object The object to remove.
*/
public void remove(T object) {
final int position = getPosition(object);
mObjects.remove(object);
notifyItemRemoved(position);
}
/**
* Sorts the content of this adapter using the specified comparator.
*
* @param comparator The comparator used to sort the objects contained in this adapter.
*/
public void sort(Comparator<? super T> comparator) {
Collections.sort(mObjects, comparator);
notifyItemRangeChanged(0, getItemCount());
}
}
这是我的 ViewHolder:
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView txt;
public ViewHolder(View itemView) {
super(itemView);
txt = (TextView) itemView;
}
public void render(String text) {
txt.setText(text);
}
}
这里是 RecyclerView 中每个项目的布局(只是 android.R.layout.simple_spinner_item
- 此屏幕仅用于显示此错误的示例):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="inherit"/>
我有两个猜测。
首先:尝试将此行放在 NestedScrollView 上
app:layout_behavior="@string/appbar_scrolling_view_behavior"
第二: 使用
<android.support.design.widget.CoordinatorLayout
作为您的父视图 像这样
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title:"/>
<TextView
style="@style/TextAppearance.AppCompat.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum"/>
<TextView
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Subtitle:"/>
<TextView
style="@style/TextAppearance.AppCompat.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
我最后一个可能的解决方案。我发誓:)
在 Java 代码中,初始化您的 recyclerView 并设置适配器后,添加此行:
recyclerView.setNestedScrollingEnabled(false)
您也可以尝试使用 relativeLayout 包装布局,以便视图保持在相同位置,但 recyclerView(滚动)在 xml 层次结构中排在第一位。最后一个绝望的建议attempt:p
我遇到了同样的问题,并通过扩展 NestedScrollView 和禁用聚焦儿童来解决。出于某种原因,即使我刚刚打开和关闭抽屉,RecyclerView 也总是请求焦点。
public class DummyNestedScrollView extends NestedScrollView {
public DummyNestedScrollView(Context context) {
super(context);
}
public DummyNestedScrollView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public DummyNestedScrollView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Fixind problem with recyclerView in nested scrollview requesting focus
*
* @param child
* @param focused
*/
@Override
public void requestChildFocus(View child, View focused) {
Log.d(getClass().getSimpleName(), "Request focus");
//super.requestChildFocus(child, focused);
}
/**
*
* @param direction
* @param previouslyFocusedRect
* @return
*/
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
Log.d(getClass().getSimpleName(), "Request focus descendants");
//return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
return false;
}
}
我通过设置解决了这个问题:
<ImageView ...
android:focusableInTouchMode="true"/>
我在 RecyclerView 上方的视图(在不需要的滚动后被隐藏)。尝试将此 属性 设置为 RecyclerView 上方的 LinearLayout 或 RecyclerView 的容器 LinearLayout(在另一种情况下帮助了我)。
正如我在 NestedScrollView 源代码中看到的那样,它试图将第一个可能的 child 集中在 onRequestFocusInDescendants 中,如果只有 RecyclerView 是可聚焦的,它就会获胜。
编辑(感谢 Waran):为了平滑滚动,不要忘记设置 yourRecyclerView.setNestedScrollingEnabled(false);
在 NestedScrollView
之后的 LinearLayout
中,按以下方式使用 android:descendantFocusability
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"
android:descendantFocusability="blocksDescendants">
编辑
由于他们中的许多人认为此答案有用,因此还将提供解释。
使用descendantFocusability
给出here. And as of focusableInTouchMode
over here。
因此在 descendantFocusability
中使用 blocksDescendants
不允许它 child 在触摸时获得焦点,因此可以停止计划外的行为。
至于focusInTouchMode
,AbsListView
和RecyclerView
都默认在它们的构造函数中调用方法setFocusableInTouchMode(true);
,因此不需要在您的XML 布局。
并且对于 NestedScrollView
使用以下方法:
private void initScrollView() {
mScroller = ScrollerCompat.create(getContext(), null);
setFocusable(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setWillNotDraw(false);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
这里用setFocusable()
的方式代替了setFocusableInTouchMode()
的方式。但是根据这个 post,应该避免 focusableInTouchMode
除非在某些情况下,因为它破坏了与 Android 正常行为的一致性。游戏是一个很好的应用程序示例,可以很好地利用触摸模式下的可聚焦 属性。 MapView,如果像在 Google 地图中那样全屏使用,是另一个可以在触摸模式下正确使用可聚焦的好例子。
由于我回复晚了,但也许可以帮助到其他人。 只需在您的应用级别 build.gradle 中使用以下或更高版本即可解决问题。
compile com.android.support:recyclerview-v7:23.2.1
滚动到顶部,只需在 setcontentview
:
scrollView.SmoothScrollTo(0, 0);
android:descendantFocusability="blocksDescendants"
在 LinearLayout 内部为我工作。
在我的例子中,这段代码解决了我的问题
RecyclerView recyclerView = findViewById(R.id.recyclerView);
NestedScrollView nestedScrollView= findViewById(R.id.nestedScrollView);
recyclerView.setFocusable(false);
nestedScrollView.requestFocus();
//populate recyclerview here
我的布局包含一个 parent 布局作为 NestedScrollView,它有一个 child LinearLayout。 LinearLayout 的方向为 "vertical" 和 childs RecyclerView 和 EditText。
这个问题是由于回收视图焦点。
如果其尺寸扩展了屏幕尺寸,所有焦点将自动转到回收视图。
将 android:focusableInTouchMode="true"
添加到第一个 ChildView,如 TextView
、Button
等(而不是在 ViewGroup
上,如 Linear
、Relative
和依此类推)对解决问题有意义,但 API 25 级及以上的解决方案不起作用。
只需在您的 ChildView 中添加这两行,如 TextView
、Button
等(而不是在 ViewGroup
中,如 Linear
、Relative
等上)
android:focusableInTouchMode="true"
android:focusable="true"
我刚刚在 API 25 级遇到这个问题。我希望其他人不要在这上面浪费时间。
为了在 RecycleView 上平滑滚动添加这一行
android:nestedScrollingEnabled="false"
但添加此属性仅适用于 API 21 级或以上。如果您希望在 API 级别 25 以下进行平滑滚动,请将此行添加到您的 class
mList = findViewById(R.id.recycle_list);
ViewCompat.setNestedScrollingEnabled(mList, false);
只需在 NestedScrollView 内的 ViewGroup 上添加 android:descendantFocusability="blocksDescendants"
。
请不要使用
android:descendantFocusability="blocksDescendants"
因为 ViewGroup 会阻止其后代获得焦点。这是一个可访问性问题。
如果您想避免 nestedscrollview
获得焦点,您可以在 nestedscrollview
上方添加一个可聚焦的虚拟布局。
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:focusable="true"
android:focusableInTouchMode="true" />
在我的例子中,由于我在父线性布局中添加了 android:layout_gravity="center",因此滚动并聚焦到 recyclerview。 删除后可以正常使用。