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日常问题解…...
从零搭建OpenStack私有云:我是如何用两台旧电脑打造个人开发测试平台的
从零搭建OpenStack私有云:我是如何用两台旧电脑打造个人开发测试平台的 去年整理仓库时发现两台闲置的旧台式机,配置都是i5-6500加16GB内存。看着它们积灰实在可惜,我决定用这两台"老伙计"搭建一个OpenStack私有云环境,…...
Ubuntu20.04安装Mapviz避坑指南:解决Qt与OpenCV冲突,手把手配置天地图
Ubuntu20.04安装Mapviz避坑指南:解决Qt与OpenCV冲突,手把手配置天地图 在ROS开发中,地图可视化工具Mapviz因其强大的插件系统和高度可定制性备受青睐。然而,Ubuntu20.04环境下安装Mapviz时,Qt版本冲突和OpenCV链接错误…...
Sora 2生成帧精度达99.7%的LUT匹配方案,DaVinci色彩科学全链路对齐指南
更多请点击: https://kaifayun.com 第一章:Sora 2与DaVinci整合的底层逻辑与技术共识 Sora 2 作为新一代视频生成基础模型,其核心能力建立在时空联合建模与长程依赖捕获之上;DaVinci 则是面向专业影视工作流的高性能非线性编辑与…...
6G通信中的HMA天线技术:原理、优势与应用
1. HMA天线技术概述在6G通信和大规模MIMO系统的发展背景下,Huygens Metasurface Antennas(HMA)技术正逐渐成为无线通信领域的研究热点。作为一名长期从事天线系统设计的工程师,我见证了从传统相控阵到现代超表面天线的技术演进历程…...
phpenv终极指南:5分钟掌握PHP多版本管理的完整解决方案
phpenv终极指南:5分钟掌握PHP多版本管理的完整解决方案 【免费下载链接】phpenv Simple PHP version management 项目地址: https://gitcode.com/gh_mirrors/ph/phpenv 还在为不同PHP项目间的版本冲突而烦恼吗?phpenv为您提供了一站式PHP版本管理…...
【限时解密】Perplexity写作辅助底层架构图首次公开:基于逆向分析的7大能力边界与替代方案评估
更多请点击: https://codechina.net 第一章:Perplexity写作辅助功能的定位与核心价值 Perplexity并非传统意义上的语法校对工具或模板生成器,而是一个以“问题驱动、证据锚定”为核心范式的智能写作协作者。它将用户输入的写作任务自动解构为…...
别死磕数据线!聊聊EMMC BGA布线里那些能删掉的‘废脚’
别死磕数据线!EMMC BGA布线中那些被忽略的"废脚"优化策略 在PCB layout工程师的日常工作中,EMMC存储器的BGA封装布线常常让人头疼不已。0.5mm的球间距、密集的数据线、严格的阻抗要求,这些因素叠加在一起,往往让设计者…...
指纹采集器模块选型指南|如何选择合适的指纹采集模块
在做指纹门禁、指纹考勤、指纹保险箱或嵌入式终端时, 指纹采集器模块几乎是整个系统的核心。 模块选对了,项目推进顺畅;选错了,后期调试、售后问题不断。 本文不讲复杂参数,只从实际应用出发, 用最通俗的方…...
今日算法(二叉树剪枝)
题目描述给你二叉搜索树的根节点 root,同时给定最小边界 low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在 [low, high] 中。修剪树不应该改变保留在树中的元素的相对结构(即如果没有被移除,原有的父子代关系都应当保…...
初次使用Taotoken完成模型调用从注册到收到响应的全过程记录
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 初次使用Taotoken完成模型调用从注册到收到响应的全过程记录 作为一名开发者,当需要将大模型能力集成到自己的项目中时…...
