如何避免 CollapsingToolbarLayout 不被捕捉或“摇摆不定"滚动时? [英] How to avoid CollapsingToolbarLayout not being snapped or being "wobbly" when scrolling?

查看:44
本文介绍了如何避免 CollapsingToolbarLayout 不被捕捉或“摇摆不定"滚动时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

假设您创建了一个应用程序,该应用程序的 UI 与您可以通过滚动活动"向导创建的 UI 类似,但您希望滚动标志具有对齐功能,例如:

<android.support.design.widget.CollapsingToolbarLayout ... app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" >

问题

事实证明,在许多情况下,它存在捕捉问题.有时 UI 不会对齐到顶部/底部,从而使 CollapsingToolbarLayout 停留在两者之间.

有时它也会尝试捕捉到一个方向,然后决定捕捉到另一个方向.

您可以在此处的附加视频中看到这两个问题.

我的尝试

我认为这是我在 RecyclerView 上使用 setNestedScrollingEnabled(false) 时遇到的问题之一,所以我询问了它here,但后来我注意到,即使使用解决方案并且根本不使用此命令,甚至使用简单的 NestedScrollView(由向导创建),我仍然可以注意到这种行为.

这就是我决定将此作为问题报告的原因,此处.

遗憾的是,我在 StackOverflow 上找不到解决这些奇怪错误的任何方法.

问题

为什么会发生这种情况,更重要的是:如何在仍然使用它应该具有的行为的同时避免这些问题?

<小时>

这是已接受答案的改进 Kotlin 版本:

class RecyclerViewEx @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : RecyclerView(context, attrs, defStyle) {私有变量 mAppBarTracking:AppBarTracking?= 空私有变量 mView:查看?= 空私有变量 mTopPos: Int = 0私有变量 mLayoutManager:LinearLayoutManager?= 空界面 AppBarTracking {有趣的 isAppBarIdle(): 布尔值有趣的 isAppBarExpanded(): 布尔值}覆盖乐趣 dispatchNestedPreScroll(dx: Int, dy: Int, 消费: IntArray?, offsetInWindow: IntArray?, type: Int): Boolean {如果(mAppBarTracking == null)return super.dispatchNestedPreScroll(dx, dy,consumed, offsetInWindow, type)if (type == ViewCompat.TYPE_NON_TOUCH && mAppBarTracking!!.isAppBarIdle()&&isNestedScrollingEnabled) {如果 (dy > 0) {if (mAppBarTracking!!.isAppBarExpanded()) {消耗!![1] = dy返回真}} 别的 {mTopPos = mLayoutManager!!.findFirstVisibleItemPosition()如果(mTopPos == 0){mView = mLayoutManager!!.findViewByPosition(mTopPos)如果 (-mView!!.top + dy <= 0) {消耗!![1] = dy - mView!!.top返回真}}}}if (dy < 0 && type == ViewCompat.TYPE_TOUCH && mAppBarTracking!!.isAppBarExpanded()) {消耗!![1] = dy返回真}val returnValue = super.dispatchNestedPreScroll(dx,dy,consumed,offsetInWindow,type)if (offsetInWindow != null && !isNestedScrollingEnabled && offsetInWindow[1] != 0)偏移窗口[1] = 0返回返回值}覆盖乐趣 setLayoutManager(布局:RecyclerView.LayoutManager){super.setLayoutManager(布局)mLayoutManager = layoutManager 作为 LinearLayoutManager}有趣的 setAppBarTracking(appBarTracking: AppBarTracking) {mAppBarTracking = appBarTracking}有趣的 setAppBarTracking(appBarLayout: AppBarLayout) {val appBarIdle = AtomicBoolean(true)val appBarExpanded = AtomicBoolean()appBarLayout.addOnOffsetChangedListener(对象:AppBarLayout.OnOffsetChangedListener {私有变量 mAppBarOffset = Integer.MIN_VALUE覆盖乐趣 onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {如果(mAppBarOffset == verticalOffset)返回mAppBarOffset = verticalOffsetappBarExpanded.set(verticalOffset == 0)appBarIdle.set(mAppBarOffset >= 0 || mAppBarOffset <= -appBarLayout.totalScrollRange)}})setAppBarTracking(对象:AppBarTracking {覆盖乐趣 isAppBarIdle(): Boolean = appBarIdle.get()覆盖乐趣 isAppBarExpanded(): Boolean = appBarExpanded.get()})}覆盖 fun fling(velocityX: Int, inputVelocityY: Int): Boolean {var velocityY = inputVelocityYif (mAppBarTracking != null && !mAppBarTracking!!.isAppBarIdle()) {val vc = ViewConfiguration.get(context)velocityY = if (velocityY <0) -vc.scaledMinimumFlingVelocity否则 vc.scaledMinimumFlingVelocity}返回 super.fling(velocityX, velocityY)}}

