Scroll doesn't work in NestedScrollView when t

2019-01-31 16:38发布

问题:

I'm using a NestedScrollView in a layout, and am attempting to use the new CoordinatorLayout from the design support library for CollapsingToolbarLayout.

My layout file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"

            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <!--            app:expandedTitleMarginEnd="64dp"-->
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:scaleType="centerCrop"
                android:src="@drawable/image_load_default_big" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/anim_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
            </android.support.v7.widget.Toolbar>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nestedScrollVw"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|enterAlways"
        android:fitsSystemWindows="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clickable="false"
            android:fitsSystemWindows="true">

            <LinearLayout
                android:id="@+id/changePasswordButtonContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <Button
                    android:id="@+id/changePasswordExpand"
                    android:layout_width="match_parent"
                    android:layout_height="55dp"
                    android:background="@drawable/back_img"
                    android:text="Change Your Password"
                    android:textColor="@color/white"
                    android:textStyle="bold" />
            </LinearLayout>


            <LinearLayout
                android:id="@+id/changePasswordContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/changePasswordButtonContainer"
                android:layout_centerInParent="true"
                android:orientation="vertical"
                android:padding="10dp">


                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:text="Edit Your Password"
                    android:textColor="@color/orange" />

                <EditText
                    android:id="@+id/etUserName"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:background="@drawable/edittext_default_bg"
                    android:drawableLeft="@drawable/password_icon"
                    android:drawableRight="@drawable/tick"
                    android:hint=" Old Password"
                    android:padding="12dp"
                    android:password="true"
                    android:textColorHint="#b5b5b5" />

                <EditText
                    android:id="@+id/etPass"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:background="@drawable/edittext_default_bg"
                    android:drawableLeft="@drawable/password_icon"
                    android:drawableRight="@drawable/cross"
                    android:hint=" New Password"
                    android:padding="12dp"
                    android:password="true"
                    android:textColorHint="#b5b5b5" />

                <RadioButton
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingBottom="20dp"
                    android:paddingTop="20dp"
                    android:text="show password" />

                <Button
                    android:id="@+id/btnSingIn"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="4dp"
                    android:background="@drawable/login_button_background"
                    android:paddingBottom="8dp"
                    android:paddingTop="8dp"
                    android:text="Done"
                    android:textColor="@color/white"
                    android:textStyle="bold" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/dealerToDealerContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/changePasswordContainer"
                android:orientation="vertical">

                <Button
                    android:id="@+id/dealerToDealerExpand"
                    android:layout_width="match_parent"
                    android:layout_height="55dp"
                    android:background="@drawable/back_img"
                    android:text="Dealer To Dealer Platform No"
                    android:textColor="@color/white"
                    android:textStyle="bold" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/dealerToDealerContainer"
                android:layout_centerInParent="true"
                android:orientation="vertical"
                android:padding="10dp">


                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:text="Edit Number"
                    android:textColor="@color/orange" />

                <EditText
                    android:id="@+id/dealerToDealerNo"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:background="@drawable/edittext_default_bg"
                    android:drawableLeft="@drawable/password_icon"
                    android:drawableRight="@drawable/tick"
                    android:hint=" 56546789"
                    android:padding="12dp"
                    android:password="true"
                    android:textColorHint="#b5b5b5" />

                <Button
                    android:id="@+id/dealerToDealerNoDone"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="4dp"
                    android:background="@drawable/login_button_background"
                    android:paddingBottom="8dp"
                    android:paddingTop="8dp"
                    android:text="Done"
                    android:textColor="@color/white"
                    android:textStyle="bold" />
            </LinearLayout>

        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

When i try to scroll, sometimes it doesn't work. reason for this is, other elements of layout with click events are consuming the touch event. Basically EditText, RadioButton, Button are consuming touch events. Any Suggestions to solve this problem ?

回答1:

I had the same problem. It happens only when NestedScrollView content height is less than height of device screen. So the workaround is to use setMinimumHeight(..) method for the view inside your NestedScrollView to make it resize to screen height:

DisplayMetrics displaymetrics = new DisplayMetrics();
getBaseActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenHeight = displaymetrics.heightPixels;

int actionBarHeight = 0;
TypedValue tv = new TypedValue();
if (getBaseActivity().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
    actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}

view.setMinimumHeight(screenHeight - actionBarHeight);

where view is your RelativeLayout

It works fine fore me. Hope it helps you



回答2:

One of your ScrollViews will send all events to the first View that answer true on dispatchMotionEvent.

You may avoid using such scenario in your app OR override all dispatchMotionEvent methods (from scrolls and Views) to not consume the ACTION_DOWN.



回答3:

In your AndroidManifest.xml, make sure you have 'windowSoftInputMode' attribute set to 'adjustResize'.

<activity android:name=".activities.YourActivity"  android:windowSoftInputMode="adjustResize">


回答4:

The solution here (a workaround for this google issue by overriding the nestedScrollview) https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2 worked like a charm!

Define FixAppBarLayoutBehavior.java

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package your.package;

import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

/**
 * Workaround AppBarLayout.Behavior for https://issuetracker.google.com/66996774
 *
 * See https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2 for
 * example usage.
 *
 * Change the package name as you wish.
 */
public class FixAppBarLayoutBehavior extends AppBarLayout.Behavior {

    public FixAppBarLayoutBehavior() {
        super();
    }

    public FixAppBarLayoutBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target,
            int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
                dxUnconsumed, dyUnconsumed, type);
        stopNestedScrollIfNeeded(dyUnconsumed, child, target, type);
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
            View target, int dx, int dy, int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
        stopNestedScrollIfNeeded(dy, child, target, type);
    }

    private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) {
        if (type == ViewCompat.TYPE_NON_TOUCH) {
            final int currOffset = getTopAndBottomOffset();
            if ((dy < 0 && currOffset == 0)
                    || (dy > 0 && currOffset == -child.getTotalScrollRange())) {
                ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
            }
        }
    }
}

Usage in java:

AppBarLayout abl = findViewById(R.id.app_bar);
((CoordinatorLayout.LayoutParams) abl.getLayoutParams()).setBehavior(new FixAppBarLayoutBehavior());

Usage in xml:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
            android:id="@+id/app_bar"
            android:layout_height="..."
            android:layout_width="..."
            app:layout_behavior="your.package.FixAppBarLayoutBehavior">

    </android.support.design.widget.AppBarLayout>

    <!-- Content -->

</android.support.design.widget.CoordinatorLayout>

This is provided in the post Click not working on RecyclerView in CoordinatorLayout when scrolling.