一.MaterialCardView
1.基本介绍
MaterialCardView
是用于实现卡片式布局效果的重要控件,它也是一个FrameLayout
,只是额外提供了圆角和阴影等效果,看上去会有立体的感觉。我们在其布局中放什么,那么这个东西就会在一张卡片中了。
2.Glide库
一般里面会放图片控件,所以这里要学习一下Glide
。Glide
是一个超级强大的开源图片加载库,它不仅可以用于加载本地图片,还可以加载网络图片,GIF图片甚至是本地视频。最重要的是,Glide
用法非常简单,只需要几行代码就能轻松实现复杂的图片加载功能。
在使用之前,需要引入依赖
implementation 'com.github.bumptech.glide:glide:4.9.0'
具体使用示例
Glide.with(context).load(imageId).into(ImageView);
二.RecyclerView的创建
1.在MainActivity
的布局文件中添加RecyclerView
2.创建一个实体类:Fruit
public class Fruit {
String name;
int imageId;
public Fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
}
3.创建item
布局
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
app:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/fruitImage"
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="centerCrop"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fruitName"
android:layout_gravity="center_horizontal"
android:layout_margin="5dp"
android:textSize="16sp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
4.创建适配器
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.MyViewHolder> {
List<Fruit> fruits = new ArrayList<>();
Context context;
FruitAdapter(Context context){
this.context = context;
for (int i = 0; i < 30; i++) {
fruits.add(new Fruit("香蕉",R.mipmap.banana));
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.textView.setText(fruits.get(position).name);
Glide.with(context).load(fruits.get(position).imageId).into(holder.fruitImage);
}
@Override
public int getItemCount() {
return fruits.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
ImageView fruitImage;
TextView textView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
fruitImage = itemView.findViewById(R.id.fruitImage);
textView = itemView.findViewById(R.id.fruitName);
}
}
}
5.修改MainActivity
中的代码
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this,2);
RecyclerView recyclerView = findViewById(R.id.mRecyclerView);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(new FruitAdapter(this));
使用效果
三.AppBarLayout
1.简介
在上面的例子中,为了不让RecyclerView
把Toolbar
给挡住,我们可以把Toolbar
嵌套在AppBarLayout
里面。它实际上是一个垂直方向的LinearLayout
,在内部做了很多滚动事件的封装,并应用了一些Material Design的设计理念。
2.使用
①将Toolbar
嵌套到AppBarLayout
中
②给RecyclerView
指定一个布局行为,即@string/appbar_scrolling_view_behavior
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<androidx.appcompat.widget.Toolbar
android:id="@+id/mToolBar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#f2652260"
android:elevation="4dp"
app:title="我是主标题"
app:subtitle="我是副标题"
app:logo="@mipmap/ic_delete"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:navigationIcon="@mipmap/ic_delete"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/toolbarMenuStyle">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/
</androidx.drawerlayout.widget.DrawerLayout>
3.更好的应用
我们在Toolbar
中添加了app:layout_scrollFlags
属性,scroll
表示当RecyclerView
向上滚动的时候,Toolbar
会跟着一起向上滚动并实现隐藏。enterAlways
表示当RecyclerView
向下滚动的时候,Toolbar
会跟着一起向下滚动并重新显示。snap
表示当Toolbar
还没有完全隐藏或显示的时候,会根据当前滚动的距离,自动选择是隐藏还是显示
效果
四.SwipeRefreshLayout
SwipeRefreshLayout
就是下拉刷新,直接用就可以
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/mRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
注意:由于RecyclerView
现在变成了SwipeRefreshLayout
的子控件,因此之前使用 app:layout_behavior
声明的布局行为现在也要移到SwipeRefreshLayout
中才行。
2.处理刷新逻辑
SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.mRefresh);
swipeRefreshLayout.setColorSchemeColors(R.color.black);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Thread(){
@Override
public void run() {
super.run();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.run();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "运行到主线程了", Toast.LENGTH_SHORT).show();
SwipeRefreshLayout swipeRefreshLayout1 = findViewById(R.id.mRefresh);
swipeRefreshLayout1.setRefreshing(false);
}
});
}
});
setColorSchemeColorss
是设置下拉进度条的颜色。setOnRefreshListener
是设置下拉的监听器
在刷新事件开始时,我们先开启新线程,睡2s,然后调用runOnUiThread
切换回主线程,然后调用SwipeRefreshLayout
的setRefreshing
方法,传入false
表示刷新事件结束,并且隐藏进度条
使用效果