【问题标题】:Unable to Put ViewPager inside a ScrollVIew/NestedScrollView无法将 ViewPager 放入 ScrollVIew/NestedScrollView
【发布时间】:2017-09-10 06:46:58
【问题描述】:

我有一个 ViewPager,它位于父线性布局内,在 ViewPager 下方有一些按钮。 ViewPager 一直运行良好,直到最近我将父级从 LinearLayout 更改为 ScrollView。现在 ViewPager 消失了。请不要将其标记为垃圾邮件或重复。

此外,Playstore 上有大量应用目前正在使用此功能。看到这个应用程序 - link

我尝试了什么:

  1. setFillViewport (true) - 这对我不起作用。
  2. 将 layout_height 设置为 0dp
  3. 使用 CustomScrollView

所有这些都对我没有帮助。我在 Android M 上运行该应用程序。

这是我的 layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1"
android:overScrollMode="never"/>

<RelativeLayout
android:layout_weight="0.8"
android:layout_marginTop="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
.....two buttons
</RelativeLayout>

</LinearLayout>

</android.support.v4.widget.NestedScrollView>

问题:

我怎样才能做到这一点?另外,有官方的方法吗?

【问题讨论】:

  • 将你的嵌套滚动视图放在父布局中,例如:coordinatorLayout
  • 这也无济于事
  • 发布完整的 xml..
  • 添加了完整的 layout.xml

标签: android android-layout android-viewpager scrollview


【解决方案1】:

我通过修复 ViewPager 的高度解决了这个问题:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="top"/>

...

</LinearLayout>

</android.support.v4.widget.NestedScrollView>

【讨论】:

    【解决方案2】:

    最好使用 recyclerView 并将 Viewpager 添加为适配器内的子项。您需要拦截 recyclerview 的触摸以将滚动交给 ViewPager。

    public class TouchInterceptRecyclerView extends RecyclerView {
    
        private boolean interceptTouch = true;
        private static final int MIN_DISTANCE = 200;
        private float downX = 0, downY = 0, moveX = 0, moveY = 0, upX = 0, upY;
    
        public TouchInterceptRecyclerView(Context context) {
            super(context);
        }
    
        public TouchInterceptRecyclerView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (getRvTop() == 0) {
                onTouchEvent(ev);
            }
            return interceptTouch;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downX = event.getX();
                    downY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    moveX = event.getX();
                    moveY = event.getY();
                    break;
                case MotionEvent.ACTION_UP:
                    upX = event.getX();
                    upY = event.getY();
                    break;
            }
            float deltaX = upX - downX;
    
            if (getViewTop() == 0 && moveY > downY && Math.abs(moveY - downY) > MIN_DISTANCE) {  // moving down
                interceptTouch = true;
            }else if (Math.abs(deltaX) > MIN_DISTANCE) {
                if (upX > downX) {    // Left to Right swipe action
                    interceptTouch = false;
                }else {    // Right to left swipe action
                    interceptTouch = false;
                }
            } else {  // screen tap
                interceptTouch = false;
            }
            return super.onTouchEvent(event);
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            return super.dispatchTouchEvent(ev);
        }
    
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
        }
    
        @Override
        public void onScrolled(int dx, int dy) {
            if (getViewTop() <= 0) {
                interceptTouch = false;            // dispatch the touch to child when reached top
            } else {
                interceptTouch = true;           // do not dispatch the touch event
            }
            super.onScrolled(dx, dy);
        }
    
        public int getViewTop() {
            int top = 0;
            View v = this.getChildAt(1);
            if (v == null) {
                v = this.getChildAt(0);
            }
            if (v != null && v instanceof LinearLayout) {
                top = v.getTop();
            }
            return top;
        }
    
        public int getRvTop() {
            int top = -1;
            View v = this.getChildAt(1);
            if (v == null) {
                v = this.getChildAt(0);
            }
            if (v != null && v instanceof LinearLayout) {
    
                ViewPager vp = (ViewPager) v.findViewById(R.id.single_pager);
                if (vp != null) {
                    int currentPos = vp.getCurrentItem();
                    RecyclerView rv = (RecyclerView) vp.findViewWithTag("recyclerview" + currentPos);
                    if (rv != null) {
                        View v1 = rv.getChildAt(0);
                        if (v1 != null && v1 instanceof CardView) {
                            top = v1.getTop() - ResourceUtils.getDimensionPixelOffset(R.dimen.padding_20);   // deducting 20 as we have give top margin as 20 to the top layout
                        }
                    }
                }
            }
            return top;
        }
    }
    

    在 RecyclerView 的适配器中,您可以像这样添加 ViewPager:

    @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            RecyclerView.ViewHolder viewHolder = null;
            View view;
            switch (viewType) {
                case TYPE_VIEW_PAGER:
                    view = LayoutInflater.from(context).inflate(R.layout.pager, parent, false);
                    viewHolder = new ViewPagerAdapter(context, view);
                    break;
            }
            return viewHolder;
        }
    

    【讨论】:

    • 感谢 Harsh 抽出时间来回答。也许我可以使用 Recycler 视图并完成工作,但 RecyclerView 和 ScrollView 之间存在概念上的差异。我想知道有没有办法可以同时使用 ScrollView 和 ViewPager?
    • 是的,您可以使用滚动视图,就像您需要同时处理两者的触摸一样。
    猜你喜欢
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    相关资源
    最近更新 更多