带有 RecyclerView 的 Android ViewPager 在 BottomSheet 中无法正常工作 [英] Android ViewPager with RecyclerView works incorrectly inside BottomSheet

查看:19
本文介绍了带有 RecyclerView 的 Android ViewPager 在 BottomSheet 中无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试滚动列表时,有时这不正确 - BottomSheet 拦截滚动事件并隐藏.

如何重现这个:

  1. 打开底部工作表
  2. 更改ViewPager的页面
  3. 尝试滚动列表

结果: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:

  1. Open Bottom Sheet
  2. Change a page of ViewPager
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