我们使用 CardView 与 RecyclerView 来. 实现一个各种猫的卡片式展示列表吧 O(∩_∩)O~
1 CardView 控件
1.1 引入依赖库
打开 App/build.gradle, 添加依赖库:
- dependencies {
- ...
- compile 'com.Android.support:recyclerview-v7:24.2.1'
- compile 'com.Android.support:cardview-v7:24.2.1'
- compile 'com.GitHub.bumptech.glide:glide:4.8.0'
- }
最后一行引入的 Glide, 它是一个快速高效的 Android 图片加载库, 注重于平滑的滚动 . Glide 支持拉取, 解码和展示视频快照, 图片, 和 GIF 动画 .
1.2 卡片式布局
CardView 控件可实现卡片式布局. 它其实是一个 FrameLayout, 只不过多了圆角与阴影功能.
布局:
- <?xml version="1.0" encoding="utf-8"?>
- <Android.support.v4.widget.DrawerLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
- xmlns:material="http://schemas.Android.com/apk/res-auto"
- Android:id="@+id/drawer"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent">
- ...
- <Android.support.v7.widget.RecyclerView
- Android:id="@+id/recycler_view"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent"/>
- ...
- </Android.support.v4.widget.DrawerLayout>
我们在 DrawerLayout 中新增了 RecyclerView, 并让它占满整个空间 (宽与高都是 match_parent).
1.3 "猫" 实体类
- public class Cat {
- // 类型
- private String type;
- // 图片资源 ID
- private int imgId;
- public Cat(String type, int imgId) {
- this.type = type;
- this.imgId = imgId;
- }
- public String getType() {
- return type;
- }
- public int getImgId() {
- return imgId;
- }
- }
1.4 RecyclerView 的 item 布局
在 layout 目录下新建 cat_item.xml, 内容为:
- <?xml version="1.0" encoding="utf-8"?>
- <Android.support.v7.widget.CardView
- xmlns:Android="http://schemas.Android.com/apk/res/Android"
- xmlns:material="http://schemas.Android.com/apk/res-auto"
- Android:layout_width="match_parent"
- Android:layout_height="wrap_content"
- Android:layout_margin="5dp"
- material:cardCornerRadius="4dp">
- <LinearLayout
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:orientation="vertical"
- >
- <ImageView
- Android:id="@+id/cat_image"
- Android:layout_width="200dp"
- Android:layout_height="200dp"
- Android:scaleType="centerCrop"/>
- <TextView
- Android:id="@+id/cat_type"
- Android:layout_width="wrap_content"
- Android:layout_height="wrap_content"
- Android:layout_gravity="center_horizontal"
- Android:layout_margin="5dp"
- Android:textSize="16sp"
- />
- </LinearLayout>
- </Android.support.v7.widget.CardView>
注意: 这里事先已把猫的相关图片放置在 res/drawable 目录中.
因为每张图片的长宽比例不一样, 所以我们把 Android:scaleType 设置为 centerCrop, 让图片按照原比例充满整个 ImageView, 并裁剪超出的部分.
1.5 RecyclerView 适配器
- public class CatAdapter extends RecyclerView.Adapter<CatAdapter.ViewHolder> {
- private Context context;
- private List<Cat> cats = new ArrayList<>();
- public CatAdapter(List<Cat> cats) {
- this.cats = cats;
- }
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- if (context == null) {// 设置上下文环境
- context = parent.getContext();
- }
- View view = LayoutInflater.from(context).inflate(R.layout.cat_item, parent, false);
- return new ViewHolder(view);
- }
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- Cat cat = cats.get(position);
- holder.type.setText(cat.getType());
- Glide.with(context).load(cat.getImgId()).into(holder.image);
- }
- @Override
- public int getItemCount() {
- return cats.size();
- }
- static class ViewHolder extends RecyclerView.ViewHolder {
- CardView cardView;
- ImageView image;
- TextView type;
- public ViewHolder(View itemView) {
- super(itemView);
- cardView = (CardView) itemView;
- image = (ImageView) itemView.findViewById(R.id.cat_image);
- type = (TextView) itemView.findViewById(R.id.cat_type);
- }
- }
- }
在 onBindViewHolder 中使用 Glide 来加载图片.
Glide.with() 可传入 Context,Activity,FragmentActivity 或 Fragment, 创建 RequestManager 对象.
RequestManager .load() 用于加载图片, 可以传入 File,resourceId,URI 等类型的参数, 创建 DrawableRequestBuilder 对象.
DrawableRequestBuilder .into() 用于指定放置图片的 ImageView.
Glide 本身会对图片进行压缩, 所以就算是很大的图片, 也可以放心使用啦 O(∩_∩)O~
1.6 活动类
- public class MainActivity extends AppCompatActivity {
- private DrawerLayout drawerLayout;
- private Cat[] cats = {new Cat("布偶猫", R.drawable.cat1),
- new Cat("异国短毛猫", R.drawable.cat2),
- new Cat("波斯猫", R.drawable.cat3),
- new Cat("美国短毛猫", R.drawable.cat4),
- new Cat("挪威森林猫", R.drawable.cat5),
- new Cat("日本短尾猫", R.drawable.cat6),
- new Cat("俄罗斯蓝猫", R.drawable.cat7),
- new Cat("伯曼猫", R.drawable.cat8),
- new Cat("缅因猫", R.drawable.cat9),
- new Cat("埃及猫", R.drawable.cat10)};
- private List<Cat> catList = new ArrayList<>();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ...
- initCats();
- RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
- int spanCount = 2;
- GridLayoutManager layoutManager = new GridLayoutManager(this, spanCount);
- recyclerView.setLayoutManager(layoutManager);
- CatAdapter adapter = new CatAdapter(catList);
- recyclerView.setAdapter(adapter);
- }
- private void initCats() {
- catList.clear();
- for (int i = 0; i <100; i++) {// 随机添加 100 只猫的信息
- Random random = new Random();
- int index = random.nextInt(cats.length);
- catList.add(cats[index]);
- }
- }
- ...
- }
initCats() 在 cats 数组中随机挑选了 100 只猫.
使用了 GridLayoutManager 布局, 它接收两个参数: Context 与总列数.
效果
卡片式布局漂亮吧? O(∩_∩)O~
2 优化
2.1 解决顶部工具栏被遮挡问题
目前设计中的卡片式布局存在一个问题, 就是会遮挡顶部工具栏.
传统做法是让 RecyclerView 向下偏移顶部工具栏的高度.
AppBarLayout 是 Design Support 库提供的一个垂直方向的 LinearLayout, 它封装很多滚动事件.
修改布局文件:
- ...
- <Android.support.design.widget.AppBarLayout
- Android:layout_width="match_parent"
- Android:layout_height="wrap_content">
- <Android.support.v7.widget.Toolbar
- Android:id="@+id/toolbar"
- Android:layout_width="match_parent"
- Android:layout_height="?attr/actionBarSize"
- Android:background="?attr/colorPrimary"
- Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
- </Android.support.design.widget.AppBarLayout>
- <Android.support.v7.widget.RecyclerView
- Android:id="@+id/recycler_view"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent"
- material:layout_behavior="@string/appbar_scrolling_view_behavior"
- />
- ...
使用 AppBarLayout 包裹 Toolbar.
为 RecyclerView 的 material:layout_behavior 指定 appbar_scrolling_view_behavior 事件.
经过这两步修改, 工具栏与卡片式布局就可以和谐共处啦 O(∩_∩)O~
2.2 工具栏响应滚动事件
- <Android.support.v7.widget.Toolbar
- ...
- material:layout_scrollFlags="scroll|enterAlways|snap"
- />
我们在 Toolbar 中新增了 material:layout_scrollFlags 属性, 并设置了三种场景中的显示策略. 从左到右, 场景依次为向上滚动时, 向下滚动时和还未完全显示与隐藏时.
属性 | 说明 |
---|---|
scroll | 一起滚动,会被隐藏。 |
enterAlways | 一起滚动,一直显示。 |
snap | 根据滚动距离,来判断是显示还是隐藏。 |
效果
当用户向上滑动内容时, 隐藏工具栏; 当用户向上滑动屏幕时, 再显示工具栏. 这是 Material Design 中的一条重要设计, 极大地提升了用户的阅读体验 O(∩_∩)O~
来源: http://www.jianshu.com/p/a2db7a0e1ec8