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

时间:2015-11-08 18:27:33

标签: android android-recyclerview android-collapsingtoolbarlayout

我使用recyclerview实现了一个collapsingtoolbar布局,如附带的示例代码所示。我的问题是,当我向下推送列表时,它不会一直到顶部。

发生的情况是,滚动停止在AppBarLayout应该结束的位置。

我想要的效果是向下推送列表,列表将一直显示在顶部并显示/展开AppBarLayout

我的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" />

2 个答案:

答案 0 :(得分:11)

我有类似的问题,当RecyclerView投入顶部时,我使用了一个简单的技巧来扩展AppBarLayout(你需要支持库&gt; = 23.x.x)

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);
                    }
                }
            }
});

答案 1 :(得分:9)

您可以使用setExpanded()方法完全展开或折叠App Bar。一种实现可能涉及覆盖Activity类中的@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); } ,并根据是否在中途点折叠后自动折叠/扩展App Bar:

list.size() - 1

关于自动滚动到最后一个位置,我已经在GitHub上放了一些代码,展示了如何programmatically smooth scroll to a specific location可能有所帮助。例如,在fling上调用滚动到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); } } } 可以复制该行为。顺便说一下,此代码的部分内容是根据StylingAndroidNovoda博客改编的:

AppBarManager

修改

上述代码段中的

interface是指用于与AppBarLayout中的Activity进行通信的RecyclerView。使用动画折叠/展开应用栏方法即可。最终方法用于计算屏幕上可见的public interface AppBarManager { void collapseAppBar(); void expandAppBar(); int getVisibleHeightForRecyclerViewInPx(); } 行数:

AppBarManager.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);
}

MainActivity.java

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;