解决方案

更新我稍微更改了代码以解决剩余的问题 - 至少是我可以重现的问题.关键的更新是仅在 AppBar 展开或折叠时处理 dy.在第一次迭代中,dispatchNestedPreScroll() 在不检查 AppBar 是否处于折叠状态的情况下处理滚动.

其他变化很小,属于清理类别.代码块更新如下.

<小时>

此答案解决了有关 RecyclerView 的问题.我给出的另一个答案仍然有效并适用于此.RecyclerView 与支持库的 26.0.0-beta2 中引入的 NestedScrollView 具有相同的问题.

以下代码基于 this answer 到一个相关问题,但包括对 AppBar 不稳定行为的修复.我已经删除了修复奇怪滚动的代码,因为它似乎不再需要了.

AppBarTracking.java

公共接口 AppBarTracking {布尔值 isAppBarIdle();boolean isAppBarExpanded();}

MyRecyclerView.java

public class MyRecyclerView extends RecyclerView {公共 MyRecyclerView(上下文上下文){这(上下文,空);}公共 MyRecyclerView(上下文上下文,AttributeSet attrs){这(上下文,属性,0);}公共 MyRecyclerView(上下文上下文,AttributeSet attrs,int defStyle){超级(上下文,属性,defStyle);}私有 AppBarTracking mAppBarTracking;私人视图 mView;私人 int mTopPos;私有 LinearLayoutManager mLayoutManager;@覆盖public boolean dispatchNestedPreScroll(int dx, int dy, int[] 消耗, int[] offsetInWindow,整数类型){//应用栏锁定问题仅在应用栏展开时出现这种类型的移动//或折叠.在触摸模式下,无论打开/关闭状态都正常//应用栏.if (type == ViewCompat.TYPE_NON_TOUCH && mAppBarTracking.isAppBarIdle()&&isNestedScrollingEnabled()) {//确保 AppBar 在应该展开时保持展开.if (dy > 0) {//向上滑动如果(mAppBarTracking.isAppBarExpanded()){//Appbar 只能在触摸的力量下离开它的展开状态...消耗[1] = dy;返回真;}} else {//向下滑动(或没有变化)//确保 AppBar 在应该折叠时保持折叠状态.//只有 dy <0 将打开 AppBar.如果需要,通过消耗 dy 来阻止它打开.mTopPos = mLayoutManager.findFirstVisibleItemPosition();如果(mTopPos == 0){mView = mLayoutManager.findViewByPosition(mTopPos);如果 (-mView.getTop() + dy <= 0) {//滚动直到滚动位置 = 0 并且 AppBar 仍处于折叠状态.消耗 [1] = dy - mView.getTop();返回真;}}}}boolean returnValue = super.dispatchNestedPreScroll(dx,dy,consumed,offsetInWindow,type);//修复禁用滚动时的滚动问题.这个问题之前存在//到 26.0.0-beta2.if (offsetInWindow != null && !isNestedScrollingEnabled() && offsetInWindow[1] != 0) {offsetInWindow[1] = 0;}返回返回值;}@覆盖公共无效 setLayoutManager(RecyclerView.LayoutManager 布局){super.setLayoutManager(layout);mLayoutManager = (LinearLayoutManager) getLayoutManager();}公共无效 setAppBarTracking(AppBarTracking appBarTracking) {mAppBarTracking = appBarTracking;}@SuppressWarnings("未使用")private static final String TAG = "MyRecyclerView";}

ScrollingActivity.java

public class ScrollingActivity 扩展 AppCompatActivity实现 AppBarTracking {私有 MyRecyclerView mNestedView;私人 int mAppBarOffset;私有布尔 mAppBarIdle = false;私人 int mAppBarMaxOffset;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_scrolling);工具栏工具栏 = findViewById(R.id.toolbar);setSupportActionBar(工具栏);mNestedView = findViewById(R.id.nestedView);最终 AppBarLayout appBar = findViewById(R.id.app_bar);appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {@覆盖public final void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {mAppBarOffset = verticalOffset;//mAppBarOffset = 0 如果应用栏被展开;如果应用栏折叠,则//mAppBarOffset = mAppBarMaxOffset//mAppBarMaxOffset 总是 <=0 (-AppBarLayout.getTotalScrollRange())//mAppBarOffset 永远不应该 >零或小于 mAppBarMaxOffsetmAppBarIdle = (mAppBarOffset >= 0) ||(mAppBarOffset <= mAppBarMaxOffset);}});appBar.post(new Runnable() {@覆盖公共无效运行(){mAppBarMaxOffset = -appBar.getTotalScrollRange();}});findViewById(R.id.disableNestedScrollingButton).setOnClickListener(new OnClickListener() {@覆盖public void onClick(final View v) {//如果 AppBar 完全展开或完全折叠(空闲),则禁用//扩展并应用补丁;否则,设置一个标志以禁用扩展//并在 AppBar 空闲时应用补丁.设置扩展启用(假);}});findViewById(R.id.enableNestedScrollingButton).setOnClickListener(new OnClickListener() {@覆盖public void onClick(final View v) {设置扩展启用(真);}});mNestedView.setAppBarTracking(this);mNestedView.setLayoutManager(new LinearLayoutManager(this));mNestedView.setAdapter(新适配器(){@覆盖public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {返回新的 ViewHolder(LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1,父母,错误的)) {};}@SuppressLint("SetTextI18n")@覆盖公共无效 onBindViewHolder(最终的 ViewHolder 持有人,最终的 int 位置){((TextView)holder.itemView.findViewById(android.R.id.text1)).setText("item" + position);}@覆盖公共 int getItemCount() {返回 100;}});}私人无效setExpandEnabled(布尔启用){mNestedView.setNestedScrollingEnabled(启用);}@覆盖公共布尔 isAppBarExpanded() {返回 mAppBarOffset == 0;}@覆盖公共布尔 isAppBarIdle() {返回 mAppBarIdle;}@SuppressWarnings("未使用")private static final String TAG = "ScrollingActivity";}

这里发生了什么?

从问题来看,很明显,当用户的手指不在屏幕上时,布局无法按应有的方式关闭或打开应用栏.拖动时,应用栏会正常运行.

在 26.0.0-beta2 版本中,引入了一些新方法 - 特别是 dispatchNestedPreScroll() 带有新的 type 参数.type 参数指定由 dxdy 指定的移动是否是由于用户触摸屏幕 ViewCompat.TYPE_TOUCH 与否 ViewCompat.TYPE_NON_TOUCH.

虽然没有确定导致问题的具体代码,但修复的重点是在需要时终止 dispatchNestedPreScroll()(处理 dy)中的垂直移动通过不让垂直运动传播.实际上,应用栏在展开时将被锁定到位,并且在通过触摸手势关闭之前不允许开始关闭.应用栏在关闭时也会被锁存,直到 RecyclerView 位于其最顶端并且有足够的 dy 在执行触摸手势时打开应用栏.>

因此,这与其说是解决问题,不如说是劝阻有问题的情况.

MyRecyclerView 代码的最后一部分处理在此 问题 在禁用嵌套滚动时处理不正确的滚动移动.这是在调用 dispatchNestedPreScroll() 的 super 之后的部分,它改变了 offsetInWindow[1] 的值.此代码背后的想法与该问题的已接受答案中提出的想法相同.唯一的区别是,由于底层嵌套滚动代码已更改,因此参数 offsetInWindow 有时为 null.幸运的是,它在重要的时候似乎是非空的,所以最后一部分继续工作.

需要注意的是,此修复"非常针对所提出的问题,而不是通用解决方案.修复程序的保质期可能很短,因为我预计很快就会解决这样一个明显的问题.

Background

Suppose you have an app you've created that has a similar UI as the one you can create via the wizard of "scrolling activity", yet you wish the scrolling flags to have snapping, as such:

<android.support.design.widget.CollapsingToolbarLayout ... app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" >

The problem

As it turns out, on many cases it has issues of snapping. Sometimes the UI doesn't snap to top/bottom, making the CollapsingToolbarLayout stay in between.

Sometimes it also tries to snap to one direction, and then decides to snap to the other .

You can see both issues on the attached video here.

What I've tried

I thought it's one of the issues that I got for when I use setNestedScrollingEnabled(false) on a RecyclerView within, so I asked about it here, but then I noticed that even with the solution and without using this command at all and even when using a simple NestedScrollView (as is created by the wizard), I can still notice this behavior.

That's why I decided to report about this as an issue, here.

Sadly, I couldn't find any workaround for those weird bugs here on StackOverflow.

The question

Why does it occur, and more importantly: how can I avoid those issues while still using the behavior it's supposed to have?


EDIT: here's a nice improved Kotlin version of the accepted answer:

class RecyclerViewEx @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : RecyclerView(context, attrs, defStyle) {
    private var mAppBarTracking: AppBarTracking? = null
    private var mView: View? = null
    private var mTopPos: Int = 0
    private var mLayoutManager: LinearLayoutManager? = null

