tyl*_*ach 171 android android-appcompat android-layout android-design-library
我正在使用新的CoordinatorLayout与AppBarLayout和CollapsingToolbarLayout.在AppBarLayout下面,我有一个带有内容列表的RecyclerView.
我已经验证了当我在列表中上下滚动时,滚动滚动在RecyclerView上工作.但是,我还希望AppBarLayout在扩展期间顺利滚动.
向上滚动以展开CollaspingToolbarLayout时,一旦将手指从屏幕上抬起,滚动会立即停止.如果向上快速向上滚动,有时CollapsingToolbarLayout也会重新折叠.与使用NestedScrollView时,RecyclerView的这种行为似乎有很大不同.
我试图在recyclerview上设置不同的滚动属性,但我无法弄清楚这一点.
这是一个显示一些滚动问题的视频. https://youtu.be/xMLKoJOsTAM
这是一个显示RecyclerView(CheeseDetailActivity)问题的示例. https://github.com/tylerjroach/cheesesquare
以下是使用Chris Banes的NestedScrollView的原始示例. https://github.com/chrisbanes/cheesesquare
小智 114
Kirill Boyarshinov的答案几乎是正确的.
主要问题是RecyclerView有时会给出不正确的fling方向,所以如果你将以下代码添加到他的答案中它可以正常工作:
public final class FlingBehavior extends AppBarLayout.Behavior {
private static final int TOP_CHILD_FLING_THRESHOLD = 3;
private boolean isPositive;
public FlingBehavior() {
}
public FlingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
if (velocityY > 0 && !isPositive || velocityY < 0 && isPositive) {
velocityY = velocityY * -1;
}
if (target instanceof RecyclerView && velocityY < 0) {
final RecyclerView recyclerView = (RecyclerView) target;
final View firstChild = recyclerView.getChildAt(0);
final int childAdapterPosition = recyclerView.getChildAdapterPosition(firstChild);
consumed = childAdapterPosition > TOP_CHILD_FLING_THRESHOLD;
}
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
isPositive = dy > 0;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这个对你有用.
Kir*_*nov 69
似乎v23更新尚未解决.
我找到了一些黑客来解决这个问题.如果ScrollingView的顶级子项接近Adapter中数据的开头,则诀窍是重建fling事件.
public final class FlingBehavior extends AppBarLayout.Behavior {
public FlingBehavior() {
}
public FlingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
if (target instanceof ScrollingView) {
final ScrollingView scrollingView = (ScrollingView) target;
consumed = velocityY > 0 || scrollingView.computeVerticalScrollOffset() > 0;
}
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
}
Run Code Online (Sandbox Code Playgroud)
在你的布局中使用它:
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="your.package.FlingBehavior">
<!--your views here-->
</android.support.design.widget.AppBarLayout>
Run Code Online (Sandbox Code Playgroud)
编辑:现在重建Fling事件是基于verticalScrollOffset而不是从顶部的项目数量RecyclerView.
EDIT2:将目标检查为ScrollingView接口实例而不是RecyclerView.两者RecyclerView并NestedScrollingView实现它.
Mak*_*ing 15
我通过将OnScrollingListener应用于recyclerView找到了修复程序.现在它运作得很好.问题是recyclerview提供了错误的消耗值,并且行为不知道何时将recyclerview滚动到顶部.
package com.singmak.uitechniques.util.coordinatorlayout;
import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
/**
* Created by maksing on 26/3/2016.
*/
public final class RecyclerViewAppBarBehavior extends AppBarLayout.Behavior {
private Map<RecyclerView, RecyclerViewScrollListener> scrollListenerMap = new HashMap<>(); //keep scroll listener map, the custom scroll listener also keep the current scroll Y position.
public RecyclerViewAppBarBehavior() {
}
public RecyclerViewAppBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
*
* @param coordinatorLayout
* @param child The child that attached the behavior (AppBarLayout)
* @param target The scrolling target e.g. a recyclerView or NestedScrollView
* @param velocityX
* @param velocityY
* @param consumed The fling should be consumed by the scrolling target or not
* @return
*/
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
if (target instanceof RecyclerView) {
final RecyclerView recyclerView = (RecyclerView) target;
if (scrollListenerMap.get(recyclerView) == null) {
RecyclerViewScrollListener recyclerViewScrollListener = new RecyclerViewScrollListener(coordinatorLayout, child, this);
scrollListenerMap.put(recyclerView, recyclerViewScrollListener);
recyclerView.addOnScrollListener(recyclerViewScrollListener);
}
scrollListenerMap.get(recyclerView).setVelocity(velocityY);
consumed = scrollListenerMap.get(recyclerView).getScrolledY() > 0; //recyclerView only consume the fling when it's not scrolled to the top
}
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
private static class RecyclerViewScrollListener extends RecyclerView.OnScrollListener {
private int scrolledY;
private boolean dragging;
private float velocity;
private WeakReference<CoordinatorLayout> coordinatorLayoutRef;
private WeakReference<AppBarLayout> childRef;
private WeakReference<RecyclerViewAppBarBehavior> behaviorWeakReference;
public RecyclerViewScrollListener(CoordinatorLayout coordinatorLayout, AppBarLayout child, RecyclerViewAppBarBehavior barBehavior) {
coordinatorLayoutRef = new WeakReference<CoordinatorLayout>(coordinatorLayout);
childRef = new WeakReference<AppBarLayout>(child);
behaviorWeakReference = new WeakReference<RecyclerViewAppBarBehavior>(barBehavior);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
dragging = newState == RecyclerView.SCROLL_STATE_DRAGGING;
}
public void setVelocity(float velocity) {
this.velocity = velocity;
}
public int getScrolledY() {
return scrolledY;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
scrolledY += dy;
if (scrolledY <= 0 && !dragging && childRef.get() != null && coordinatorLayoutRef.get() != null && behaviorWeakReference.get() != null) {
//manually trigger the fling when it's scrolled at the top
behaviorWeakReference.get().onNestedFling(coordinatorLayoutRef.get(), childRef.get(), recyclerView, 0, velocity, false);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Xia*_*zou 13
自支持设计26.0.0以来,它已得到修复.
compile 'com.android.support:design:26.0.0'
Run Code Online (Sandbox Code Playgroud)
这是Google支持设计AppBarLayout的流畅版本.如果你正在使用AppBarLayout,你会发现它有一个问题.
compile "me.henrytao:smooth-app-bar-layout:<latest-version>"
Run Code Online (Sandbox Code Playgroud)
请参阅此处的图书馆.. https://github.com/henrytao-me/smooth-app-bar-layout
| 归档时间: |
|
| 查看次数: |
50634 次 |
| 最近记录: |