最近遇到的一个问题一直困扰着我,执行以下代码无法获取正确的值。
boolean canScroll = view.canScrollHorizontally(1);
使用一个 RecyclerView 实现了一个类似 Tab 效果,当这个 Tab 可以滑动时,显示最右侧的三角按钮,否则隐藏这个按钮。效果如图
首先想到的是 SDK 中自带的 View.canScrollHorizontally(intdirection)
接口,API 文档的解析为
Check if this view can be scrolled horizontally in a certain direction.
即如果这个 View 在指定的方向上是可以滑动的,那么就返回 true。参数 direction 为正数则向左滑动检测,负数则向右滑动检测。
一开始是直接调用
mCategoryReclycerView.setAdapter(mCategoryAdapter);
if (mCategoryReclycerView.canScrollHorizontally(1)) {
mCategoryBtn.setVisibility(View.VISIBLE);
} else {
mCategoryBtn.setVisibility(View.GONE);
}
很明显这样的用法无法正确得到我想要的效果。原因是 RecyclerView 设置 Adapter 之后,数据还没有马上渲染,它内部数据是一个异步的操作。
于是我就想到 View.post(Runnable)
方法。
修改代码为,而且还延迟了100 ms。
mCategoryReclycerView.postDelayed(()->{
if (mCategoryReclycerView.canScrollHorizontally(1)) {
mCategoryBtn.setVisibility(View.VISIBLE);
} else {
mCategoryBtn.setVisibility(View.GONE);
}
},100);
当 Tab 上的分类超过手机屏幕宽度之后,依然没有显示表示”更多”操作三角按钮。
这时候非常郁闷,程序员焦虑的心情可想而知。
各种找资料查 API 文档,踩坑和填坑之后,期间省略一万字,终于在 stackoverflow 上看一个回答,说可以放在 GloblaLayoutListener 中进行检测。
于是修改代码为
mCategoryReclycerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
if (mCategoryReclycerView.canScrollHorizontally(1)) {
mCategoryBtn.setVisibility(View.VISIBLE);
//只要布局发生变动,这个方法执行多次,当拿到正确值,就把监听 remove 掉
mCategoryReclycerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mCategoryBtn.setVisibility(View.GONE);
}
}
});
执行代码,完美解决问题!
API 文档也是各种坑,文档中很多 API 都没有正确说明如何使用,这个需要开发者平时的积累。