    interface AppBarTracking {
        fun isAppBarIdle(): Boolean
        fun isAppBarExpanded(): Boolean
    }

    override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?, type: Int): Boolean {
        if (mAppBarTracking == null)
            return super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type)
        if (type == ViewCompat.TYPE_NON_TOUCH && mAppBarTracking!!.isAppBarIdle()
                && isNestedScrollingEnabled) {
            if (dy > 0) {
                if (mAppBarTracking!!.isAppBarExpanded()) {
                    consumed!![1] = dy
                    return true
                }
            } else {
                mTopPos = mLayoutManager!!.findFirstVisibleItemPosition()
                if (mTopPos == 0) {
                    mView = mLayoutManager!!.findViewByPosition(mTopPos)
                    if (-mView!!.top + dy <= 0) {
                        consumed!![1] = dy - mView!!.top
                        return true
                    }
                }
            }
        }
        if (dy < 0 && type == ViewCompat.TYPE_TOUCH && mAppBarTracking!!.isAppBarExpanded()) {
            consumed!![1] = dy
            return true
        }

        val returnValue = super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type)
        if (offsetInWindow != null && !isNestedScrollingEnabled && offsetInWindow[1] != 0)
            offsetInWindow[1] = 0
        return returnValue
    }

    override fun setLayoutManager(layout: RecyclerView.LayoutManager) {
        super.setLayoutManager(layout)
        mLayoutManager = layoutManager as LinearLayoutManager
    }

