CardView
CardView的基本使用
CardView 是用于实现卡片式布局效果的重要控件,实际上也是一个 frameLayout, 只是额外提供了圆角和 阴影,看上去有立体效果。
效果如下:
常用API:
方法
|
说明
|
cardBackgroundColor
|
设置背景颜色
|
cardCornerRadius
|
设置圆角边大小
|
cardElevation
|
阴影大小
-
设置为
0
代表没有阴影
|
cardMaxElevation
|
最大的阴影大小
|
cardPreventCornerOverlap
|
在
v20
和之前的版本中添加内边距,这个属性是为了防止卡片内容 和边角的重叠
|
cardUseCompatPadding
|
设置内边距,
v21+
的版本和之前的版本仍旧具有一样的计算方式
|
contentPadding
|
内边距
|
contentPaddingBottom
|
底部边距
|
contentPaddingLeft
|
左侧边距
|
contentPaddingRight
|
右侧边距
|
contentPaddingTop
|
顶部边距
|
基本使用方法:
<?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="240dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
android:layout_margin="3dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/iv_img"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="fitXY"
app:srcCompat="@mipmap/a2" />
<TextView
android:layout_marginTop="5dp"
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="一号" />
</LinearLayout>
</androidx.cardview.widget.CardView>
CardView与RecycleView的结合使用
实现效果如下:
实现步骤:
1. 布局文件
主布局 activity_main.xm
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_news"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
子布局
news_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardElevation="5dp"
app:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="3dp"
android:orientation="horizontal">
<ImageView android:id="@+id/iv_img"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"/>
<TextView android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:textSize="16sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
代码文件
实体类
News.java
public class News {
private String title;
private int imgID;
public News(String title, int imgID){
this.title = title;
this.imgID = imgID;
}
public String getTitle() {
return title;
}
public int getImgID() {
return imgID;
}
}
适配器
NewsAdapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private List<News> list;
public NewsAdapter(List<News> list){
this.list = list;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
News news = list.get(position);
holder.iv_img.setImageResource(news.getImgID());
holder.iv_img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), news.getImgID()+"图片被点击", Toast.LENGTH_SHORT).show();
}
});
holder.tv_title.setText(news.getTitle());
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), news.getTitle()+"被点击", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
View view; ImageView iv_img;
TextView tv_title;
public ViewHolder(@NonNull View itemView) {
super(itemView);
view = itemView;
iv_img = itemView.findViewById(R.id.iv_img);
tv_title = itemView.findViewById(R.id.tv_title);
}
}
}
调用适配器
public class MainActivity2 extends AppCompatActivity {
private RecyclerView rv_news;
private String[] titles= {"AI 改变千行万业,开发者如何投身 AI 语音新“声”态","实 时互动还有哪些可能?RTE 2022 创新编程挑战赛正式开启","子寅:不会“怼”产品经理,干不了程序 员,更干不好脱口秀","AI 改变千行万业,开发者如何投身 AI 语音新“声”态","实时互动还有哪些可 能?RTE 2022 创新编程挑战赛正式开启","子寅:不会“怼”产品经理,干不了程序员,更干不好脱口 秀"};
private int[] imgs = {R.mipmap.a1,R.mipmap.a2,R.mipmap.a3,R.mipmap.a1, R.mipmap.a2, R.mipmap.a3};
private List<News> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initData();
rv_news = findViewById(R.id.rv_news);
NewsAdapter adapter = new NewsAdapter(list);
// 在设置适配器之前需要设置布局管理器
// 要不然 RecyclerView: No layout manager attached; skipping layout
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
// 加上此句话,效果就变为横向的
//GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
// 如果加上分隔线,效果会更好
rv_news.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
rv_news.setLayoutManager(layoutManager);
rv_news.setAdapter(adapter);
}
private void initData() {
for (int i = 0;i < titles.length; i++) {
News news = new News(titles[i], imgs[i]);
list.add(news);
}
}
}
Fragment
Fragment译为“碎片”,是Android 3.0(API 11)提出的,最开始是为了适配大屏的平板。
Fragment的概念
1. Fragment是依赖于Activity
的,不能独立存在。
2. 一个Activity
里可以有多个
Fragment
。
3. 一个Fragment
可以被多个
Activity
重用。
4. Fragment有自己的生命周期,并能接收输入事件。
5. 可以在Activity
运行时动态地添加或删除
Fragment
。
Fragment生命周期
Activity 加载 Fragment 的时候,依次调用:
onAttach() -> onCreate() -> onCreateView() ->onActivityCreated() -> onStart() ->onResume()
Fragment的静态加载
Fragment
的静态加载过程:
1. 定义
Fragment
的布局,就是
fragment
显示内容
fragment_footer.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.FooterFragment">
<TextView
android:id="@+id/tv_footer"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#83A8C5"
android:gravity="center"
android:textSize="24dp"
android:text="页尾" />
</FrameLayout>
2.自定义一个
Fragment
类,需要继承
Fragment
或者它的子类,重写
onCreateView()
方法,在该法
中调用
inflater.inflate()
方法加载
Fragment
的布局文件,接着返回加载的
view
对象。
FooterFragment.java
public class FooterFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1; private String mParam2;
public FooterFragment() {
// Required empty public constructor
}
/*** Use this factory method to create a new instance of
* this fragment using the provided parameters.
** @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FooterFragment.
*/
// TODO: Rename and change types and number of parameters
public static FooterFragment newInstance(String param1, String param2) {
FooterFragment fragment = new FooterFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
publicViewonCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState{
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_footer, container, false);
}
}
3.
在需要加载
Fragment
的
Activity
对应的布局文件中添加
fragment
的标签,注意
name
属性是全限定
类名,就是要包含
Fragment
的包名。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity4">
<fragment
android:id="@+id/headerFragment"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_alignParentTop="true"
android:name="com.hopu.cardviewdemo.fragment.HeaderFragment"/>
<fragment
android:id="@+id/footerFragment"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_alignParentBottom="true"
android:name="com.hopu.cardviewdemo.fragment.FooterFragment"/>
</RelativeLayout>
id
,
name
属性是必须的
4. Activity
在
onCreate( )
方法中调用
setContentView()
加载布局文件。
Fragment的动态使用
Fragment
真正的强大之处在于可以动态地添加到
Activity
当中,因此这也是你必须要掌握的东西。当你
学会了在程序运行时向
Activity
添加
Fragment
,程序的界面就可以定制的更加多样化。
1. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="第一个碎片" />
<Button
android:id="@+id/btn_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="第二个碎片" />
</LinearLayout>
<FrameLayout
android:id="@+id/fl_ly"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</FrameLayout>
</LinearLayout>
2.
创建
Fragment1
package com.hp.demo.fragement;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.hp.demo.R;
/**
* A simple {@link Fragment} subclass.
* Use the {@link Fragment1#newInstance} factory method to
* create an instance of this fragment.
*/
public class Fragment1 extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public Fragment1() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment Fragment1.
*/
// TODO: Rename and change types and number of parameters
public static Fragment1 newInstance(String param1, String param2) {
Fragment1 fragment = new Fragment1();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_1, container, false);
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1C8AE1"
tools:context=".fragement.Fragment1">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/black"
android:textSize="30sp"
android:gravity="center"
android:text="机械人" />
</FrameLayout>
3. 创建Fragment2
package com.hp.demo.fragement;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.hp.demo.R;
/**
* A simple {@link Fragment} subclass.
* Use the {@link Fragment2#newInstance} factory method to
* create an instance of this fragment.
*/
public class Fragment2 extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public Fragment2() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment Fragment2.
*/
// TODO: Rename and change types and number of parameters
public static Fragment2 newInstance(String param1, String param2) {
Fragment2 fragment = new Fragment2();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_2, container, false);
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#4CAF50"
tools:context=".fragement.Fragment2">
<!-- TODO: Update blank fragment layout -->
<TextView
android:textColor="@color/black"
android:textSize="30sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="恕瑞玛" />
</FrameLayout>
4.
在活动中,点击按钮后切换
Fragment
package com.hp.demo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.hp.demo.fragement.Fragment1;
import com.hp.demo.fragement.Fragment2;
public class MainActivity2 extends AppCompatActivity {
private Button btn_one,btn_two;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
btn_one=findViewById(R.id.btn_one);
btn_two=findViewById(R.id.btn_two);
btn_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Fragment1 fragment1=new Fragment1();
getSupportFragmentManager().beginTransaction().replace(R.id.fl_ly,fragment1).commit();
}
});
btn_two.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Fragment2 fragment2=new Fragment2();
getSupportFragmentManager().beginTransaction().replace(R.id.fl_ly,fragment2).commit();
}
});
}
}