继续使用上篇文章的项目,拷贝一份并改名为
day20_CardView
一、CardView
CardView
也是FrameLayout
的一种,不过提供了额外的圆角和阴影等效果
1、添加依赖
implementation 'androidx.recyclerview:recyclerview:1.1.0' // 瀑布布局
implementation 'androidx.cardview:cardview:1.0.0' // 卡片布局
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' // 加载图片的库
2、主布局
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fab"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/done"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
3、实体类
Fruit
public class Fruit {
private String name;
private int imageId;
public Fruit(String name, int imageId){
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
}
4、菜单项布局
fruit_item_xml
scaleType
指定缩放属性,centerCrop
按比例缩放填满imageView
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:id="@+id/fruit_image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fruit_name"
android:layout_gravity="center_horizontal"
android:layout_margin="5dp"
android:textSize="16sp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
5、适配器
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private Context mContext;
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder{
CardView cardView;
ImageView fruitimage;
TextView fruitName;
public ViewHolder(View view){
super(view);
cardView = (CardView) view;
fruitimage = view.findViewById(R.id.fruit_image);
fruitName = view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruit> fruitList){
mFruitList = fruitList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (mContext == null){
mContext = parent.getContext();
}
View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Fruit fruit = mFruitList.get(position);
holder.fruitName.setText(fruit.getName());
Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitimage);
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}
Glide
用来加载图片:
Glide.with()
参数传入Context
、Activity
或Fragment
load()
加载图片,可以是URL
或本地路径,甚至是资源id
into()
设置到某个资源里
6、主活动
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
private Fruit[] fruits = {
new Fruit("苹果", R.drawable.the_apple), new Fruit("香蕉", R.drawable.the_banana),
new Fruit("鸭梨", R.drawable.the_pear), new Fruit("葡萄", R.drawable.the_grape),
new Fruit("菠萝", R.drawable.the_pinapple), new Fruit("草莓", R.drawable.the_strawberry),
new Fruit("樱桃", R.drawable.the_cherry), new Fruit("芒果", R.drawable.the_mango)};
private List<Fruit> fruitList = new ArrayList<>();
private FruitAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
......
initFruits();
RecyclerView recyclerView = findViewById(R.id.recycler_view);
GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(layoutManager);
adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
......
private void initFruits() {
fruitList.clear();
for (int i = 0; i < 50; i++){
Random random = new Random();
int index = random.nextInt(fruits.length);
fruitList.add(fruits[index]);
}
}
}
代码没啥好解释的,看不懂就多写几遍
【参考文章】
运行:
但是发现,ToolBar
怎么被RecyclerView
遮住了?!
解决这个问题就要借助AppBarLayout
了
二、AppBarLayout
因为CoordinatorLayout
属于FrameLayout
,所以内部元素会自动在摆放在左上角,从而产生被遮挡现象。这个问题可以通过偏移来解决,但不是最好的办法。
AppBarLayout
实际上是一个垂直方向的LinearLayout
,在内部做了许多滚动事件的封装,并应用了Material Design
的设计理念
使用方法:
- 将
Toolbar
嵌套到AppBarLayout
- 给
RecyclerView
指定一个布局行为:app:layout_behavior="@string/appbar_scrolling_view_behavior"
主布局:
。。。。。。
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
。。。。。。
运行:
这次虽然取消了遮挡,但是没体现出Material Design
的优势
给ToolBar
再设置一个属性:
app:layout_scrollFlags="scroll|enterAlways|snap"
scroll
:当RecyclerView
向上滚动时,Toolbar
跟着向上滚动,并隐藏enterAlways
:当RecyclerView
向下滚动时,Toolbar
一起向下滚动并重新显示snap
:Toolbar
再没有完全隐藏或显示时,根据滚动举例,自动选择隐藏还是显示
运行: