简体   繁体   English

当recyclerview滚动/返回顶部时展开appbarlayout

[英]Expand appbarlayout when recyclerview is scrolled/fling to top

I implemented a collapsingtoolbar layout with a recyclerview as shown in the sample code attached. 我实现了一个带有recyclerview的collapsingtoolbar布局,如附带的示例代码所示。 My issue is that, when I fling the list downward, it does not go all the way to the top. 我的问题是,当我向下推送列表时,它不会一直到顶部。

What happens is that, the scrolling stops right at the point where the AppBarLayout is supposed to end. 会发生什么,滚动停止在AppBarLayout应该结束的点。

The effect that I want is upon flinging the list downward, the list will go all the way to the top AND reveal/expand the AppBarLayout 我想要的效果是向下推送列表,列表将一直到顶部并显示/扩展AppBarLayout

My minSdk is 14. Any help or suggestion is greatly appreciated. 我的minSdk是14.非常感谢任何帮助或建议。

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.AppBarLayout>

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

        <LinearLayout
            app:layout_collapseMode="parallax">

            //some elements

        </LinearLayout>

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

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

<android.support.v7.widget.RecyclerView
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/> //value android.support.design.widget.AppBarLayout$ScrollingViewBehavior

<android.support.v7.widget.Toolbar
    app:popupTheme="@style/AppTheme.PopupOverlay"
    app:layout_collapseMode="parallax" />

I had similar problem and I used a simple trick to expand AppBarLayout when RecyclerView fling to top (you need to have support library >= 23.xx) 我遇到了类似的问题,当RecyclerView投入到顶部时,我使用了一个简单的技巧来扩展AppBarLayout(你需要支持库> = 23.xx)

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    int firstVisiblePosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
                    if (firstVisiblePosition == 0) {
                        mAppBarLayout.setExpanded(true, true);
                    }
                }
            }
});

You can fully expand or collapse the App Bar with the setExpanded() method. 您可以使用setExpanded()方法完全展开或折叠App Bar。 One implementation could involve overriding dispatchTouchEvent() in your Activity class, and auto-collapsing/expanding your App Bar based on whether it is collapsed past the halfway point: 一个实现可能涉及覆盖Activity类中的dispatchTouchEvent() ,并根据它是否在中途点折叠后自动折叠/展开App Bar:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_UP) {
        float per = Math.abs(mAppBarLayout.getY()) / mAppBarLayout.getTotalScrollRange();
        boolean setExpanded = (per <= 0.5F);
        mAppBarLayout.setExpanded(setExpanded, true);
    }
    return super.dispatchTouchEvent(event);
}

In respect to automatically scrolling to the last position on a fling, I have put some code on GitHub that shows how to programmatically smooth scroll to a specific location that may help. 关于在fling上自动滚动到最后一个位置,我在GitHub上放了一些代码,显示了如何以编程方式平滑滚动到可能有用的特定位置 Calling a scroll to list.size() - 1 on a fling for instance could replicate the behaviour. 调用滚动到list.size() - 1fling ,例如可以复制的行为。 Parts of this code by the way are adapted from the StylingAndroid and Novoda blogs: 顺便说一下,这段代码的部分内容改编自StylingAndroidNovoda博客:

public class RecyclerLayoutManager extends LinearLayoutManager {

    private AppBarManager mAppBarManager;
    private int visibleHeightForRecyclerView;

