仿选股宝选个头条上下拉加载一页的功能
一、前言
最近有一个需求就是上拉、下拉整体刷新一页数据,并且将下一页数据整体划出显示,上一页数据则消失。这个类似于选股宝的头条选股的效果,先上图。
二、实现心路历程
拿到这个需求,我就想,我靠,没搞过啊,这个怎么弄!仔细看,这好像就是上拉刷新、下拉加载呀,怎么实现?套两层recycleView?里面负责显示,外面一层负责动画?添加header 和 footer?然后增加动画,还有阻尼效果?不行不行,实现时间太长,不允许!找找网上有没有实现好的开源代码,然后:“仿选股宝选股头条上拉加载”等等,都没有。那只能自己实现了,然后自己再细看这玩意,越看越像之前ListView时代的PullToRefresh,然后我就想,找一个这样的上下组件,然后这种入场方式就自己实现:先上拉,数据出来之后,记录新加载的第一条数据,然后从该条开始,向上或者向下移动。最后和大佬说这个方案的时候,他给我提意见:你这样就弄得整个recycleView的逻辑很复杂,你还不如利用Fragment显示,让它处理数据显示,动画,进出场,recycleView只负责列表显示。瞬间茅塞顿开。
三、上代码
上下拉加载,我就自己不造轮子了,有很多大牛写的很好,找了几个,最终选中了https://www.cnblogs.com/zhujiabin/p/7425535.html 这个,我对他的代码做了小小的改动,增加下拉加载时,没有数据,显示到顶了,类似于上拉没有数据的那种效果,具体修改思路按照代码中底部加载完成字段isMore 增加isPreviousData字段控制,代码就不贴了,比较简单,稍微改下就行。
3.1具体使用
3.1.1 用一个Activity承接Fragment
PullRefreshActivity.java
public class PullRefreshActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pull_refresh);BaseFragment fragment = new BaseFragment();BaseFragment fragment2 = new BaseFragment();getSupportFragmentManager().beginTransaction().replace(R.id.fl_root, PullRefreshFragment.newInstance(it)).setCustomAnimations(R.anim.fragment_top_in, R.anim.fragment_bottom_out, R.anim.fragment_bottom_in, R.anim.fragment_top_out).commit();}
}
其XML文件很简单,就一个FrameLayout,这里就不贴出了,说明一下,这个代码仅用于demo,具体项目中,这Activity得加载一次数据,在数据加载成功回调中切换Fragment,然后在Fragment中,Fragment代码如下:
PullRefreshFragment.kt
class PullRefreshFragment: Fragment() {private var list: PullRefreshRecyclerView? = nullprivate var pageNum: Int = 0private var adapter: MyAdapter? = nullprivate val data = ArrayList<String>()override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {val view = inflater.inflate(R.layout.fragment_six, container, false)list = view.findViewById<PullRefreshRecyclerView>(R.id.list)PullRefreshUtil.setRefresh(list as PullRefreshView, true, true)adapter = MyAdapter(activity, data)list?.setLayoutManager(LinearLayoutManager(activity))list?.setAdapter(adapter)loadData()list?.setOnPullDownRefreshListener {list?.isPreviousData(true)pageNum = 1loadData()list?.refreshFinish()}list?.setOnPullUpRefreshListener {pageNum++list?.isMore(true)loadData()list?.refreshFinish()}
list?.setOnHeadStateListener(object : PullRefreshView.OnHeadStateListener{override fun onRetractHead(head: View?) {activity?.supportFragmentManager?.beginTransaction()?..setCustomAnimations(R.anim.fragment_top_in, R.anim.fragment_bottom_out, R.anim.fragment_bottom_in, R.anim.fragment_top_out)?.replace(R.id.fl_root, PullRefreshFragment(), TAG2)?.commit()(head as HeadView).onRetractHead(head)}override fun onRefreshHead(head: View?) {(head as HeadView).onRefreshHead(head)}override fun onScrollChange(head: View?, scrollOffset: Int, scrollRatio: Int) {(head as HeadView).onScrollChange(head, scrollOffset, scrollRatio)}override fun onNotMore(head: View?) {(head as HeadView).onNotMore(head)}override fun onHasMore(head: View?) {(head as HeadView).onHasMore(head)}})//以下两个监听,为了切换Fragment,实际开发中我们不需要这两个监听,我们只要在数据加载成功回调中处理即可 list?.setOnTailStateListener(object : PullRefreshView.OnTailStateListener{override fun onScrollChange(tail: View?, scrollOffset: Int, scrollRatio: Int) {(tail as TailView).onScrollChange(tail, scrollOffset, scrollRatio)}override fun onRefreshTail(tail: View?) {(tail as TailView).onRefreshTail(tail)}override fun onRetractTail(tail: View?) {activity?.supportFragmentManager?.beginTransaction()?..setCustomAnimations(R.anim.fragment_top_in, R.anim.fragment_bottom_out, R.anim.fragment_bottom_in, R.anim.fragment_top_out)?.replace(R.id.fl_root, PullRefreshFragment())?.commit()(tail as TailView).onRetractTail(tail)}override fun onNotMore(tail: View?) {(tail as TailView).onNotMore(tail)}override fun onHasMore(tail: View?) {(tail as TailView).onHasMore(tail)}})return view}private fun loadData() {for (i in 0..14) {data.add(i.toString() + "")}adapter?.setData(data)adapter?.notifyDataSetChanged()}var mOnLoadSuccess: OnLoadSuccess? = nullfun setOnLoadSucess(onLoadSuccess: OnLoadSuccess) {this.mOnLoadSuccess = onLoadSuccess}interface OnLoadSuccess {fun loadSuccess()}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {private List<String> mData;private Context mContext;public MyAdapter(Context context, ArrayList<String> dataList) {this.mContext = context;this.mData = dataList;}public void setData(List<String> data) {this.mData = data;}@Overridepublic int getItemCount() {return mData.size();}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {holder.tv.setText(mData.get(position));}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(mContext).inflate(R.layout.item_adapter, parent, false);return new ViewHolder(view);}public class ViewHolder extends RecyclerView.ViewHolder {public TextView tv;public ViewHolder(View itemView) {super(itemView);tv = itemView.findViewById(R.id.tv);}}
}
其中item_adapter.xml文件很简单,只有一个TextView,这里就不贴出来了,另外Fragment进出场的四个动画如下:
fragment_bottom_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromYDelta="100%p"android:toYDelta="0%p"android:duration="300"/><alphaandroid:fromAlpha="0.5"android:toAlpha="1.0"android:duration="300"/>
</set>
fragment_top_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromYDelta="0%p"android:toYDelta="-100%p"android:duration="300"/><alphaandroid:fromAlpha="1.0"android:toAlpha="0.5"android:duration="300"/>
</set>
fragment_top_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromYDelta="-100%p"android:toYDelta="0%p"android:duration="300"/><alphaandroid:fromAlpha="0.5"android:toAlpha="1.0"android:duration="300"/>
</set>
fragment_bottom_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromYDelta="0%p"android:toYDelta="100%p"android:duration="300"/><alphaandroid:fromAlpha="1.0"android:toAlpha="0.5"android:duration="300"/>
</set>
具体效果如下:
仿选股宝选个头条上下拉加载一页的功能相关推荐
- uniapp弹出框_uniApp上拉刷新,下拉加载,以及筛选功能
uniApp插件市场有很多友好的插件,今天举一个例子 如上图所示,实现上拉刷新,下来加载,右上角点击弹出筛选框,只需要在插件市场搜索刷新 选择你想要的效果(也可以下载后自己改动效果) 点击导入插件,会 ...
- Android_ListView上拉加载更多(ListView分页功能)
先上效果图 加载完数据 首先定义一个底部正在加载的布局footer_layout.xml <?xml version="1.0" encoding="utf-8&q ...
- Android RecyclerView(八)设置自定义 下拉刷新 与 上拉加载数据
Android RecyclerView(八)设置下拉刷新 与 上拉加载数据 GitHub 项目源码 CSDN 博客说明 智慧安卓App 文章分析 下拉刷新效果 上拉加载数据效果 1 xml布局文件中 ...
- ListView上拉加载和下拉刷新多种实现方式
ListView上拉加载和下拉刷新多种实现方式 该篇为ListView下拉刷新和上拉加载实现的各种方法大合集.可能在具体的细节逻辑上处理不太到位,但基本上完成逻辑的实现.细节方面,个人可以根据自己的需 ...
- 仿头条新闻app,实现下拉刷新,上拉加载分页
---恢复内容开始--- 环境appcan appcan.ready(function() {page = 1;type = 0;searchDate = getNowTime();highSearc ...
- ASP.NET仿新浪微博下拉加载更多数据瀑布流效果
闲来无事,琢磨着写点东西.貌似页面下拉加载数据,瀑布流的效果很火,各个网站都能见到各式各样的展示效果,原理大同小异.于是乎,决定自己写一写这个效果,希望能给比我还菜的菜鸟们一点参考价值. ...
- iOS高仿微信、仪表盘、图片标注图片滤镜、高斯模糊、上拉加载、下拉刷新等源码
iOS精选源码 Swift-图片画框标注 Swift版的上拉加载, 下拉刷新控件(一句话集成, 超级易用) iOS tabbar上的提示框 Swift图片浏览器,经过一年多维护,已基本稳定 图片滤镜 ...
- iOS高仿微信、仪表盘、图片标注图片滤镜、高斯模糊、上拉加载、下拉刷新等源码...
iOS精选源码 Swift-图片画框标注 Swift版的上拉加载, 下拉刷新控件(一句话集成, 超级易用) iOS tabbar上的提示框 Swift图片浏览器,经过一年多维护,已基本稳定 图片滤镜 ...
- listview下拉刷新上拉加载扩展(三)-仿最新版美团外卖
本篇是基于上篇listview下拉刷新上拉加载扩展(二)-仿美团外卖改造而来,主要调整了headview的布局,并加了两个背景动画,看似高大上,其实很简单: as源码地址:http://downloa ...
最新文章
- 布Sendmail之网,安全则不漏(上)
- Delphi Code Editor 之 编辑器选项
- 编译原理练习题(第三章)
- opencv画框返回坐标 python_python opencv鼠标事件实现画框圈定目标获取坐标信息
- 全球及中国益生菌市场应用发展与投资前景调研报告2022版
- 云服务器建站原理_云服务器cvm与建站主机之间的区别
- LeetCode MySQL 1587. 银行账户概要 II
- Spring 整合junit
- 一步一步教你玩转.NET Framework的配置文件app.config (转载)
- Docker安装迅雷下载工具实现远程下载
- 电子政务工程建设项目可行性研究报告编制要求
- 华为2018届校园招聘笔试题目以及相应代码分享 软件开发岗位
- 解决vscode的任务栏白色图标的问题
- 京东2022双11预售期,商家该做些什么?
- 中值滤波Median filtering
- C语言三个数相乘怎么写,编程怎么写乘法
- 光纤快速连接器如何安装使用?与冷接子有何区别?
- linux mint卸载桌面环境,在Ubuntu系统中安装最新Cinnamon桌面环境,包括启用及卸载...
- 数据中台架构与技术选型
- 下载Nexus老版本war包