    fun setAppBarTracking(appBarTracking: AppBarTracking) {
        mAppBarTracking = appBarTracking
    }

    fun setAppBarTracking(appBarLayout: AppBarLayout) {
        val appBarIdle = AtomicBoolean(true)
        val appBarExpanded = AtomicBoolean()
        appBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
            private var mAppBarOffset = Integer.MIN_VALUE

            override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
                if (mAppBarOffset == verticalOffset)
                    return
                mAppBarOffset = verticalOffset
                appBarExpanded.set(verticalOffset == 0)
                appBarIdle.set(mAppBarOffset >= 0 || mAppBarOffset <= -appBarLayout.totalScrollRange)
            }
        })
        setAppBarTracking(object : AppBarTracking {
            override fun isAppBarIdle(): Boolean = appBarIdle.get()
            override fun isAppBarExpanded(): Boolean = appBarExpanded.get()
        })
    }

    override fun fling(velocityX: Int, inputVelocityY: Int): Boolean {
        var velocityY = inputVelocityY
        if (mAppBarTracking != null && !mAppBarTracking!!.isAppBarIdle()) {
            val vc = ViewConfiguration.get(context)
            velocityY = if (velocityY < 0) -vc.scaledMinimumFlingVelocity
            else vc.scaledMinimumFlingVelocity
        }

        return super.fling(velocityX, velocityY)
    }
}

