【RecyclerView与Glide】实现一个Android电子书阅读APP

http://www.cnblogs.com/xfangs/

欢迎在本文下方评论,小方很需要鼓励支持!!!

本系列教程仅供学习交流

小说阅读器最终实现效果见 一篇博文



前言

在上一篇文章中,我们实现了ViewPager的基本功能,按照计划,制作咱们的电子书阅读app需要使用ViewPager插入两页视图,一个用来显示当前书架,一个用来展示不同的分类。这一节,我们将在被标记为find的页面上实现分类选项。

涉及组件或框架:RecyclerView、Glide



首先·布局

同样的,在这里,小方因为水平有限只能简单介绍RecyclerView的基本使用方法,涉及到更深奥的操作部分,就无能为力了。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical" android:layout_width="match_parent"
 4     android:layout_height="match_parent">
 5
 6     <android.support.v7.widget.RecyclerView
 7         android:id="@+id/recyler_view_find_book"
 8         android:layout_margin="8dp"
 9         android:layout_width="match_parent"
10         android:layout_height="match_parent"/>
11
12 </LinearLayout>

没有复杂的步骤,我们只需要把RecyclerView加入到之前ViewPager的两个布局之一中,就完成了整个列表布局。

当然,你也许会遇到一些意外。

这是说明我们还没有引入RecyclerView这个库,进入Design界面,从左边的组件中找到RecyclerView,单击,将会弹出选择框。

在加入了库之后,我们就能看到RecyclerView正确无误的显示在界面上了。

适配器

这次我们工作的主战场在上一节提到的Fragment,也就是ViewPager的两个页面之一。

回顾一下代码。

 1     public static class FindBooksFragment extends Fragment {
 2
 3         public FindBooksFragment() {
 4         }
 5
 6         @Override
 7         public View onCreateView(final LayoutInflater inflater, ViewGroup container,
 8                                  Bundle savedInstanceState) {
 9
10             View rootView = inflater.inflate(R.layout.pager_book_find, container, false);
11
12             return rootView;
13         }
14
15     }

之前说了,ViewPager会在创建这个页面的时候调用onCreateView这个函数,所以我们在这里进行初始化操作。

在这之前,我们需要先完成RecyclerView的适配器,同样的,这里适配器起到将数据和页面结合到一起的作用,具体地说,假设一个列表中的项目可以分为三类,我们就为这三类元素分别设计布局,然后将每一项的数据传给适配器,适配器可以根据数据选择对应的布局,然后把每一项显示出来。

首先,新建一个类。

关于RecyclerView的适配器,网络上已经有很多博客描述了, 随意找一篇看的过去的文章,先大体了解一下。

。。。搜索时间。。。

了解过后,我们知道需要为列表项写布局,这在前面也间接提到了。

那么,新建一个布局文件

book_find_item.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:id="@+id/bookFind_cardview"
 5     android:layout_width="match_parent"
 6     android:layout_height="wrap_content"
 7     android:layout_margin="4dp"
 8     android:foreground="?android:attr/selectableItemBackground"
 9     android:clickable="true">
10
11     <ImageView
12         android:id="@+id/bookFind_image"
13         android:layout_width="match_parent"
14         android:layout_height="150dp"
15         android:scaleType="centerCrop"
16         tools:src="@color/cardview_dark_background"/>
17
18     <TextView
19         android:id="@+id/bookFind_class"
20         android:layout_width="match_parent"
21         android:layout_height="match_parent"
22         android:background="#00000000"
23         android:textColor="#FFFFFF"
24         android:textStyle="normal|bold"
25         android:textSize="14sp"
26         android:gravity="center"
27         tools:text="123"/>
28
29 </android.support.v7.widget.CardView>

在这里,我们又使用了一个新的组件,CardView,它体现了安卓最新设计风格,恰到好处的圆角、逼真的阴影、点击特效、等等,有多种属性可供调整。

尤其要说的是上面代码中加粗的字体,一个新的命名空间 tools ,在使用它之前,我们首先要在最外层的部件上声明。

只要打出前面几个字母,android studio 就会自动补全好。

tools 命名空间提供了测试的效果,以他为名号的属性在程序运行期间是被忽略的,只供测试预览使用,使得开发更加方便了。下图就是我们预览时得到的效果,

当程序运行起来时, 还会是如图所示的样子吗?

(必然不是)

制作好了布局文件,我们就可以开始对适配器进行编写了。

