wm1*_*1sr 58 android android-cardview android-recyclerview
我有一个RecyclerView在里面CardView.该CardView有500dp的高度,但我想缩短这个高度,如果RecyclerView是较小的.所以我想知道RecyclerView在第一次完成放置项目时是否有任何监听器被调用,从而可以将RecyclerView高度设置为CardView高度(如果小于500dp).
and*_*ino 54
在我的Recycler视图完成对所有元素的膨胀之后,我还需要执行代码.我尝试onBindViewHolder在我的适配器中检入,如果位置是最后一个,然后通知观察者.但在那时,回收者的观点仍然没有完全填充.
正如RecyclerView实现的那样ViewGroup,这个anwser非常有用.您只需要将一个OnGlobalLayoutListener添加到recyclerView:
View recyclerView = findViewById(R.id.myView);
recyclerView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//At this point the layout is complete and the
//dimensions of recyclerView and any child views are known.
//Remove listener after changed RecyclerView's height to prevent infinite loop
recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Run Code Online (Sandbox Code Playgroud)
Pha*_*e P 32
@andrino anwser的工作修改.
正如@Juancho在上面的评论中指出的那样.这种方法被多次调用.在这种情况下,我们希望它只被触发一次.
使用实例创建自定义侦听器
private RecyclerViewReadyCallback recyclerViewReadyCallback;
public interface RecyclerViewReadyCallback {
void onLayoutReady();
}
Run Code Online (Sandbox Code Playgroud)
然后设置OnGlobalLayoutListener你的RecyclerView
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (recyclerViewReadyCallback != null) {
recyclerViewReadyCallback.onLayoutReady();
}
recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Run Code Online (Sandbox Code Playgroud)
之后,您只需要使用您的代码实现自定义侦听器
recyclerViewReadyCallback = new RecyclerViewReadyCallback() {
@Override
public void onLayoutReady() {
//
//here comes your code that will be executed after all items are laid down
//
}
};
Run Code Online (Sandbox Code Playgroud)
我尝试过这个,它对我有用。这是 Kotlin 扩展
fun RecyclerView.runWhenReady(action: () -> Unit) {
val globalLayoutListener = object: ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
action()
viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
}
Run Code Online (Sandbox Code Playgroud)
然后调用它
myRecyclerView.runWhenReady {
// Your action
}
Run Code Online (Sandbox Code Playgroud)
如果使用Kotlin,则有更紧凑的解决方案。从这里取样。
此布局侦听器通常用于在测量View后执行某些操作,因此通常需要等到width和height大于0为止
。...可以由扩展View并可以访问的任何对象使用它。侦听器的所有特定功能和属性。
// define 'afterMeasured' layout listener:
inline fun <T: View> T.afterMeasured(crossinline f: T.() -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (measuredWidth > 0 && measuredHeight > 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
f()
}
}
})
}
// using 'afterMeasured' handler:
myRecycler.afterMeasured {
// do the scroll (you can use the RecyclerView functions and properties directly)
// ...
}
Run Code Online (Sandbox Code Playgroud)
我改进了 android 开发人员的答案来解决这个问题。这是一段 Kotlin 代码,但即使您只懂 Java,也应该很容易理解。
我写了一个子类,LinearLayoutManager它可以让你收听onLayoutCompleted()事件:
/**
* This class calls [mCallback] (instance of [OnLayoutCompleteCallback]) when all layout
* calculations are complete, e.g. following a call to
* [RecyclerView.Adapter.notifyDataSetChanged()] (or related methods).
*
* In a paginated listing, we will decide if load more needs to be called in the said callback.
*/
class NotifyingLinearLayoutManager(context: Context) : LinearLayoutManager(context, VERTICAL, false) {
var mCallback: OnLayoutCompleteCallback? = null
override fun onLayoutCompleted(state: RecyclerView.State?) {
super.onLayoutCompleted(state)
mCallback?.onLayoutComplete()
}
fun isLastItemCompletelyVisible() = findLastCompletelyVisibleItemPosition() == itemCount - 1
interface OnLayoutCompleteCallback {
fun onLayoutComplete()
}
}
Run Code Online (Sandbox Code Playgroud)
现在我设置mCallback如下:
mLayoutManager.mCallback = object : NotifyingLinearLayoutManager.OnLayoutCompleteCallback {
override fun onLayoutComplete() {
// here we know that the view has been updated.
// now you can execute your code here
}
}
Run Code Online (Sandbox Code Playgroud)
注意:与链接的答案不同的是,我使用onLayoutComplete()它只被调用一次,正如文档所说:
void onLayoutCompleted(RecyclerView.State 状态)
在完成完整的布局计算后调用。
onLayoutChildren(Recycler, State)由于动画或布局测量,布局计算可能包括多次调用,但它只会包括一次onLayoutCompleted(State)调用。该方法将在调用结束时layout(int, int, int, int)调用。这是 LayoutManager 进行一些清理的好地方,例如挂起的滚动位置、保存的状态等。
小智 7
我发现知道何时完成放置项目的最佳方法是使用 LinearLayoutManager。
例如:
private RecyclerView recyclerView;
...
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false){
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
// TODO
}
);
...
Run Code Online (Sandbox Code Playgroud)
小智 5
同样在相同的情况下,您可以使用RecyclerView.post()method 在弹出列表/网格项目后运行您的代码。在我的情况下,这已经足够了。
| 归档时间: |
|
| 查看次数: |
36386 次 |
| 最近记录: |