Android RecyclerView 滚动到中间位置的方法示例
最近看到QQ音乐的歌词每次滑动后都可以滚回到中间位置。觉得甚是神奇,打开开发者模式显示布局,发现歌词部分不是采用android控件的写的,应该是前端写的。于是,我想,能不能用recyclerView实现这个自动回滚到中间位置呢。
功夫不负有心人,查找了一些资料之后,终于搞定了。
下面由我细细讲来。
目标
点击某个条目,在经过4s无任何操作之后,该条目滚动到中间位置显示。点击后,用户在滑动,等用户不操作后再开始延时。用户多次点击,记最后一次点击位置。
分析
首先先考虑,滚动到指定位置是如何操作的?
//滚动到指定位置 recyclerView.scrollToPosition(position); //平滑滚动到指定位置 recyclerView.smoothScrollToPosition(position);
有没有滚动到制定像素位置呢?
//scrollBy(x,y)这个方法是自己去控制移动的距离,单位是像素,所以在使用scrollBy(x,y)需要自己去计算移动的高度或宽度。 recyclerView.scrollBy(x,y)
可是,问题是滚动到中间位置啊?这个怎么办呢?这样子行不行呢?
mRecyclerView.scrollToPosition(0); mRecyclerView.scrollBy(0,400);
先滚动到制定位置,在滚动一段距离不就好了?运行发现,这两行代码只执行第一行,第二行无效。
debug调试看了下,还是没有弄懂,实现太复杂。
那就是说这样是不行的,那有没有其他办法呢?
RecyclerView有一个滚动监听方法:
mRecyclerView.addOnScrollListener(newRecyclerView.OnScrollListener(){
@Override
publicvoidonScrollStateChanged(RecyclerViewrecyclerView,intnewState){
super.onScrollStateChanged(recyclerView,newState);
}
@Override
publicvoidonScrolled(RecyclerViewrecyclerView,intdx,intdy){
super.onScrolled(recyclerView,dx,dy);
}
});
onScrollStateChanged方法对应三种状态:静止(SCROLL_STATE_IDLE),拖动滚动(SCROLL_STATE_DRAGGING),滑动(SCROLL_STATE_SETTLING)。
当手动缓慢滑动的时候,会触发:onScrollStateChanged(拖动滚动)-->(n个)onScrolled-->onScrollStateChanged(静止);
当手快速滑动的时候,会触发:onScrollStateChanged(拖动滚动)-->(n个)onScrolled-->onScrollStateChanged(滑动)-->
(n个)onScrolled-->onScrollStateChanged(静止);
有想法了,点击的时候,先运行scrollToPosition,在onScrolled方法里面运行scrollBy方法。写代码,运行,通过。
下面就是中间位置的计算了。
首先计算出recylerview的展现高度。
Rectrect=newRect(); mRecyclerView.getGlobalVisibleRect(rect); reHeight=rect.bottom-rect.top-vHeight; 当运行scrollToPosition后,点击条目就会出现在视野当中,这时候,计算出相应的位移即可。需要注意一点的是,当点击条目在视野内的时候,是不会运行scrollToPosition方法的。 inttop=mRecyclerView.getChildAt(position-firstPosition).getTop(); inthalf=reHeight/2; mRecyclerView.scrollBy(0,top-half);
最后就是延时的设定,采用Handler进行延时。
代码
核心代码如下:
publicclassMainActivityextendsAppCompatActivity{
privatestaticfinalStringTAG="MainActivity";
privateRecyclerViewmRecyclerView;
privateLinearLayoutManagermLayoutManager;
privateRecyclerView.AdaptermAdapter;
privateString[]data;
privateHandlerhandler;
privatebooleanisClick=false;
privatestaticintvHeight=-1;
privatestaticintreHeight=-1;
privatestaticintposition=0;
privatestaticfinalinttarget=10;
privatestaticbooleanisMove=false;
privateRunnablerunnable;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler=newHandler();
mRecyclerView=(RecyclerView)findViewById(R.id.my_recycler_view);
//创建默认的线性LayoutManager
mLayoutManager=newLinearLayoutManager(this);
mLayoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setNestedScrollingEnabled(false);
data=newString[]{"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21"};
runnable=newRunnable(){
@Override
publicvoidrun(){
if(isVisible()){
scrollToMiddle();
}else{
mRecyclerView.scrollToPosition(position);
isMove=true;
isClick=false;
}
}
};
mAdapter=newMyAdapter(data,newMyAdapter.onRecyclerViewItemClick(){
@Override
publicvoidonItemClick(Viewv,intpos){
Toast.makeText(MainActivity.this,"第"+pos+"行",Toast.LENGTH_SHORT).show();
position=pos;
vHeight=v.getHeight();
Rectrect=newRect();
mRecyclerView.getGlobalVisibleRect(rect);
reHeight=rect.bottom-rect.top-vHeight;
//handler.removeCallbacksAndMessages(null);
handler.removeCallbacks(runnable);
handler.postDelayed(runnable,4000);
isClick=true;
}
});
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addOnScrollListener(newRecyclerView.OnScrollListener(){
@Override
publicvoidonScrollStateChanged(RecyclerViewrecyclerView,intnewState){
super.onScrollStateChanged(recyclerView,newState);
Log.d(TAG,""+newState);
if(newState==RecyclerView.SCROLL_STATE_DRAGGING&&!isMove){
handler.removeCallbacks(runnable);
}
if(newState==RecyclerView.SCROLL_STATE_IDLE){
if(isClick){
handler.postDelayed(runnable,4000);
}
}
}
@Override
publicvoidonScrolled(RecyclerViewrecyclerView,intdx,intdy){
super.onScrolled(recyclerView,dx,dy);
if(isMove){
if(vHeight<0){
isMove=false;
return;
}
scrollToMiddle();
}
}
});
publicvoidscrollToMiddle(){
finalintfirstPosition=mLayoutManager.findFirstVisibleItemPosition();
inttop=mRecyclerView.getChildAt(position-firstPosition).getTop();
Log.d(TAG,"position"+position+""+top);
inthalf=reHeight/2;
mRecyclerView.scrollBy(0,top-half);
isMove=false;
}
publicbooleanisVisible(){
finalintfirstPosition=mLayoutManager.findFirstVisibleItemPosition();
finalintlastPosition=mLayoutManager.findLastVisibleItemPosition();
returnposition<=lastPosition&&position>=firstPosition;
}
@Override
protectedvoidonDestroy(){
super.onDestroy();
handler.removeCallbacksAndMessages(null);
handler=null;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。