解决方案

Update I have changed the code slightly to address remaining issues - at least the ones that I can reproduce. The key update was to dispose of dy only when the AppBar is expanded or collapsed. In the first iteration, dispatchNestedPreScroll() was disposing of scroll without checking the status of the AppBar for a collapsed state.

Other changes are minor and fall under the category of clean up. The code blocks are updated below.


This answer addresses the question's issue regarding RecyclerView. The other answer I have given still stands and applies here. RecyclerView has the same issues as NestedScrollView that were introduced in 26.0.0-beta2 of the support libraries.

The code below is base upon this answer to a related question but includes the fix for the erratic behavior of the AppBar. I have removed the code that fixed the odd scrolling because it no longer seems to be needed.

AppBarTracking.java

public interface AppBarTracking {
    boolean isAppBarIdle();
    boolean isAppBarExpanded();
}

MyRecyclerView.java

public class MyRecyclerView extends RecyclerView {

    public MyRecyclerView(Context context) {
        this(context, null);
    }

    public MyRecyclerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    private AppBarTracking mAppBarTracking;
    private View mView;
    private int mTopPos;
    private LinearLayoutManager mLayoutManager;

    @Override
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow,
                                           int type) {

        // App bar latching trouble is only with this type of movement when app bar is expanded
        // or collapsed. In touch mode, everything is OK regardless of the open/closed status
        // of the app bar.
        if (type == ViewCompat.TYPE_NON_TOUCH && mAppBarTracking.isAppBarIdle()
                && isNestedScrollingEnabled()) {
            // Make sure the AppBar stays expanded when it should.
            if (dy > 0) { // swiped up
                if (mAppBarTracking.isAppBarExpanded()) {
                    // Appbar can only leave its expanded state under the power of touch...
                    consumed[1] = dy;
                    return true;
                }
            } else { // swiped down (or no change)
                // Make sure the AppBar stays collapsed when it should.
                // Only dy < 0 will open the AppBar. Stop it from opening by consuming dy if needed.
                mTopPos = mLayoutManager.findFirstVisibleItemPosition();
                if (mTopPos == 0) {
                    mView = mLayoutManager.findViewByPosition(mTopPos);
                    if (-mView.getTop() + dy <= 0) {
                        // Scroll until scroll position = 0 and AppBar is still collapsed.
                        consumed[1] = dy - mView.getTop();
                        return true;
                    }
                }
            }
        }

        boolean returnValue = super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type);
        // Fix the scrolling problems when scrolling is disabled. This issue existed prior
        // to 26.0.0-beta2.
        if (offsetInWindow != null && !isNestedScrollingEnabled() && offsetInWindow[1] != 0) {
            offsetInWindow[1] = 0;
        }
        return returnValue;
    }

    @Override
    public void setLayoutManager(RecyclerView.LayoutManager layout) {
        super.setLayoutManager(layout);
        mLayoutManager = (LinearLayoutManager) getLayoutManager();
    }

    public void setAppBarTracking(AppBarTracking appBarTracking) {
        mAppBarTracking = appBarTracking;
    }

    @SuppressWarnings("unused")
    private static final String TAG = "MyRecyclerView";
}

ScrollingActivity.java

