滚动NestedScrollView后,onClick方法无法正常工作

toi*_*idv 37 android android-layout android-design-library

我使用NestedScrollView和CoordinatorLayout为工具栏启用滚动动画(通过app:layout_scrollFlags ="scroll | enterAlways").

NestedScrollView包含LinearLayout作为根子项,我将2个TextViews放入LinearLayout以启用展开/折叠动画.一个设置为Visible,另一个设置为Gone.并通过LinearLayout的onClick事件切换可见性

通常,一切都按预期工作,但当我滚动NestedScrollView时,onClick事件无法正常工作.我需要在滚动后双击以获得展开/折叠动画

有没有人和我有同样的问题?请帮我

<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.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="98dp"
        android:paddingLeft="24dp"
        android:paddingRight="24dp">

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/detail_expense_reason_trim"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:singleLine="false"
            android:textColor="@color/add_new_expense_text_color" />

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/detail_expense_reason"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:singleLine="false"
            android:textColor="@color/add_new_expense_text_color"
            android:visibility="gone" />
    </LinearLayout>

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

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/detail_expense_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>
Run Code Online (Sandbox Code Playgroud)

 @InjectView(R.id.detail_expense_reason)
AppCompatTextView originalReason;

@InjectView(R.id.detail_expense_reason_trim)
AppCompatTextView trimReason;

@InjectView(R.id.detail_expense_container)
LinearLayout expenseContainer;
Run Code Online (Sandbox Code Playgroud)

//处理事件

public void onClick() {
    if (originalReason.getVisibility() == View.VISIBLE) {
        originalReason.setVisibility(View.GONE);
        trimReason.setVisibility(View.VISIBLE);
    } else {
        originalReason.setVisibility(View.VISIBLE);
        trimReason.setVisibility(View.GONE);
    }

}
Run Code Online (Sandbox Code Playgroud)

小智 33

我在这个帖子上找到了相同问题的解决方案:滚动后无法立即点击RecyclerView内的项目

你可以通过将layout_behavior添加到你的AppBarLayout来修复你的代码.你可以在这里找到代码修复AppBarLayout.Behavior.添加这个类来触摸你的项目并修复你的代码:

<android.support.design.widget.AppBarLayout android:layout_width="match_parent" app:layout_behavior="yourPackageName.FixAppBarLayoutBehavior" android:layout_height="wrap_content">

  • 我试了很多.这是最好的解决方案 (2认同)

Chr*_*ris 19

这是NestedScrollView的一个bug,bug的细节可以在这里找到:问题.问题是mScroller.isFinished()在投掷操作后onInterceptTouchEvent(MotionEvent ev)不会返回true(即使停止投掷).因此触发事件被截获.

这个bug已经报道了一段时间,但仍然没有修复.所以我已经为这个问题创建了自己的bug修复版本.我实现了自己的NestedScrollView,复制了所有代码NestedScrollView并进行了以下修改:

public class NestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild {
    ...
    private void initScrollView() {
        ...
        // replace this line:
        // mScroller = new ScrollerCompat(getContext(), null);
        mScroller = ScrollerCompat.create(getContext(), null);
        ...
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        ...
        switch (action & MotionEventCompat.ACTION_MASK) {
            ...
            case MotionEvent.ACTION_DOWN: {
                ...
                // replace this line:
                // mIsBeingDragged = !mScroller.isFinished();
                mIsBeingDragged = false;
                ...
            }
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)

NestedScrollView应该与原始行为相同.

  • 这是另一个问题.如果NestedScrollView正在抛弃,我们无法点击停止投掷 (2认同)

Dus*_*inB 8

我在这里打开了另一个问题:https://issuetracker.google.com/issues/68103042因为它似乎仍然是Oreo中的一个问题(多个设备,包括模拟器).

我的解决方案(改编自https://issuetracker.google.com/issues/37051723上的 ta .. @ graymeter.com的建议)不需要修改AOSP代码,因为它使用反射:

public class MyNestedScrollView extends NestedScrollView {

    private static final Logger sLogger = LogFactory.getLogger(MyNestedScrollView.class);

    private OverScroller mScroller;
    public boolean isFling = false;

    public MyNestedScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mScroller = getOverScroller();
    }

    @Override
    public void fling(int velocityY) {
        super.fling(velocityY);

        // here we effectively extend the super class functionality for backwards compatibility and just call invalidateOnAnimation()
        if (getChildCount() > 0) {
            ViewCompat.postInvalidateOnAnimation(this);

            // Initializing isFling to true to track fling action in onScrollChanged() method
            isFling = true;
        }
    }

    @Override
    protected void onScrollChanged(int l, final int t, final int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        if (isFling) {
            if (Math.abs(t - oldt) <= 3 || t == 0 || t == (getChildAt(0).getMeasuredHeight() - getMeasuredHeight())) {
                isFling = false;

                // This forces the mFinish variable in scroller to true (as explained the
                //    mentioned link above) and does the trick
                if (mScroller != null) {
                    mScroller.abortAnimation();
                }
            }
        }
    }

    private OverScroller getOverScroller() {
        Field fs = null;
        try {
            fs = this.getClass().getSuperclass().getDeclaredField("mScroller");
            fs.setAccessible(true);
            return (OverScroller) fs.get(this);
        } catch (Throwable t) {
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)