带有 RecyclerView 的 Android ViewPager 在 BottomSheet 中无法正常工作 [英] Android ViewPager with RecyclerView works incorrectly inside BottomSheet
问题描述
当我尝试滚动列表时,有时这不正确 - BottomSheet 拦截滚动事件并隐藏.
如何重现这个:
- 打开底部工作表
- 更改ViewPager的页面
- 尝试滚动列表
结果:BottomSheet 将被隐藏.
这是示例代码:
编译'com.android.support:design:23.4.0'
MainActivity.java
package com.nkdroid.bottomsheetsample;导入 android.os.Bundle;导入 android.support.design.widget.BottomSheetBehavior;导入 android.support.design.widget.TabLayout;导入 android.support.v4.view.PagerAdapter;导入 android.support.v4.view.ViewPager;导入 android.support.v7.app.AppCompatActivity;导入 android.support.v7.widget.LinearLayoutManager;导入 android.support.v7.widget.RecyclerView;导入 android.view.View;导入 android.view.ViewGroup;导入 android.widget.Button;导入 android.widget.TextView;上市类 MainActivity扩展 AppCompatActivity{私有BottomSheetBehavior行为;@覆盖受保护void onCreate(final Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);最终按钮 btnView = (按钮) findViewById(R.id.btnView);btnView.setOnClickListener(new View.OnClickListener(){@覆盖上市void onClick(final View v) {行为.setState(BottomSheetBehavior.STATE_EXPANDED);}});最终视图bottomSheet = findViewById(R.id.bottom_sheet);行为 = BottomSheetBehavior.from(bottomSheet);final ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);viewPager.setAdapter(new MyPagerAdapter());最终 TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);tabLayout.setupWithViewPager(viewPager);}私人的类 MyPagerAdapter扩展 PagerAdapter{@覆盖上市int getCount() {返回 15;}@覆盖上市对象实例化项目(最终的 ViewGroup 容器,最终的 int 位置){final RecyclerView recyclerView = new RecyclerView(MainActivity.this);recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));recyclerView.setAdapter(new ItemAdapter());container.addView(recyclerView);返回回收者视图;}@覆盖上市boolean isViewFromObject(最终视图视图,最终对象对象){返回 view.equals(object);}@覆盖上市void destroyItem(最终的 ViewGroup 容器,最终的 int 位置,最终的 Object 对象){container.removeView((View) 对象);}@覆盖上市CharSequence getPageTitle(最终 int 位置){返回 String.valueOf(position);}}上市类 ItemAdapter扩展 RecyclerView.Adapter{@覆盖上市ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {返回新的 ViewHolder(new TextView(MainActivity.this));}@覆盖上市void onBindViewHolder(最终的 ViewHolder 持有者,最终的 int 位置){}@覆盖上市int getItemCount() {返回 100;}上市类 ViewHolder扩展 RecyclerView.ViewHolder{公共文本视图文本视图;上市ViewHolder(最终视图 itemView){超级(项目视图);textView = (TextView) itemView;}}}}
activity_main.xml
任何解决方法的想法?
我遇到了同样的限制,但能够解决它.
你描述的效果的原因是BottomSheetBehavior
(从v24.2.0开始)只支持一个滚动子,在布局过程中通过以下方式识别:
私有视图 findScrollingChild(View view) {如果(查看 NestedScrollingChild 的实例){返回视图;}如果(查看 ViewGroup 的实例){ViewGroup 组 = (ViewGroup) 视图;for (int i = 0, count = group.getChildCount(); i < count; i++) {查看 scrollingChild = findScrollingChild(group.getChildAt(i));如果(scrollingChild != null){返回滚动子;}}}返回空;}
你可以看到它本质上是使用 DFS 找到第一个滚动的孩子.
我稍微增强了这个实现并组装了一个小型库以及一个示例应用程序.你可以在这里找到它:
When I try to scroll list, sometimes this works incorrect - BottomSheet intercepts the scroll event and hides.
How to reproduce this:
- Open Bottom Sheet
- Change a page of ViewPager
- Try scroll the list
Result: BottomSheet will be hidden.
Here is sample code:
compile 'com.android.support:design:23.4.0'
MainActivity.java
package com.nkdroid.bottomsheetsample;
import android.os.Bundle;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.TabLayout;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public
class MainActivity
extends AppCompatActivity
{
private BottomSheetBehavior behavior;
@Override
protected
void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button btnView = (Button) findViewById(R.id.btnView);
btnView.setOnClickListener(new View.OnClickListener()
{
@Override
public
void onClick(final View v) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
final View bottomSheet = findViewById(R.id.bottom_sheet);
behavior = BottomSheetBehavior.from(bottomSheet);
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new MyPagerAdapter());
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private
class MyPagerAdapter
extends PagerAdapter
{
@Override
public
int getCount() {
return 15;
}
@Override
public
Object instantiateItem(final ViewGroup container, final int position) {
final RecyclerView recyclerView = new RecyclerView(MainActivity.this);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
recyclerView.setAdapter(new ItemAdapter());
container.addView(recyclerView);
return recyclerView;
}
@Override
public
boolean isViewFromObject(final View view, final Object object) {
return view.equals(object);
}
@Override
public
void destroyItem(final ViewGroup container, final int position, final Object object) {
container.removeView((View) object);
}
@Override
public
CharSequence getPageTitle(final int position) {
return String.valueOf(position);
}
}
public
class ItemAdapter
extends RecyclerView.Adapter<ItemAdapter.ViewHolder>
{
@Override
public
ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
return new ViewHolder(new TextView(MainActivity.this));
}
@Override
public
void onBindViewHolder(final ViewHolder holder, final int position) {
}
@Override
public
int getItemCount() {
return 100;
}
public
class ViewHolder
extends RecyclerView.ViewHolder
{
public TextView textView;
public
ViewHolder(final View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout android:id = "@+id/coordinatorLayout"
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:layout_width = "match_parent"
android:layout_height = "match_parent"
android:background = "#a3b1ef"
android:fitsSystemWindows = "true"
tools:context = ".ui.MainActivity"
>
<Button
android:id = "@+id/btnView"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:text = "Show view"
app:layout_behavior = "@string/appbar_scrolling_view_behavior"
/>
<LinearLayout
android:id = "@+id/bottom_sheet"
android:layout_width = "match_parent"
android:layout_height = "400dp"
android:background = "#fff"
android:gravity = "center"
android:orientation = "vertical"
app:layout_behavior = "@string/bottom_sheet_behavior"
>
<android.support.design.widget.TabLayout
android:id = "@+id/tabs"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
app:tabMode = "scrollable"
/>
<android.support.v4.view.ViewPager
android:id = "@+id/viewPager"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
Any ideas for a workaround?
I came across the same limitation but were able to solve it.
The reason for the effect you described is that BottomSheetBehavior
(as of v24.2.0) only supports one scrolling child which is identified during layout in the following way:
private View findScrollingChild(View view) {
if (view instanceof NestedScrollingChild) {
return view;
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0, count = group.getChildCount(); i < count; i++) {
View scrollingChild = findScrollingChild(group.getChildAt(i));
if (scrollingChild != null) {
return scrollingChild;
}
}
}
return null;
}
You can see that it essentially finds the first scrolling child using DFS.
I slightly enhanced this implementation and assembled a small library as well as an example app. You can find it here: https://github.com/laenger/ViewPagerBottomSheet
Simply add the maven repo url to your build.gradle:
repositories {
maven { url "https://raw.github.com/laenger/maven-releases/master/releases" }
}
Add the library to the dependencies:
dependencies {
compile "biz.laenger.android:vpbs:0.0.2"
}
Use ViewPagerBottomSheetBehavior
for your bottom sheet view:
app:layout_behavior="@string/view_pager_bottom_sheet_behavior"
Setup any nested ViewPager inside the bottom sheet:
BottomSheetUtils.setupViewPager(bottomSheetViewPager)
(This also works when the ViewPager is the bottom sheet view and for further nested ViewPagers)
这篇关于带有 RecyclerView 的 Android ViewPager 在 BottomSheet 中无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!