Luk*_*sen 58 android swiperefreshlayout android-recyclerview
我正在使用新RecyclerView-Layout
的a SwipeRefreshLayout
并经历了一种奇怪的行为.当滚动列表回到顶部时,有时顶部的视图会被切入.
如果我现在尝试滚动到顶部 - Pull-To-Refresh触发器.
如果我尝试删除Recycler-View周围的Swipe-Refresh-Layout,问题就消失了.它可以在任何手机上重现(不仅仅是L-Preview设备).
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<android.support.v7.widget.RecyclerView
android:id="@+id/hot_fragment_recycler"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
Run Code Online (Sandbox Code Playgroud)
这是我的布局 - 行由RecyclerViewAdapter动态构建(此列表中有2个Viewtypes).
public class HotRecyclerAdapter extends TikDaggerRecyclerAdapter<GameRow> {
private static final int VIEWTYPE_GAME_TITLE = 0;
private static final int VIEWTYPE_GAME_TEAM = 1;
@Inject
Picasso picasso;
public HotRecyclerAdapter(Injector injector) {
super(injector);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position, int viewType) {
switch (viewType) {
case VIEWTYPE_GAME_TITLE: {
TitleGameRowViewHolder holder = (TitleGameRowViewHolder) viewHolder;
holder.bindGameRow(picasso, getItem(position));
break;
}
case VIEWTYPE_GAME_TEAM: {
TeamGameRowViewHolder holder = (TeamGameRowViewHolder) viewHolder;
holder.bindGameRow(picasso, getItem(position));
break;
}
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType) {
case VIEWTYPE_GAME_TITLE: {
View view = inflater.inflate(R.layout.game_row_title, viewGroup, false);
return new TitleGameRowViewHolder(view);
}
case VIEWTYPE_GAME_TEAM: {
View view = inflater.inflate(R.layout.game_row_team, viewGroup, false);
return new TeamGameRowViewHolder(view);
}
}
return null;
}
@Override
public int getItemViewType(int position) {
GameRow row = getItem(position);
if (row.isTeamGameRow()) {
return VIEWTYPE_GAME_TEAM;
}
return VIEWTYPE_GAME_TITLE;
}
Run Code Online (Sandbox Code Playgroud)
这是适配器.
hotAdapter = new HotRecyclerAdapter(this);
recyclerView.setHasFixedSize(false);
recyclerView.setAdapter(hotAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
contentView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadData();
}
});
TypedArray colorSheme = getResources().obtainTypedArray(R.array.main_refresh_sheme);
contentView.setColorSchemeResources(colorSheme.getResourceId(0, -1), colorSheme.getResourceId(1, -1), colorSheme.getResourceId(2, -1), colorSheme.getResourceId(3, -1));
Run Code Online (Sandbox Code Playgroud)
和Fragment
包含的代码Recycler
和SwipeRefreshLayout
.
如果其他人经历过这种行为并解决了它或者至少找到了它的原因?
小智 66
写下面的代码中addOnScrollListener
的RecyclerView
像这样:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int topRowVerticalPosition =
(recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop();
swipeRefreshLayout.setEnabled(topRowVerticalPosition >= 0);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
Run Code Online (Sandbox Code Playgroud)
tom*_*136 52
在您使用此解决方案之前:RecyclerView尚未完成,请不要在生产中使用它,除非您喜欢我!
至于2014年11月,RecyclerView中仍然存在导致canScrollVertically
过早返回错误的错误.此解决方案将解决所有滚动问题.
解决方案的下降:
public class FixedRecyclerView extends RecyclerView {
public FixedRecyclerView(Context context) {
super(context);
}
public FixedRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixedRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean canScrollVertically(int direction) {
// check if scrolling up
if (direction < 1) {
boolean original = super.canScrollVertically(direction);
return !original && getChildAt(0) != null && getChildAt(0).getTop() < 0 || original;
}
return super.canScrollVertically(direction);
}
}
Run Code Online (Sandbox Code Playgroud)
您甚至不需要替换RecyclerView
代码FixedRecyclerView
,替换XML标记就足够了!(确保在RecyclerView完成后,转换将快速而简单)
说明:
基本上,canScrollVertically(boolean)
过早返回false,所以我们检查是否RecyclerView
一直滚动到第一个视图的顶部(第一个孩子的顶部将为0),然后返回.
编辑:如果你不想RecyclerView
出于某种原因扩展,你可以扩展SwipeRefreshLayout
和覆盖该canChildScrollUp()
方法并将检查逻辑放在那里.
EDIT2:
RecyclerView已经发布,到目前为止还没有必要使用此修复程序.
bal*_*rkm 12
我最近遇到了同样的问题.我尝试了@Krunal_Patel建议的方法,但它在我的Nexus 4中大部分时间工作,并且在三星galaxy s2中根本不起作用.在调试时,对于RecyclerView,recyclelerView.getChildAt(0).getTop()始终不正确.因此,在经过各种方法之后,我想我们可以利用LayoutManager的方法findFirstCompletelyVisibleItemPosition()来预测RecyclerView的第一项是否可见,以启用SwipeRefreshLayout.Find下面的代码.希望它可以帮助有人试图解决同样的问题.干杯.
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
}
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
swipeRefresh.setEnabled(linearLayoutManager.findFirstCompletelyVisibleItemPosition() == 0);
}
});
Run Code Online (Sandbox Code Playgroud)
Amr*_*dri 10
这就是我在我的案例中解决这个问题的方法.对于那些最终在这里寻找与此类似的解决方案的人来说,这可能是有用的.
recyclerView.addOnScrollListener(new OnScrollListener()
{
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
// TODO Auto-generated method stub
super.onScrolled(recyclerView, dx, dy);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
// TODO Auto-generated method stub
//super.onScrollStateChanged(recyclerView, newState);
int firstPos=linearLayoutManager.findFirstCompletelyVisibleItemPosition();
if (firstPos>0)
{
swipeLayout.setEnabled(false);
}
else {
swipeLayout.setEnabled(true);
}
}
});
Run Code Online (Sandbox Code Playgroud)
我希望这肯定可以帮助那些正在寻找类似解决方案的人.
归档时间: |
|
查看次数: |
74584 次 |
最近记录: |