Bel*_*loo 5 animation android android-layout android-recyclerview
我创建了一个自定义布局管理的RecyclerView
。我已通过启用了我的经理的构造函数中的自动测量setAutoMeasureEnabled(true)
当RecyclerView
的layout_height
设置为wrap_content
与此属性LayoutManager
是能够测量的高度RecyclerView
,根据里面的物品。它工作正常,但是当我删除底部的最后一个项目时,正在播放删除的动画,这会RecyclerView
导致在动画结束之前测量其高度到结果高度。
您可能已经猜到,此行为对于添加项目是正确的,因为在这种情况下,应在动画之前测量容器
RecyclerView
动画结束后如何处理这种情况以使处理自动测量?我有所有孩子定位逻辑,onLayoutChildren
但是我认为发布此问题不是必需的,它可能是如此广泛和不清楚。
可能我应该onMeasure
手动处理layoutManager的拦截器(删除项目后调用4次(在onItemsRemoved调用之前进行一次))。因此,我可以根据删除开始时收到的高度在此处设置测量的高度:
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
super.onMeasure(recycler, state, widthSpec, heightSpec);
requestSimpleAnimationsInNextLayout();
if (!isAutoMeasureEnabled()) {
setMeasuredDimension(getWidth(), preHeight);
}
}
@Override
public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
super.onItemsRemoved(recyclerView, positionStart, itemCount);
setAutoMeasureEnabled(false);
new Handler(Looper.myLooper()).postDelayed(new Runnable() {
@Override
public void run() {
setAutoMeasureEnabled(true);
requestSimpleAnimationsInNextLayout();
requestLayout();
}
}, 400);
preHeight = //calculate height before deletion
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我为处理程序提供了大约延迟的400ms
值,该处理程序在动画完成后执行自动测量,因此这可能会导致需要的结果,但是动画的持续时间不是一成不变的,而且我看不到有可能收听动画完成的事件。
因此,所需的行为:
顺便说一下,LinearLayoutManager的自动测量以相同的方式工作
如果您仅用算法的文字说明就为我指明了正确的方向,那就足够了。
我终于想通了。所以,我的解决方案:
在onAdapterChanged
方法中订阅 dataChanges 事件并禁用自动测量。
@Override
public void onAdapterChanged(RecyclerView.Adapter oldAdapter,
RecyclerView.Adapter newAdapter) {
newAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
// on api 16 this is invoked before onItemsRemoved
super.onItemRangeRemoved(positionStart, itemCount);
/** we detected removing event, so should process measuring manually
*/
setAutoMeasureEnabled(false);
}
});
//Completely scrap the existing layout
removeAllViews();
}
Run Code Online (Sandbox Code Playgroud)
在onMeasure
的情况下,自动测量手动禁用测量,使用电流的大小:
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
super.onMeasure(recycler, state, widthSpec, heightSpec);
if (!isAutoMeasureEnabled()) {
// we should perform measuring manually
// so request animations
requestSimpleAnimationsInNextLayout();
//keep size until remove animation will be completed
setMeasuredDimension(getWidth(), getHeight());
}
}
Run Code Online (Sandbox Code Playgroud)
动画完成后执行自动测量:
@Override
public void onItemsRemoved(final RecyclerView recyclerView, int positionStart, int itemCount) {
super.onItemsRemoved(recyclerView, positionStart, itemCount);
//subscribe to next animations tick
postOnAnimation(new Runnable() {
@Override
public void run() {
//listen removing animation
recyclerView.getItemAnimator().isRunning(new RecyclerView.ItemAnimator.ItemAnimatorFinishedListener() {
@Override
public void onAnimationsFinished() {
//when removing animation finished return auto-measuring back
setAutoMeasureEnabled(true);
// and process onMeasure again
requestLayout();
}
});
}
});
Run Code Online (Sandbox Code Playgroud)
这个回调链是安全的,因为postOnAnimation
如果布局管理器从RecyclerView
归档时间: |
|
查看次数: |
2720 次 |
最近记录: |