首先制作一个接口,用来获取点击事件。

 1     private OnItemClickListener listener;
 2
 3     public void setOnItemClickListener(OnItemClickListener listener) {
 4         this.listener = listener;
 5     }
 6
 7     public interface OnItemClickListener {
 8         void onItemClick(View view, int position);
 9         void onItemLongClick(View view, int position);
10     }

然后在适配器的类中再新建一个类。

 1     static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
 2         View tocView;
 3         private TextView textview_bookFindClass;
 4         private ImageView imageView;
 5         private OnItemClickListener listener;
 6
 7         public ViewHolder(View itemView, OnItemClickListener l) {
 8             super(itemView);
 9             tocView = itemView;
10             textview_bookFindClass = (TextView) itemView.findViewById(R.id.bookFind_class);
11             imageView = (ImageView) itemView.findViewById(R.id.bookFind_image);
12             listener = l;
13             itemView.setOnClickListener(this);
14             itemView.setOnLongClickListener(this);
15         }
16
17
18         @Override
19         public void onClick(View v) {
20             if (listener != null) {
21                 listener.onItemClick(v, getAdapterPosition());
22             }
23         }
24
25         @Override
26         public boolean onLongClick(View v) {
27             if (listener != null) {
28                 listener.onItemLongClick(v, getAdapterPosition());
29             }
30             return false;
31         }
32     }

可能略显复杂,这个类的作用是缓存列表项,具体比较低层的东西小方就不太清楚了,上网搜了搜,就不现学现卖了,欢迎有兴趣的同学一起讨论。

ViewHolder 类继承自 RecyclerView.ViewHolder,为了实现点击监听,还要接入两个接口,一个是单击的接口,一个是长按的接口。

从构造函数开始一点一点理解,构造函数接收两个参数,一个是每一项的View,一个是每一项的点击监听器。初始化组件之后,设置监听器,按照之前设置的接口的设定,将View和位置传给借口。

如果还不是很清楚,那么先将代码复制过去,使用次数多了,自然就理解了。

然后,在AdapterBookFind这个类中,完成它的构造函数,这里是根据需要自行设定的,在这里我们需要将分类名称传给适配器,显示在每一项上,所以传送了一个字符串列表。你也可以根据自己的需要传送想要传送的数据。

1     private ArrayList<String> myCategory;
2
3     public AdapterBookFind(ArrayList<String> category) {
4         this.myCategory = category;
5     }

下面我们需要重写一个函数,用来获取一个ViewHolder的实例。

1     private Context context;
2     @Override
3     public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
4         View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.book_find_item, parent, false);
5         context = parent.getContext();
6         final ViewHolder holder = new ViewHolder(view, listener);
7
8         return holder;
9     }

在这里,我们又声明了一个叫做context的变量,并初始化,具体作用后面再表。

1     @Override
2     public int getItemCount() {
3         return myCategory.size();
4     }

类似ViewPager的适配器一样,我们同样需要重写取数目的函数,根据数据返回一个值。

马上就到最后一步了,我们将要对列表的每一项设置不同的内容。

 1     @Override
 2     public void onBindViewHolder(final ViewHolder holder, int position) {
 3         holder.textview_bookFindClass.setText(myCategory.get(position));
 4
 5         switch (position) {
 6             case 0:
 7                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
 8                 break;
 9             case 1:
10                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
11                 break;
12             case 2:
13                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
14                 break;
15             case 3:
16                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
17                 break;
18             case 4:
19                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
20                 break;
21             case 5:
22                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
23                 break;
24             case 6:
25                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
26                 break;
27             case 7:
28                 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
29                 break;
30             default:
31
32                 break;
33         }
34         holder.imageView.setColorFilter(Color.parseColor("#55555555"));
35
36     }

因为我们的布局文件中只有两个组件能体现数据的内容,TextView和ImageView。

第三行是根据不同的位置选择不同的字符串进行设置,没有难度。

在说switch之前,我们先来看最后一行

holder.imageView.setColorFilter(Color.parseColor("#55555555"));

给imageView设置滤色,因为我想要在图片之上显示一个白色的文字,适当的使图片变暗,能凸显文字。

switch当然也能看得懂,但是出现了一个陌生的东西 Glide。