    public RecyclerLayoutManager(Context context) {
        super(context);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        View firstVisibleChild = recyclerView.getChildAt(0);
        final int childHeight = firstVisibleChild.getHeight();
        int distanceInPixels = ((findFirstVisibleItemPosition() - position) * childHeight);
        if (distanceInPixels == 0) {
            distanceInPixels = (int) Math.abs(firstVisibleChild.getY());
        }
        //Called Once
        if (visibleHeightForRecyclerView == 0) {
            visibleHeightForRecyclerView = mAppBarManager.getVisibleHeightForRecyclerViewInPx();
        }
        //Subtract one as adapter position 0 based
        final int visibleChildCount = visibleHeightForRecyclerView/childHeight - 1;

        if (position <= visibleChildCount) {
            //Scroll to the very top and expand the app bar
            position = 0;
            mAppBarManager.expandAppBar();
        } else {
            mAppBarManager.collapseAppBar();
        }

        SmoothScroller smoothScroller = new SmoothScroller(recyclerView.getContext(), Math.abs(distanceInPixels), 1000);
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    public void setAppBarManager(AppBarManager appBarManager) {
        mAppBarManager = appBarManager;
    }

    private class SmoothScroller extends LinearSmoothScroller {
        private static final int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;
        private final float distanceInPixels;
        private final float duration;

        public SmoothScroller(Context context, int distanceInPixels, int duration) {
            super(context);
            this.distanceInPixels = distanceInPixels;
            float millisecondsPerPx = calculateSpeedPerPixel(context.getResources().getDisplayMetrics());
            this.duration = distanceInPixels < TARGET_SEEK_SCROLL_DISTANCE_PX ?
                    (int) (Math.abs(distanceInPixels) * millisecondsPerPx) : duration;
        }

        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return RecyclerLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
        }

        @Override
        protected int calculateTimeForScrolling(int dx) {
            float proportion = (float) dx / distanceInPixels;
            return (int) (duration * proportion);
        }
    }
}

Edit: 编辑:

AppBarManager in the above code snippet refers to an interface used to communicate with the AppBarLayout in an Activity . 上面代码片段中的AppBarManager是指用于与ActivityAppBarLayout通信的interface Collapse/expand app bar methods do just that, with animations. 使用动画折叠/展开应用栏方法即可。 The final method is used to calculate the number of RecyclerView rows visible on screen: 最终方法用于计算屏幕上可见的RecyclerView行数:

AppBarManager.java AppBarManager.java

public interface AppBarManager {

    void collapseAppBar();
    void expandAppBar();
    int getVisibleHeightForRecyclerViewInPx();

}

MainActivity.java MainActivity.java

public class MainActivity extends AppCompatActivity implements AppBarManager{

@Override
public void collapseAppBar() {
    mAppBarLayout.setExpanded(false, true);
}

@Override
public void expandAppBar() {
    mAppBarLayout.setExpanded(true, true);
}

@Override
public int getVisibleHeightForRecyclerViewInPx() {

    if (mRecyclerFragment == null) mRecyclerFragment =
            (RecyclerFragment) getSupportFragmentManager().findFragmentByTag(RecyclerFragment.TAG);

    int windowHeight, appBarHeight, headerViewHeight;
    windowHeight = getWindow().getDecorView().getHeight();
    appBarHeight = mAppBarLayout.getHeight();
    headerViewHeight = mRecyclerFragment.getHeaderView().getHeight();
    return windowHeight - (appBarHeight + headerViewHeight);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在向下滚动时扩展AppBarLayout到达RecyclerView的顶部 - How to expand AppBarLayout when scrolling down reaches at top of the RecyclerView 当 AppBarLayout 滚动时,RecyclerView fling 导致延迟 - RecyclerView fling causes laggy while AppBarLayout is scrolling 滚动recyclerview时隐藏BottomAppBar(在Activity中)和Appbarlayout(在片段中) - Hide both BottomAppBar (in Activity) and Appbarlayout(in fragment) when recyclerview is scrolled 向上滚动时,RecyclerView跳到顶部 - RecyclerView jump to top when scrolled up 在垂直 RecyclerView 内的水平 RecyclerView 上垂直滚动时,AppBarLayout 不会折叠/展开 - AppBarLayout does not collapse/expand when scrolling vertically over horizontal RecyclerView inside vertical RecyclerView android,当在viewpager中滚动recyclerview时,如何使父scrollview滚动到顶部 - android when recyclerview in a viewpager is scrolled, how to top parent scrollview scroll 如何检测 RecyclerView 何时滚动到最顶部位置 - How to detect when RecyclerView is scrolled to most top position 如何检测用户何时滚动到RecyclerView中的最顶层项目 - How to detect when user have scrolled to the top most item in a RecyclerView AppBarLayout削减了第一个RecyclerView项目的顶部 - AppBarLayout Cuts the Top of the First RecyclerView Item 随AppBarLayout和ViewPager(回收者视图)猛扑 - fling with AppBarLayout and ViewPager(recycler view)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM