Android RecyclerView 之 列表宫格布局的切换
前言
RecyclerView 的使用我就不再多说,接下来的几篇文章主要说一下 RecyclerView 的实用小功能,包括 列表宫格的切换,吸顶效果,多布局效果等,今天这篇文章就来实现一下列表宫格的切换,效果如下

一、数据来源
数据来源于知乎日报API,采用 okhttp+retrofit 组合方式请求获取,网络请求没有进行二次封装,只是简单请求数据源,对于有需求的用户自行进行封装修改。
二、使用步骤
1.引入库
//万能适配器implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'//卡片布局implementation 'androidx.cardview:cardview:1.0.0'//图片加载implementation 'com.github.bumptech.glide:glide:4.9.0'//json解析implementation 'com.alibaba:fastjson:1.2.61'//标题栏implementation 'com.github.goweii:ActionBarEx:3.2.2'// 只引入ActionBarEximplementation 'com.github.goweii.ActionBarEx:actionbarex:3.2.2'// 引入ActionBarCommon/Search/Super,依赖于ActionBarEximplementation 'com.github.goweii.ActionBarEx:actionbarex-common:3.2.2'
2.获取数据
使用如下 URL 进行数据请求:API 使用的 HTTP Method 均为 GET
https://news-at.zhihu.com/api/3/news/hot
响应实例:
{"recent": [{"news_id": 3748552,"thumbnail": "http://p3.zhimg.com/67/6a/676a8337efec71a100eea6130482091b.jpg","title": "长得漂亮能力出众性格单纯的姑娘为什么会没有男朋友?","url": "http://daily.zhihu.com/api/2/news/3748552"}]
}
根据实例生成实体类 NewsListBean 实现序列换接口 Serializable
public class NewsListBean implements Serializable {private String date;private List<Recent> recent;public String getDate() {return date;}public void setDate(String date) {this.date = date;}public List<Recent> getRecent() {return recent;}public void setRecent(List<Recent> recent) {this.recent = recent;}public static class Recent implements Serializable {private String news_id;private String thumbnail;private String title;private String url;public String getNews_id() {return news_id;}public void setNews_id(String news_id) {this.news_id = news_id;}public String getThumbnail() {return thumbnail;}public void setThumbnail(String thumbnail) {this.thumbnail = thumbnail;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}}
}
写一个 接口类用来管理 API ,可以单独放在一个文件夹下
public interface ApiUrl {@GET("/api/4/news/hot")Call<NewsListBean> getPic();}
3.主要代码
1 activity_main.xml
这里使用了三方库 ActionBarEx 实现了沉浸式标题栏,使用了系统的 ProgressBar 实现请求加载框
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><per.goweii.actionbarex.ActionBarExandroid:id="@+id/abc_main_return"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#14a4fb"app:ab_autoImmersion="false"app:ab_bottomLineColor="#f3f3f3"app:ab_bottomLineHeight="0dp"app:ab_statusBarColor="#00000000"app:ab_statusBarMode="dark"app:ab_statusBarVisible="true"app:ab_titleBarHeight="50dp"app:ab_titleBarLayout="@layout/top" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/zh_lv"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/abc_main_return" /><ProgressBarandroid:id="@+id/progressbar"style="@style/Base.Widget.AppCompat.ProgressBar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:visibility="gone" />
</RelativeLayout>
2 zh_item_layout.xml
列表子布局 ,采用 CardView 卡片布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/zh_card_View"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/dp_10"android:layout_marginTop="10dp"android:layout_marginRight="@dimen/dp_10"android:layout_marginBottom="@dimen/dp_10"app:cardBackgroundColor="#ffffff"app:cardCornerRadius="10dp"app:cardElevation="10dp"app:cardPreventCornerOverlap="true"app:cardUseCompatPadding="false"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="120dp"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/transparent"><ImageViewandroid:id="@+id/news_image"android:layout_width="70dp"android:layout_height="70dp"android:layout_centerVertical="true"android:layout_margin="10dp"android:elevation="2dp"android:scaleType="fitXY" /><TextViewandroid:id="@+id/news_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginStart="10dp"android:layout_marginTop="10dp"android:layout_marginEnd="10dp"android:layout_toEndOf="@id/news_image"android:ellipsize="end"android:maxEms="15"android:singleLine="true"android:textColor="@color/black"android:textSize="20sp" /></RelativeLayout></RelativeLayout></androidx.cardview.widget.CardView>
3 zh_grid__item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/zh_card_View"android:layout_width="match_parent"android:layout_height="180dp"android:layout_marginLeft="@dimen/dp_10"android:layout_marginTop="10dp"android:layout_marginRight="@dimen/dp_10"android:layout_marginBottom="@dimen/dp_10"app:cardBackgroundColor="#ffffff"app:cardCornerRadius="10dp"app:cardElevation="10dp"app:cardPreventCornerOverlap="true"app:cardUseCompatPadding="false"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/transparent"android:gravity="center"android:orientation="vertical"android:padding="@dimen/dp_10"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="3"><ImageViewandroid:id="@+id/news_image"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center"><TextViewandroid:id="@+id/news_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:ellipsize="end"android:maxEms="8"android:singleLine="true"android:textColor="@color/black"android:textSize="20sp" /></LinearLayout></LinearLayout></androidx.cardview.widget.CardView>
4 NewsListAdapter 适配器
public class NewsListAdapter extends BaseQuickAdapter<NewsListBean.Recent, BaseViewHolder> {public NewsListAdapter(int layoutResId, @Nullable List<NewsListBean.Recent> data) {super(layoutResId, data);}@Overrideprotected void convert(@NonNull BaseViewHolder helper, NewsListBean.Recent item) {helper.setText(R.id.news_title, item.getTitle());String img = item.getThumbnail();ImageView newsImage = helper.getView(R.id.news_image);Glide.with(mContext).asBitmap().load(img).diskCacheStrategy(DiskCacheStrategy.ALL).into(newsImage);helper.addOnClickListener(R.id.zh_card_View);}}
5 BaseActivity 基类
public abstract class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {Window window = getWindow();// 5.0以上系统状态栏透明if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.setStatusBarColor(Color.TRANSPARENT);}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// 全屏显示,隐藏状态栏和导航栏,拉出状态栏和导航栏显示一会儿后消失。window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE// | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION// | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION// | View.SYSTEM_UI_FLAG_FULLSCREEN| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);} else {// 全屏显示,隐藏状态栏window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);}}//预防软键盘挡住输入框getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);//禁止横屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);super.onCreate(savedInstanceState);}}
6 MainActivity 主要代码
这里主要通过一个 boolean 值 isGrid 来判断是否切换状态来加载不同的布局,以及布局管理器来达到实际效果
public class MainActivity extends BaseActivity {private RecyclerView zhLv;private ProgressBar proBar;private NewsListAdapter adapter;private List<NewsListBean.Recent> mList = new ArrayList<>();private static final int REQUEST_EXTERNAL_STORAGE = 1;private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};private ImageView menuBtn;private LinearLayoutManager layoutManager;private ImageView btnImg;private LinearLayout backLayoput;public static void verifyStoragePermissions(Activity activity) {int permission = ActivityCompat.checkSelfPermission(activity,Manifest.permission.WRITE_EXTERNAL_STORAGE);if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);}}private boolean isGrid = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);verifyStoragePermissions(MainActivity.this);initView();initData();menuBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {switchLayout();}});}private void switchLayout() {if (isGrid) {layoutManager = new LinearLayoutManager(this);adapter = new NewsListAdapter(R.layout.zh_item_layout, mList);zhLv.setAdapter(adapter);} else {layoutManager = new GridLayoutManager(this, 2);adapter = new NewsListAdapter(R.layout.zh_grid__item_layout, mList);zhLv.setAdapter(adapter);}zhLv.setLayoutManager(layoutManager);isGrid = !isGrid;}private void initView() {zhLv = findViewById(R.id.zh_lv);proBar = findViewById(R.id.progressbar);menuBtn = findViewById(R.id.btn_main_menu);btnImg = findViewById(R.id.btn_main_menu);backLayoput = findViewById(R.id.btn_back_layout);backLayoput.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {finish();}});layoutManager = new LinearLayoutManager(MainActivity.this);zhLv.setLayoutManager(layoutManager);adapter = new NewsListAdapter(R.layout.zh_item_layout, mList);zhLv.setAdapter(adapter);}private void initData() {proBar.setVisibility(View.VISIBLE);Retrofit retrofit = new Retrofit.Builder().baseUrl("https://news-at.zhihu.com/")//设置数据解析器.addConverterFactory(GsonConverterFactory.create()).build();ApiUrl apiUrl = retrofit.create(ApiUrl.class);Call<NewsListBean> call = apiUrl.getPic();call.enqueue(new Callback<NewsListBean>() {@Overridepublic void onResponse(Call<NewsListBean> call, Response<NewsListBean> response) {List<NewsListBean.Recent> recent = response.body().getRecent();if (response.body() != null && recent.size() > 0) {try {mList.addAll(recent);adapter.setNewData(mList);proBar.setVisibility(View.GONE);} catch (Exception e) {String message = e.getMessage();e.printStackTrace();}}}@Overridepublic void onFailure(Call<NewsListBean> call, Throwable t) {Log.e("mmm", "errow " + t.getMessage());}});}}
总结
一个小小的很实用的功能就完成了,下一篇文章会接着实现RecyclerView 吸顶效果,后续还会加上列表本地缓存等功能,Demo 在此系列文章完结附上,不妨点赞收藏哦~
青山不改,绿水长流 有缘江湖再见 ~
相关文章:
Android RecyclerView 之 列表宫格布局的切换
前言 RecyclerView 的使用我就不再多说,接下来的几篇文章主要说一下 RecyclerView 的实用小功能,包括 列表宫格的切换,吸顶效果,多布局效果等,今天这篇文章就来实现一下列表宫格的切换,效果如下 一、数据来…...
妈妈的爱依然深沉
村里的孩子为了买化肥,跟城里官老爷们借了好多钱。 那几年庄稼转手很快,不是用来吃的,因此借钱成本很高,大概LPR加100bp。 后来村里孩子终于发现庄稼终究只能用来吃,不再热衷买卖化肥。可是官老爷们的金融生意还要继续…...
net.ResolveTCPAddr(“tcp6“, address)
尝试解析 "www.google.com" 的IPv6地址。如果解析成功,程序将打印出解析后的IP地址、端口以及区域信息。如果解析失败,程序将打印出错误信息。 需要注意的是,如果 "www.google.com" 没有IPv6地址,或者本地网络…...
mysql和mybatisPlus实现:datetime类型的字段范围查询
前提说明 数据库在存储数据时,我们为了精确一下时间,便会把改时间类型的字段设置为datetime类型; 在过滤数据库数据时,我们又需要对该字段进行一个范围的过滤 由此,便出现了这篇博客 datetime数据类型 在MySQL中,datetime数据类型用于保存日期和时间的值。它的格式为Y…...
学习笔记:用ROS接收rosbag发布的topic
用ROS接收 bag.open发布的topic python语言 要使用ROS接收保存在rosbag文件中的话题消息,可以按照以下步骤进行操作: 1.首先,请确保你已经安装了ROS和相关的依赖。 2.创建一个ROS功能包(或使用现有的功能包)来处理…...
LAMP架构介绍配置命令讲解
LAMP架构介绍配置命令讲解 一、LAMP架构介绍1.1概述1.2LAMP各组件的主要作用1.3各组件的安装顺序 二、编译安装Apache httpd服务---命令讲解1、关闭防火墙,将安装Apache所需的软件包传到/opt/目录下2、安装环境依赖包3、配置软件模块4、编译安装5、优化配置文件路径…...
C语言之函数题
目录 1.乘法口诀表 2.交换两个整数 3.函数判断闰年 4.函数判断素数 5.计算斐波那契数 6.递归实现n的k次方 7.计算一个数的每位之和(递归) 8.字符串逆序(递归实现) 9.strlen的模拟(递归实现) 10.求…...
SpringBoot的四种handler类型
Controller ReuestMapping 实现Controller接口 使用Component将该类封装成一个Bean 实现HttpRequestHandler 实现RouterFunction...
基于KNN算法的鸢尾花种类预测
导入数据 iris_data load_iris() iris_data.data[0:5, :]array([[5.1, 3.5, 1.4, 0.2],[4.9, 3. , 1.4, 0.2],[4.7, 3.2, 1.3, 0.2],[4.6, 3.1, 1.5, 0.2],[5. , 3.6, 1.4, 0.2]])# 特征值名称 iris_data.feature_names[sepal length (cm),sepal width (cm),petal length (cm…...
英语-面试
自我介绍 hi,my name is tzh,26 years old.I major in software engineering. I participate in the design and development of the social project and e-commerce project. I master java and algorithm. Im familiar with gateway,spring,springboot,springcloud,redis…...
文件传输协议
文章目录 一、FTP1. 定义2. 端口3. 数据传输方式主动方式被动方式 二、TFTP三、常用命令 首先可以看下思维导图,以便更好的理解接下来的内容。 一、FTP 1. 定义 文件传输协议(FTP)是一种用于在客户端和服务器之间进行文件传输的标准网络协…...
Llama-2大模型本地部署研究与应用测试
最近在研究自然语言处理过程中,正好接触到大模型,特别是在年初chatgpt引来的一大波AIGC热潮以来,一直都想着如何利用大模型帮助企业的各项业务工作,比如智能检索、方案设计、智能推荐、智能客服、代码设计等等,总得感觉…...
白嫖idea
白嫖idea 地址 https://www.jetbrains.com/toolbox-app/...
PyCharm切换虚拟环境
PyCharm切换虚拟环境 为了满足不同任务需要不同版本的包,可以在Anaconda或者Miniconda创建多个虚拟环境文件夹,并在PyCharm下切换虚拟环境。 解决方案 1、打开Ananconda Prompt 2、创建自己的虚拟环境 格式:conda create -n 虚拟环境名字…...
自动化运维工具-----Ansible入门详解
目录 一.Ansible简介 什么是Ansible? Ansible的特点 Ansible的架构 二.Ansible任务执行解析 ansible任务执行模式 ansible执行流程 ansible命令执行过程 三.Ansible配置解析 ansible的安装方式 ansible的程序结构(yum安装为例) ansibl…...
一、Mycat2介绍与下载安装
第一章 入门概述 1.1 是什么 Mycat 是数据库中间件。 1、数据库中间件 中间件:是一类连接软件组件和应用的计算机软件,以便于软件各部件之间的沟 通。 例子:Tomcat,web中间件。 数据库中间件:连接java应用程序和数据库…...
链表的介绍
链表是一种常用的数据结构,它可以动态地添加、删除、查找和遍历元素。链表由多个节点组成,每个节点包括一个数据项和一个指向下一个节点的指针。这种数据结构可以高效地插入和删除元素,但相对于数组来说,查找元素的效率较低。 插…...
深度剖析:数据服务API的安全性与隐私保护
随着互联网技术的飞速发展,数据服务API已经成为了企业和个人获取、处理和分析数据的重要工具。然而,数据服务API的安全问题也日益凸显,尤其是在用户隐私保护方面。本文将深入剖析数据服务API的安全性与隐私保护问题,并结合产品FDL…...
MediaPlayer音频与视频的播放介绍
作者:向阳逐梦 Android多媒体中的——MediaPlayer,我们可以通过这个API来播放音频和视频该类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最小的步骤来获取,解码和播放音视频。 它支持三种不同的媒体来源…...
【Terraform学习】Terraform模块基础操作(Terraform模块)
本站以分享各种运维经验和运维所需要的技能为主 《python》:python零基础入门学习 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…...
告别单片机!用Multisim 10.0和74LS192芯片,手把手教你搭一个30秒倒计时器(附完整电路图)
数字电路实战:用Multisim与74LS192打造精准30秒倒计时器 在电子设计领域,倒计时器是一个经典而实用的项目。传统上,许多初学者会直接选择单片机方案,认为编程控制更为简单。但真正理解数字电路的工作原理,掌握硬件层面…...
从电商搜索到内容审核:微调后的Chinese-CLIP模型还能这么用?
从电商搜索到内容审核:微调后的Chinese-CLIP模型还能这么用? 当电商平台每天新增数百万商品时,如何快速识别违规商品图片?当社交媒体需要审核海量用户上传的图文内容时,如何高效判断图文匹配度?这些看似不同…...
2025版等级保护测评报告模板:风险导向与合规深化的实践指南
1. 2025版等级保护测评报告模板的核心变革 如果你最近接触过等级保护测评工作,一定会注意到2025版报告模板带来的显著变化。这个版本最大的特点就是从过去的"得分导向"彻底转向了"风险导向"。在实际工作中,我发现很多企业安全负责人…...
工业现场直通车:用C#和雷赛DMC3000库,从零搭建一个真实的运动控制上位机
工业现场直通车:用C#和雷赛DMC3000库构建高可靠运动控制上位机 在工业自动化领域,运动控制系统的稳定性和实时性直接决定了生产效率和产品质量。许多开发者从教学Demo过渡到实际工业应用时,常常面临理论与实践的断层——教材中的理想化代码无…...
ProperTree三分钟精通:跨平台Plist编辑器的核心工作流指南
ProperTree三分钟精通:跨平台Plist编辑器的核心工作流指南 【免费下载链接】ProperTree Cross platform GUI plist editor written in python. 项目地址: https://gitcode.com/gh_mirrors/pr/ProperTree ProperTree是一款采用Python和Tkinter开发的跨平台GUI…...
QMCFLAC2MP3深度解析:从格式解密到跨设备音频转换的全流程实践
QMCFLAC2MP3深度解析:从格式解密到跨设备音频转换的全流程实践 【免费下载链接】qmcflac2mp3 直接将qmcflac文件转换成mp3文件,突破QQ音乐的格式限制 项目地址: https://gitcode.com/gh_mirrors/qm/qmcflac2mp3 问题引入:破解音乐格式…...
5分钟掌握YetAnotherKeyDisplayer:专业按键可视化工具终极指南
5分钟掌握YetAnotherKeyDisplayer:专业按键可视化工具终极指南 【免费下载链接】YetAnotherKeyDisplayer The application for displaying pressed keys of the keyboard 项目地址: https://gitcode.com/gh_mirrors/ye/YetAnotherKeyDisplayer YetAnotherKey…...
【毕业设计】微信小程序文创商城-从真实支付到模拟支付的实现与优化
1. 微信小程序文创商城支付功能概述 做毕业设计选择微信小程序文创商城是个不错的选题,尤其是支付功能的实现,既能锻炼技术能力,又很实用。我去年指导过几个类似的项目,发现学生们最头疼的就是支付模块。真实支付需要营业执照和公…...
别再傻傻编译整个内核了!香橙派3B (rk3566) 快速修改和测试设备树节点的正确姿势
香橙派3B设备树节点高效调试指南:从编译优化到实战技巧 每次修改设备树节点都要重新编译整个内核?等待十几分钟甚至更久只为了验证一个小改动?对于香橙派3B(rk3566)开发者来说,这种低效的工作流程已经成为过去。本文将揭示一套经…...
微信小程序uView实战:u-picker三级联动避坑指南(附完整代码)
uView框架下u-picker三级联动的深度实践与性能优化 在微信小程序开发中,地区选择器几乎是每个涉及用户地址功能的必备组件。uView作为一款优秀的小程序UI框架,其u-picker组件提供了强大的多级联动功能,但在实际开发中,不少开发者会…...