实际不难理解,这个switch的作用还是根据不同的位置选择不同的文件进行显示,我们当然可以使用ImageView自带的方法来设置图片,但是ImageView只能设置本地或者APK之中的图片资源,对于网络图片或者诸多不支持的图片类型(如GIF)就毫无办法,不仅如此,当本地图片较大时,还会不可避免的出现卡顿现象。

这时候Glide出现了,它能快速加载各种图片,根据显示大小自动对图片进行压缩,同样一条语句,如果传入图片链接还能加载网络图片,并缓存。

Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);

如上面代码所示的一句话,就能加载APK资源中的一张图片,这里我们只有图标一个文件,所以将图标文件传给了imageView。

不过如果你只是把刚刚的代码复制粘贴到你的工程,你的程序应该会报错,显示没有找到Glide这个东西,这是因为Glide不是官方提供的,我们需要手动引入。

找到上面那个文件。

加入最后一行,选择同步。

这样,我们就引入了Glide。



整合

 1     public static class FindBooksFragment extends Fragment {
 2
 3         public FindBooksFragment() {
 4         }
 5
 6         private RecyclerView recyclerView;
 7         private StaggeredGridLayoutManager staggeredGridLayoutManager;
 8         private AdapterBookFind bookAdapterBookFind;
 9
10         @Override
11         public View onCreateView(final LayoutInflater inflater, ViewGroup container,
12                                  Bundle savedInstanceState) {
13
14             final ArrayList<String> bookClass = new ArrayList<>();
15             bookClass.add("//玄幻");
16             bookClass.add("//武侠");
17             bookClass.add("//都市");
18             bookClass.add("//历史");
19             bookClass.add("//游戏");
20             bookClass.add("//科幻");
21             bookClass.add("//女生");
22             bookClass.add("//所有");
23
24             View rootView = inflater.inflate(R.layout.pager_book_find, container, false);
25             recyclerView = (RecyclerView) rootView.findViewById(R.id.recyler_view_find_book);
26
27             staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
28             recyclerView.setLayoutManager(staggeredGridLayoutManager);
29             bookAdapterBookFind = new AdapterBookFind(bookClass);
30             recyclerView.setAdapter(bookAdapterBookFind);
31
32             bookAdapterBookFind.setOnItemClickListener(new AdapterBookFind.OnItemClickListener() {
33                 @Override
34                 public void onItemClick(View view, int position) {
35                     Log.e(TAG, "onItemClick: 111" );
36                 }
37
38                 @Override
39                 public void onItemLongClick(View view, int position) {
40                     Log.e(TAG, "onItemLongClick: 222" );
41                 }
42             });
43
44             return rootView;
45         }
46
47         private static final String TAG = "FindBooksFragment";
48
49     }

首先初始化我们的字符串列表。StaggeredGridLayoutManager是我们列表的布局管理器,安卓提供了三种布局管理器,用来实现不同的列表效果,多行列表,瀑布流列表,不同的滑动方向都可以进行设置,大家可以百度其他的布局管理器。

所以在27-30行,我们分别为RecyclerView设置了列表管理器和适配器,32行开始,为适配器设置点击监听器,咱们暂时不设置功能,使用log工具将其输出在Android Monitor(log语句有快捷键)。



效果

运行程序,你将见到

我们又完成了新的一节,现在可以尝试更换不同的图片,尝试使用网络图片(不要忘记加入网络访问权限)。

未完待续...下一篇文章讲述使用 litePal 完成书架,敬请期待!!!

时间: 2024-10-05 19:45:05

【RecyclerView与Glide】实现一个Android电子书阅读APP的相关文章

【新建项目&amp;使用viewPager】实现一个Android电子书阅读APP

