博主声明:
转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。
本文首发于此 博主:威威喵 | 博客主页:https://blog.csdn.net/smile_running
感受 Material Design UI 魅力,你不能错过的 Material Design 全系列文章:
Material Design 之一 BottomNavigationView + ViewPager + Fragment 仿微信底部导航效果
Material Design 之二 Toolbar + DrawerLayout + NavigationView 实现QQ侧拉抽屉效果
Material Design 之三 TabLayout + ViewPager + Fragment 今日头条标题切换效果
Material Design 之四 SwipeRefreshLayout + CardView + RecyclerView 精美瀑布流效果
Material Design 之五 CoordinatorLayout + AppBarLayout 提供最佳浏览体验
Material Design 之六 CollapsingToolbarLayout + FloatingActionButton 打造精美详情界面
Material Design 之七 TextInputLayout+TextInputEditText 打造精美的登录界面
RecyclerView 是我们 Android 开发中必备的控件之一,可以说基本每一个复杂一点的界面都需要 RecyclerView 来帮助处理,因为 RecyclerView 的可定制性非常高,我们可以玩出各种花样来。
不仅如此,RecyclerView 自带的三种布局形式,比如线性、网格、瀑布流都非常容易就能用上的,我们可以根据需要,自行的设置页面样式,接下来,我们使用 RecyclerView 来使用一下这三种布局,并且配合 design 库下的 CardView 控件,制作一个精美的动物信息浏览的界面。
先看看效果图吧:
在此之前呢,我们把准备工作给做好,第一个是我的代码是沿用上篇文章:TabLayout+ViewPager 快速实现标题切换效果
第二个是由于本次图片的量比较大,因为我们在 RecyclerView 中要引入大量的图片来浏览,所以不得不使用第三方开源的图片加载库,这也是为了方便。
首先,在 app 项目中引入 Glide 图片加载库,sync 一下会自动下载:
implementation 'com.github.bumptech.glide:glide:4.9.0'
然后它的用法非常简单,比如这样:
Glide.with(context).load(data.get(i).get("pic")).into(holder.img);
好了,基于这个代码上, 我们添加一个线性布局的 RecyclerView
然后,它的 Item 布局文件如下:
接下来是它的适配器,在适配器中设置 item 布局和加载每一个 item 的数据:
package nd.no.xww.bottomnavigationlayout;
import android.content.Context;
import android.media.Image;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.List;
import java.util.Map;
/**
* @author xww
* @desciption :
* @date 2019/7/24
* @time 12:06
*/
public class RecyclerLineAdapter extends RecyclerView.Adapter {
Context context;
List
添加数据源和设置适配器
int[] pics = {
R.drawable.a1,
R.drawable.a2,
R.drawable.a3,
R.drawable.a4,
R.drawable.a5,
R.drawable.a6,
R.drawable.a7,
R.drawable.a8,
R.drawable.a9,
R.drawable.a10,
R.drawable.a11,
R.drawable.a12,
};
String[] names = {
"北极熊",
"犀牛",
"花豹",
"白马",
"小鹦鹉",
"袋鼠",
"狐狸",
"小猫咪",
"哈巴狗",
"蜥蜴",
"大熊猫",
"蚂蚁",
};
List> lineData = new ArrayList<>();
private void addData() {
Map map = null;
Random random = new Random();
for (int i = 0; i < 30; i++) {
int n = random.nextInt(pics.length);
map = new HashMap<>();
map.put("pic", pics[n]);
map.put("name", names[n]);
map.put("desc", "我是一只" + names[n]);
lineData.add(map);
}
}
// 设置为线性布局
lineRecycler.setLayoutManager(new LinearLayoutManager(getContext()));
// 设置适配器
lineRecycler.setAdapter(new RecyclerLineAdapter(getContext(), lineData));
然后,我们运行一下是这样的效果:
不过这样的界面并不是特别好看,于是,我们就给它的 item 添加一个 CardView,使得我们的每一个 Item 都像一张张卡片那样呈现出来,修改 recyclerview item 布局如下:
我们在原先基础的最外层包裹了一个 CardView,并且设置了两个 CardView 经常使用的属性。一个是 cardElevation 指的是 CardView 的一个高度,可以这样想象,RecyclerView 是一个平面,而 CardView 就在它的上面,我们可以通过设置 cardElevation 来控制这个高度,也就是 CardView 在这样的高度时的一个阴影效果,高度越高,阴影越明显。
还有一个属性是 cardCornerRadius 指的是 CardView 四周的弧度,值越大,圆弧就越明显。那么,我们修改完之后的效果如下:
嗯,这样看起来就有点舒服了哦,我是比较喜欢这样的效果,看上去像一张一张小卡片一样,浏览起来也舒服。
上面我们介绍的就是 RecyclerView 线性布局的使用,效果还是不错的,一般可以用于浏览个人信息列表操作。接着,我们来看第二种布局形式:网格布局。
网格布局也是非常常用的,一般用于图片相册的浏览,接下来的工作就是复制粘贴一下原先的代码就可以了,因为适配器里面的代码几乎一个样,我们可以考虑把它封装起来用,不过现在还是怎么方便怎么来。
对于线性布局来说,网格布局是需要做一定量的修改的,也就是布局文件的修改,我们把旁边的 “我是一只...” 文本给去掉,保留了图片和动物名称,所以布局文件代码修改为:
没了这个,我们适配器中也相应的把 textview 给删除,这个应该很简单,就是把 desc 给删了就好了,还是贴一下代码吧:
package nd.no.xww.bottomnavigationlayout;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.List;
import java.util.Map;
/**
* @author xww
* @desciption :
* @date 2019/7/24
* @time 12:06
*/
public class RecyclerGridAdapter extends RecyclerView.Adapter {
Context context;
List> data;
public RecyclerGridAdapter(Context context, List> data) {
this.data = data;
this.context = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recycler_one_view_2_item, viewGroup, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int i) {
Glide.with(context).load(data.get(i).get("pic")).into(holder.img);
holder.name.setText(data.get(i).get("name").toString());
}
@Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView img;
TextView name;
public ViewHolder(@NonNull View itemView) {
super(itemView);
img = itemView.findViewById(R.id.img_recy_item_2_pic);
name = itemView.findViewById(R.id.tv_recy_item_2_name);
}
}
}
然后,是数据做一下简单的修改,把对应的 desc 数据给删除:
private void addGridData() {
Map map = null;
Random random = new Random();
for (int i = 0; i < 30; i++) {
int n = random.nextInt(pics.length);
map = new HashMap<>();
map.put("pic", pics[n]);
map.put("name", names[n]);
gridData.add(map);
}
}
最重要的一步,为 RecyclerView 设置布局管理样式:
//设置网格布局样式,2为列数
gridRecycler.setLayoutManager(new GridLayoutManager(getContext(), 2));
gridRecycler.setAdapter(new RecyclerGridAdapter(getContext(), gridData));
好了,这样我们再运行一下,效果如下:
这样就完成了网格布局的设置,效果看起来还可以。
最后一个布局样式是瀑布流的布局,其实和网格布局几乎一样的,网格布局是规规矩矩的,而瀑布流就是有长有短的那种,有错位和落差感,有时候太规矩的不好看,有一点错位显得更加美观。
瀑布流的 RecyclerView Item 布局文件要注意了,不能写固定的一个高度,否则就没有效果了。比如,我们得这样改:
注意上面的代码,cardview 的高度不能固定,以及下面的 textview 高度也都不能固定值,都要写为 wrap_content,适配器就不需要修改了,要改的地方就是数据格式还有 RecyclerView 的布局管理样式。
我们添加数据要改为这样,名称有长的有短的,才能形成长短不一的瀑布流的形式。
private void addStaggeredData() {
Map map = null;
Random random = new Random();
String[] str = {
"瀑布流\n",
"瀑布流\n瀑布流\n",
"瀑布流\n瀑布流\n瀑布流\n",
"瀑布流\n瀑布流\n瀑布流\n瀑布流\n",
};
for (int i = 0; i < 30; i++) {
int n = random.nextInt(pics.length);
map = new HashMap<>();
map.put("pic", pics[n]);
map.put("name", names[n] + "\n" + str[random.nextInt(str.length)]);
staggeredData.add(map);
}
}
最关键的还是 RecyclerView 的设置:
// 设置瀑布流形式,2为两列
staggerRecycler.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
// 设置适配器
staggerRecycler.setAdapter(new RecyclerStaggeredAdapter(getContext(), staggeredData));
好了,我们运行一下,就会产生错落的瀑布流效果了:
那么,到此为止呢,几种 RecyclerView 常用的布局形式都给试了一遍,总体来说都非常不错的,特别是配合 CardView 以后,显示效果更佳。不过 design 库里面还有一个比较漂亮的控件,与 RecyclerView 也是天生绝配的存在,那就是下拉刷新的控件:SwipeRefreshLayout,最后呢,我们继续把 SwipeRefreshLayout 添加到 RecyclerView 上,看看效果如何吧。
我们就那网格布局例子为基础, 在它的 RecyclerView 上面加上一个 SwipeRefreshLayout 控件,这样要注意一下,SwipeRefreshLayout 必须是 RecyclerView 的父容器,也就是 SwipeRefreshLayout 包裹 RecyclerView,看下面的代码你就非常清楚了:
SwipeRefreshLayout 要刷新的话,需要添加一个监听事件,又因为适配器在刷新后需要把数据也刷新一下,然后再绑定到 RecyclerView 上,代码如下所示。
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
gridData.clear();
addGridData();
gridAdapter.notifyDataSetChanged();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (swipeRefreshLayout.isRefreshing()) {
swipeRefreshLayout.setRefreshing(false);
}
}
}, 1500);
}
});
首先,要把集合给清空,然后为集合添加新的数据,最后调用适配器通知一下重新绑定数据就搞定了。那么效果如下:
这里有个与 SwipeRefreshLayout 相关的比较常用的属性,直接看下面的代码就知道了:
//为下拉刷新,设置一组颜色
swipeRefreshLayout.setColorSchemeColors(Color.BLUE, Color.RED, Color.GREEN);
//设置触发刷新的距离
swipeRefreshLayout.setDistanceToTriggerSync(200);
//设置滑动的距离
swipeRefreshLayout.setSlingshotDistance(400);
刷新时就会不停的变化进度的颜色效果,显得花里胡哨的,当然了,你也可以只添加一种颜色。
还有两个用于设置刷新的监听与取消情况:
//开始刷新,false 取消刷新
swipeRefreshLayout.setRefreshing(true);
//判断是否正在刷新
swipeRefreshLayout.isRefreshing();
好了,结合上面的几个控件,我们可以随意的写出好看的界面。