RecyclerView
RecyclerView 定位
RecyclerView.scrollBy(x, y)
y > 0 向上移动
y < 0 向下移动
scroll只会触发一次onScrolled
RecyclerView.scrollToPosition(position)
scrollToPosition(position)这个方法的作用是定位到指定项,就是把你想显示的项显示出来,但是在屏幕的什么位置是不管的,只要那一项现在看得到了,那它就罢工了!
会触发onScrolled方法一次。然后我们可以处理一些你想滑动的不足一个item的距离,scrollBy或者其他的都行。
recyclerView.smoothScrollToPosition(position)
smoothScrollToPosition(position)和scrollToPosition(position)效果基本相似,也是把你想显示的项显示出来,只要那一项现在看得到了,那它就罢工了,不同的是smoothScrollToPosition是平滑到你想显示的项,而scrollToPosition是直接定位显示!
smoothScroll会触发多次onScrolled,还会触发onScrollStateChanged
scrollToPositionWithOffset
使用: ((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(position,0);
主角总是最后才登场,这种方式是定位到指定项如果该项可以置顶就将其置顶显示。比如:微信联系人的字母索引定位就是采用这种方式实现。
onScrollStateChanged 和 onScroll
实现滚动监听,首先需要通过实现OnScrollListener 接口,
重写一下两个方法:
- onScrollStateChanged 用于监听ListView滑动状态的变化
- onScroll 用于监听ListView屏幕滚动
onScrollStateChanged
// 监听滑动状态的变化
@Override
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
// OnScrollListener.SCROLL_STATE_FLING; // 2 屏幕处于甩动状态
// OnScrollListener.SCROLL_STATE_IDLE; // 0 停止滑动状态
// OnScrollListener.SCROLL_STATE_TOUCH_SCROLL;// 1 手指接触状态
// 记录当前滑动状态
super.onScrollStateChanged(recyclerView, newState)
}
scrollState 回调顺序如下:
- scrollState = SCROLL_STATE_TOUCH_SCROLL(1):表示正在滚动。当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1
- scrollState =SCROLL_STATE_FLING(2) :表示手指做了抛的动作(手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动)。
- crollState =SCROLL_STATE_IDLE(0) :表示屏幕已停止。屏幕停止滚动时为0。
onScroll
监听屏幕滑动
// 监听屏幕滚动的item的数量
@Override
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
onScroll中参数讲解:
recyclerView : 当前滚动的view
dx : 水平滚动距离
dy : 垂直滚动距离
dx > 0 时为手指向左滚动,列表滚动显示右面的内容
dx < 0 时为手指向右滚动,列表滚动显示左面的内容
dy > 0 时为手指向上滚动,列表滚动显示下面的内容
dy < 0 时为手指向下滚动,列表滚动显示上面的内容
当不满一屏幕时 onScroll 不会触发
可以使用 OnTouchListener监控
原文
private var canSlide = false //能否翻页
val onTouchListener = object : View.OnTouchListener {
var oldy: Float = 0.0f
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
event?.action.let {
if (it == MotionEvent.ACTION_DOWN) {
oldy = event!!.getY();
}
if (it == MotionEvent.ACTION_UP) {
var distance = ViewConfiguration.get(context)
.getScaledTouchSlop() // 在我们认为用户正在滚动之前,触摸可以移动的像素距离
this@PhotoGalleryFragment.canSlide =
(oldy - event!!.getY()) > distance * 20 // 当按下和弹起的距离为正值,且大于distance是表示可以翻页
}
}
return false
}
}
val recyclerListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (canSlide && !recyclerView.canScrollVertically(1)) { // 当canSlide为真且RecyclerView已到底部时
canSlide = false
var adpter = mPhotoRecyclerView.adapter as PhotoAdpter
FetachItemTask().execute(adpter.mGalleryItems.size / 10 + 2) // 加载数据
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
}
canScrollVertically和canScrollHorizontally方法
public boolean canScrollVertically (int direction)
这个方法是判断View在竖直方向是否还能向上,向下滑动。
其中,direction为 -1 表示手指向下滑动(屏幕向上滑动), 1 表示手指向上滑动(屏幕向下滑动)。
public boolean canScrollHorizontally (int direction)
这个方法用来判断 水平方向的滑动
例如:
RecyclerView.canScrollVertically(1)的值表示是否能向下滚动,false表示已经滚动到底部
RecyclerView.canScrollVertically(-1)的值表示是否能向上滚动,false表示已经滚动到顶部
两种判断是否到底部的方法:
方法一:
如果 当前
第一个可见item的位置 + 当前可见的item个数 >= item的总个数
这样就可以判断出来,是在底部了。
loadingMoreListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) //向下滚动
{
int visibleItemCount = mLinearLayoutManager.getChildCount();
int totalItemCount = mLinearLayoutManager.getItemCount();
int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = true;
loadMoreDate();
}
}
}
};