本章结尾处已放出应用DEMO,已经实现所有本文及后续文章所述全部功能,大家可以先下载下来玩玩看,欢迎在本文下方评论,小方很需要鼓励支持!!! 小说阅读器最终实现效果见上一篇博文 上一篇博文 新建一个项目 呼-我们即将步入安卓开发之旅了,首先要新建一个项目. 选择了开始新项目之后,会打开一个窗口让你设置应用的名字(大写字母开头),还要设置一个类似网址的东西,用来区别不同的开发者,如果你有自己的域名可以像我一样直接设置(宣传一波小方自己的站点-http://xfangfang.cn),或者设置一个自

使用 Vue 和 epub.js 制作电子书阅读器

ePub 简介 ePub 是一种电子书的标准格式,平时我看的电子书大部分是这种格式.在手机上我一般用"多看"阅读 ePub 电子书,在 Windows 上找不到用起来比较顺心的软件,所以很久之前就想折腾一下,自己开发一个 ePub 电子书阅读器.这两天趁着有空,做了一个简单的阅读器.虽然还有些 bug,但基本功能算是齐全了.自己开发的有很多好处,以后只要稍微修改一下,就可以实现导出 HTML 或者 导出 Markdown 的功能,方便保存读书笔记,这一点比大多数软件好用多了. epub

分分钟教你做出自己的新闻阅读APP

分分钟教你做出自己的新闻阅读APP 引子 曾经不小心发现了一些好的看新闻的网站,但是电脑又不是随身携带,因此想要下载一个这个网站的手机APP来看新闻,但是问题来了,这个网站根本没有做Android端!你说用手机浏览器来看?天,有些网站用手机浏览器来看又会出现好些个问题,比如说:广告太多,还有那令人厌恶的弹窗,更有些排版简直让人不忍直视有木有.因此,我萌生出一个自己打造一个新闻阅读器的APP的想法,毕竟以前也玩过Android的开发,虽然是菜鸟级别的,但是做出一个手机新闻阅读APP还是难不倒我的~

如何更好地开发一个Android应用

作为一名android开发工程师(http://www.maiziedu.com/course/android-px/),脑海中经常在想一个问题,如何更好地开发一个android应用?这个问题不仅是android开发工程师,比如总监.CEO等等都在想这样一个问题.面向开发者,开发主管,总监,CEO等.更好地开发一个android应用主要做到三个大点,就足矣. 项目定义 不同类型的项目当以不同的处理方式. 1. 项目型 该类型项目,重点在于完成项目,取决于客户需求,或难或易,开发者能做的就是深入挖

一个类的阅读,分析

阅读到这么个类: public class FileDownloadList { /**上下文*/ private Context mContext; /**请求对象*/ private BaseRequestLims fileRequest = null; /**进度条对话框*/ private AlertDialog progressDialog = null; /**进度条控件变量*/ private ProgressBar mProgress; /**百分比显示控件*/ private

电子书阅读软件的功能

作者:马健邮箱:[email protected]发布:2015.01.03 从ComicsViewer(CV).MyReader(MR).PageByPage(PBP)到UnicornViewer(UV),几年间我已经发布了几款电子书阅读软件,分别针对扫描版电子书籍 包括漫画/连环画/PDG(CV.UV).HTML书籍(MR).纯文本书籍(MR.PBP).PDG/PDF/DjVu/TIFF(UV)等.有心人可能已经注意到,这些软件都有一些共同的功能,这些功能也是我认为一款电子书阅读软件所应该具

Android官方入门文档[1]创建一个Android项目

Android官方入门文档[1]创建一个Android项目 创建一个Android项目 这节课教你1.创建与Android Studio中的一个项目2.创建使用命令行工具项目 你也应该阅读?管理项目 Creating an Android Project This lesson teaches you to1.Create a Project with Android Studio2.Create a Project with Command Line Tools You should also

电子书阅读及工具

我现在看电子书,除了计算机以外,还常使用 ipad mini 和 kindle.所讨论的工具都在这三个平台上. 后半部分讲的内容才是工具,前半部分是历史回顾.只对工具感兴趣的,请向下翻页. 1. 我最初读的电子读物,应该是 qbasic 的手册.当时还不知道有电子读物或者手册这回事,常问张仕鹏师兄问题,只要见他在机房,就死皮赖脸地去问.有一次问到红色的颜色编号到底是多少,他终于受不了,告诉我按F1键,说:你自己看手册吧.然后,我就开始漫长的手册阅读生涯,也因此有幸学会 RTFM 比身边常有一个高

电子书阅读器安卓版推荐 PDF阅读器也可轻松编辑文档了

在电子书的各种格式中,你最青睐哪种呢?是mobi.txt.还是PDF,相信很多人和小编一样喜欢阅读 PDF格式的电子书,这时候选择一款合适的PDF阅读器就十分重要了.那么,电子书阅读软件哪个好呢? 在回答这个问题之前,我们先考虑这样一个问题,我们需要一款什么样的PDF阅读器?是只满足基本的阅读功能就可以了么?想必很多人都不满足于这吧.小编今天推荐的这款轻快PDF阅读器的功能就十分齐全,不信且往下看: 一.我们需要什么样的阅读功能? 1.自动添加手机内的PDF文件:这点应该没什么意见吧,毕竟很多人