public class ScrollingActivity extends AppCompatActivity
        implements AppBarTracking {

    private MyRecyclerView mNestedView;
    private int mAppBarOffset;
    private boolean mAppBarIdle = false;
    private int mAppBarMaxOffset;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scrolling);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mNestedView = findViewById(R.id.nestedView);

        final AppBarLayout appBar = findViewById(R.id.app_bar);

        appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public final void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                mAppBarOffset = verticalOffset;
                // mAppBarOffset = 0 if app bar is expanded; If app bar is collapsed then
                // mAppBarOffset = mAppBarMaxOffset
                // mAppBarMaxOffset is always <=0 (-AppBarLayout.getTotalScrollRange())
                // mAppBarOffset should never be > zero or less than mAppBarMaxOffset
                mAppBarIdle = (mAppBarOffset >= 0) || (mAppBarOffset <= mAppBarMaxOffset);
            }
        });

        appBar.post(new Runnable() {
            @Override
            public void run() {
                mAppBarMaxOffset = -appBar.getTotalScrollRange();
            }
        });

        findViewById(R.id.disableNestedScrollingButton).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                // If the AppBar is fully expanded or fully collapsed (idle), then disable
                // expansion and apply the patch; otherwise, set a flag to disable the expansion
                // and apply the patch when the AppBar is idle.
                setExpandEnabled(false);
            }
        });

        findViewById(R.id.enableNestedScrollingButton).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                setExpandEnabled(true);
            }
        });

        mNestedView.setAppBarTracking(this);
        mNestedView.setLayoutManager(new LinearLayoutManager(this));
        mNestedView.setAdapter(new Adapter() {
            @Override
            public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
                return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(
                        android.R.layout.simple_list_item_1,
                        parent,
                        false)) {
                };
            }

            @SuppressLint("SetTextI18n")
            @Override
            public void onBindViewHolder(final ViewHolder holder, final int position) {
                ((TextView) holder.itemView.findViewById(android.R.id.text1)).setText("item " + position);
            }

            @Override
            public int getItemCount() {
                return 100;
            }
        });
    }

    private void setExpandEnabled(boolean enabled) {
        mNestedView.setNestedScrollingEnabled(enabled);
    }

    @Override
    public boolean isAppBarExpanded() {
        return mAppBarOffset == 0;
    }

    @Override
    public boolean isAppBarIdle() {
        return mAppBarIdle;
    }

    @SuppressWarnings("unused")
    private static final String TAG = "ScrollingActivity";
}

What is happening here?

From the question, it was apparent that the layout was failing to snap the app bar closed or open as it should when the user's finger was not on the screen. When dragging, the app bar behaves as it should.

In version 26.0.0-beta2, some new methods were introduced - specifically dispatchNestedPreScroll() with a new type argument. The type argument specifies if the movement specified by dx and dy are due to the user touching the screen ViewCompat.TYPE_TOUCH or not ViewCompat.TYPE_NON_TOUCH.

Although the specific code that causes the problem was not identified, the tack of the fix is to kill vertical movement in dispatchNestedPreScroll() (dispose of dy) when needed by not letting vertical movement propagate. In effect, the app bar is to be latched into place when expanded and will not allowed to start to close until it is closing through a touch gesture. The app bar will also be latched when closed until the RecyclerView is positioned at its topmost extent and there is sufficient dy to open the app bar while performing a touch gesture.

So, this is not so much a fix as much as a discouragement of problematic conditions.

The last part of the MyRecyclerView code deals with an issue that was identified in this question dealing with improper scroll movements when nested scrolling is disabled. This is the part that comes after the call to the super of dispatchNestedPreScroll() that changes the value of offsetInWindow[1]. The thinking behind this code is the same as presented in the accepted answer for the question. The only difference is that since the underlying nested scrolling code has changed, the argument offsetInWindow is sometime null. Fortunately, it seems to be non-null when it matters, so the last part continues to work.

The caveat is that this "fix" is very specific to the question asked and is not a general solution. The fix will likely have a very short shelf life since I expect that such an obvious problem will be addressed shortly.

这篇关于如何避免 CollapsingToolbarLayout 不被捕捉或“摇摆不定"滚动时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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