recyclerview初始位置怎么恢复到上次滚动到的位置

XRecyclerView实现下拉刷新、滚动到底部加载更多等功能
作者:Tryking
字体:[ ] 类型:转载 时间:
这篇文章主要为大家详细介绍了XRecyclerView实现下拉刷新、滚动到底部加载更多等功能,以及添加header功能的RecyclerView
一个实现了下拉刷新,滚动到底部加载更多以及添加header功能的的RecyclerView。使用方式和RecyclerView完全一致,不需要额外的layout,不需要写特殊的adater。 加载效果内置了AVLoadingIndicatorView上的所有效果,可以根据需要指定。
项目地址:
&RelativeLayout xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"&
&com.jcodecraeer.xrecyclerview.XRecyclerView
android:id="@+id/recyclerview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" /&
&/RelativeLayout&
2.MainActivity
package com.example.
import android.os.B
import android.os.H
import android.support.v7.app.AppCompatA
import android.support.v7.widget.LinearLayoutM
import android.view.LayoutI
import android.view.M
import android.view.MenuI
import android.view.V
import android.view.ViewG
import com.jcodecraeer.xrecyclerview.ProgressS
import com.jcodecraeer.xrecyclerview.XRecyclerV
import java.util.ArrayL
public class MainActivity extends AppCompatActivity {
private XRecyclerView mRecyclerV
private MyAdapter mA
private ArrayList&String& listD
private int refreshTime = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (XRecyclerView)this.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);
mRecyclerView.setLaodingMoreProgressStyle(ProgressStyle.Pacman);
mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);
View header = LayoutInflater.from(this).inflate(R.layout.recyclerview_header, (ViewGroup)findViewById(android.R.id.content),false);
mRecyclerView.addHeaderView(header);
mRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
public void onRefresh() {
refreshTime ++;
new Handler().postDelayed(new Runnable(){
public void run() {
listData.clear();
for(int i = 0; i & 15 ;i++){
listData.add("item" + i + "after " + refreshTime + " times of refresh");
mAdapter.notifyDataSetChanged();
mRecyclerView.refreshComplete();
//refresh data here
public void onLoadMore() {
new Handler().postDelayed(new Runnable(){
public void run() {
for(int i = 0; i & 15 ;i++){
listData.add("item" + (i + listData.size()) );
mAdapter.notifyDataSetChanged();
mRecyclerView.loadMoreComplete();
listData = new ArrayList&String&();
mAdapter = new MyAdapter(listData);
for(int i = 0; i & 15 ;i++){
listData.add("item" + i);
mRecyclerView.setAdapter(mAdapter);
public boolean onCreateOptionsMenu(Menu menu) {
// I this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return super.onOptionsItemSelected(item);
3. adapter
package com.example.
import android.support.v7.widget.RecyclerV
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.widget.TextV
import java.util.ArrayL
* Created by jianghejie on 15/11/26.
public class MyAdapter extends RecyclerView.Adapter&MyAdapter.ViewHolder& {
public ArrayList&String& datas =
public MyAdapter(ArrayList&String& datas) {
this.datas =
//创建新View,被LayoutManager所调用
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);
ViewHolder vh = new ViewHolder(view);
//将数据与界面进行绑定的操作
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.mTextView.setText(datas.get(position));
//获取数据的数量
public int getItemCount() {
return datas.size();
//自定义的ViewHolder,持有每个Item的的所有界面元素
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextV
public ViewHolder(View view){
super(view);
mTextView = (TextView) view.findViewById(R.id.text);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具18被浏览2724分享邀请回答0添加评论分享收藏感谢收起可以使用
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
防止item 交换位置
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
layoutManager.invalidateSpanAssignments(); //防止第一行到顶部有空白区域
32 条评论分享收藏感谢收起查看更多回答RecyclerView恢复浏览位置一些事 - 简书
RecyclerView恢复浏览位置一些事
Android做应用不免需要使用到列表,说到列表,大部分人会想到ListView,当然现在也有很多人会想到RecyclerView,因为毕竟是谷歌官方推荐嘛,什么定制性更高,功能更强,更高效。
实话说,ListView对于大部分人来说,足够用了,因为毕竟熟悉RecyclerView需要时间,RecyclerView也有一些不大不小的坑。不管怎么说,我在项目中用上了RecyclerView,本没什么,跟ListView一样,现主要介绍下这几天使用RecyclerView碰到的事,也希望其他人少走弯路。
情况是这样子的,我们需要对页面中整个数据缓存,并记录用户浏览位置,下次用户再次进入当前页面时,能定位到之前的浏览位置,很好的用户体验,开始做...
关于数据缓存,我们是使用Realm存储的,Realm确实神器啊,傻瓜式操作,增删减查,几句代码搞定,不用像android原生数据库一样,所有的都要自己实现。一开始的逻辑是,在退出页面时,使用Realm记录当前页面所有数据,并记录用户滑动的位置;当用户重新进入页面时,读取数据库数据,加载到RecyclerView中,然后滑动到上次浏览位置。
当数据少时,这样做确实没问题,上面的操作基本在几十毫秒内解决,但是一旦数据上百或几百条时,Realm读取数据时间明显增加,RecylcerView加载数据时间也相应增加,最关键的是滑动到上次浏览位置时,能明显看到滑动动画,当然我用的滑动方法时下面这个
recyclerView.post(new Runnable() {
public void run() {
recyclerView.scrollBy(0, 100);
事后证明我用的这个滑动方法也有问题,当然这是后话。
实际证明,这种实现缓存并滑动到浏览位置的方案行不通。然后一通的谷歌,百度,然后又是看到一大堆博客类似上面代码方式,很无奈...
这时候,IOS大哥过来跟我说,它们可以存储整个页面,然后再次进页面的时候只要重新加载这个存储的页面就好,是不是so easy,没有数据库缓存,没有RecyclerView滑动这回事;我就估摸着,Android是不是可以存储整个Activity呢?想到就做,确实可以保存整个Activity,但是怎么加入到当前的Activity栈中呢?开始查资料,继续一通谷歌百度,然而好像还是不知道怎么加(有知道的哥们希望告诉下),倒是额外学到了一个很有用的方法moveTaskToBack(),算是浪费时间的补偿吧。
又一条路不通,开始意识到是不是陷入死胡同了,有些烦了,刷知乎吧,本着鸟枪法的原则,不经意的在知乎也搜了关于这个问题的方案,看了十几篇好像也没什么用,快失望的时候,突然看到一句评论:缓存Fragment。看到这句评论的时候,真有种热泪盈眶的感觉,是啊,缓存整个Activity行不通,缓存Fragment总行吧,想到就做,每当用户退出当前页面时,在内存中缓存当前Fragment,下次进这个页面时,直接加载这个Fragment,实验很成功,进入页面直接就在上次浏览位置,不会出现滑动动画,完美实现需要的效果(当然加载这个缓存的Fragment时,里面涉及到Activity的对象全部需要重新加载)。
按理说,事情到这里应该就完了。但是不对,缓存的Fragment带有Activity的引用(虽然这个Activity已经在退出时被销毁了),不会释放,会造成内存泄露,出了问题就解呗,然而研究一通发现,要缓存整个Fragment,这个内存泄露的问题必定会出现,最后也未发现解决的方法,就暂时搁置了。
虽然搁置这件事,但内心总有心疙瘩,浏览技术网站时,总是时不时的会搜索关于这个问题的解决方法,无意中发现ListView存在一个方法setSelectionFromTop可以直接直接回到浏览位置;既然ListView有这个方法,RecyclerView应该也有吧?然而查询之后,发现那只是我的意淫;不过,没这个方法,也并没有放弃,RecyclerView既然是可以替代ListView的,总觉得是有和setSelectionFromTop相同功能的方法的,最后也确实找出了,scrollToPositionWithOffset,嗯,好像不再RecyclerView里面,去LinearLayoutManager里面试试,终于找到!
它有2个参数,第一个参数代表你要滑动到哪个Item,第二个参数代表这个item距离屏幕顶部的距离,这个距离可以使用下面代码计算得出:
int position = linearLayoutManager.findFirstVisibleItemPosition();
View view = recyclerView.getChildAt(position);
if (view != null) {
int top = view.getTop();
ok,实现了效果,不卡顿,也不会有滑动动画,也不会出现内存泄露,问题解决了嘛?
这次是彻底解决了,以上记录苦逼的绕坑过程,那么多的研究,发现最后一个scrollToPositionWithOffset就解决了,是不是很崩溃?我确实崩溃了。
最后,希望技术博客的转载哥哥们,转载之前自己试试效果吧,因为有时候真的挺坑人的!哭!
业余程序员android:RecyclerView局部刷新那点事~
1.局部刷新的引入提到RecyclerView,我们首先想到的是ListView,对于ListView的局部刷新,我们之前已经有解决方案,[android:ListView的局部刷新]当时的解决方案是:记录点击的Item的position,然后在更新过程中,不断的判断,该position是不是介于可见的Item之间,如果是,则更新,否者,不更新。2.RecyclerView的局部更新 按照之前的思路,首先要寻找RecyclerView中可见的item的位置范围,该方法并不在RecyclerView中,而是LinearLayoutManager中,如:int fristPos = layoutManager.findFirstVisibleItemPosi
int lastPos = layoutManager.findLastVisibleItemPosition();
if (position >= fristPos && position <= lastPos) {
View view = recyclerView.getChildAt(position);
}然后查找到对应的View,进行更新(递归查找)/**
* 在ViewGroup中根据id进行查找
* @param vg
* @param id 如:R.id.tv_name
private View findViewInViewGroupById(ViewGroup vg, int id) {
for (int i = 0; i < vg.getChildCount(); i++) {
View v = vg.getChildAt(i);
if (v.getId() == id) {
if (v instanceof ViewGroup) {
return findViewInViewGroupById((ViewGroup) v, id);
}3.新的思路:notifyItemChangedRecyclerView不像ListView,只有一个更新notifyDataSetChanged,它不仅保留了ListView的更新特点,还针对“增加,删除,更新”操作专门进行更新,可以只更新一个item,也可以更新一部分item,所以,用起来效率更高。因此,RecyclerView的局部刷新,就可以通过修改数据源的方式,调用notifyItemChanged(position)即可。4.优化虽然只更新单个item,不会造成闪烁,但是,如果单个item都很复杂,比如,item中需要从网络上加载图片等等。为了避免多次刷新照成的闪烁,我们可以在加载的时候,为ImageView设置一个Tag,比如imageView.setTag(image_url),下一次再加载之前,首先获取Tag,比如imageUrl = imageView.getTag(),如果此时的地址和之前的地址一样,我们就不需要加载了,如果不一样,再加载。-------------------------------------------------------------------更多交流,开发联盟QQ群:

我要回帖

更多关于 recyclerview 滚动 的文章

 

随机推荐