Android中的CardView和Fragment

1.CardView

1.1 CardView的基本使用

CardView是用于实现卡片式布局效果的重要控件,实际上也是一个frameLayout,只是额外提供了圆角和 阴影,看上去有立体效果。效果如下:

 1.2常用API:

 基本使用方法:

<androidx.cardview.widget.CardView
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"
app:srcCompat="@mipmap/a1" />
<TextView
android:id="@+id/tv_title"
android:text="AI 改变千行万业,开发者如何投身 AI 语音新“声”态"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:textSize="16sp" />
</LinearLayout>

1.3 CardView与RecycleView的结合使用

先看一下效果吧:

 再看一下具体的实现步骤:

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"
tools:context=".MainActivity2">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_news"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

子布局:

?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>

2.代码:

实体类 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);
}
}
}

MainAvticity:

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);
}
}
}

2.Fargment

2.1Fargment简介:

1.Fragment的简介 Fragment译为“碎片”,是Android 3.0(API 11)提出的,最开始是为了适配大屏的平板。

2.Fragment看起来和Activity一样,是一个用户界面。可以结合多个Fragments到一个activity中来构 建一个有多方面功能的UI,还可以重用同一个Fragment在多个activities中。Fragment可以当成是 activity的一个组件,每个Fragment有单独的生命周期,可以在activity运行时进行添加和移除 Fragment。因此,相比较于activity,Fragment更加轻量级,更加灵活。

3.一个Fragment总是被植入在一个activity中 ,并且其生命周期受其父activity直接影响,比如 activity处于暂停,则其中的Fragment都暂停;activity销毁,则所有Fragment都销毁。但是,当 一个activity运行时,你可以独立的操作每一个Fragment,比如添加和删除他们。进行类似的操作 时,可以将Fragment添加入被activity管理的后退栈中,这样用户可以通过点击返回按钮来返回之 前打开的Fragment。

4.Fragment可以作为activity的一部分添加到布局文件中,通过声明元素作为ViewGroup的一部分。 也可以将Fragment作为一个没有自己UI的不可见的activity的工人。

总结:

1. Fragment是依赖于Activity的,不能独立存在。

2. 一个Activity里可以有多个Fragment。

3. 一个Fragment可以被多个Activity重用。

4. Fragment有自己的生命周期,并能接收输入事件。

5. 可以在Activity运行时动态地添加或删除Fragment。

2.2 Fragment生命周期

如图:

 

 2.2.1常见的周期流程

1. Activity加载Fragment的时候,依次调用:onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() ->onResume()

2. 当做出一个悬浮的对话框风格的Activity,或者其他,就是让Fragment所在的Activity可见,但不获 得焦点:onPause()

3. 当对话框关闭,Activity又获得了焦点: onResume()

4. 当替换Fragment,并调用addToBackStack()将它添加到Back栈中:onPause() -> onStop() -> onDestoryView() 。注意,此时的Fragment还没有被销毁哦。

5. 当按下键盘的回退键,Fragment会再次显示出来:onCreateView() -> onActivityCreated() -> onStart() -> onResume()

6. 如果替换后,在事务commit之前没有调用addToBackStack()方法将Fragment添加到back栈中, 或者退出了Activity的话,那么Fragment将会被完全结束,Fragment会进入销毁状态: onPause() -> onStop() -> onDestoryView() -> onDestory() -> onDetach()

2.3 Fragment的静态加载

静态加载--以标签的形式添加到Activity的布局当中。

 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 {
3. 在需要加载Fragment的Activity对应的布局文件中添加fragment的标签,注意name属性是全限定
类名,就是要包含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
public View onCreateView(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"?>
id,name属性是必须的
4. Activity在onCreate( )方法中调用setContentView()加载布局文件。
3.3 Fragment的动态使用
Fragment真正的强大之处在于可以动态地添加到Activity当中,因此这也是你必须要掌握的东西。当你
学会了在程序运行时向Activity添加Fragment,程序的界面就可以定制的更加多样化。
1. activity_main.xml
<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>

4. Activity在onCreate( )方法中调用setContentView()加载布局文件。

2.4Fragment的动态使用

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:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity5">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/btn_fragment1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="第一个碎片" />
<Button
android:id="@+id/btn_fragment2"
2. 创建Fragment1
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="第二个碎片" />
</LinearLayout>
<FrameLayout
android:id="@+id/lay_fl"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

2. 创建Fragment1

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);
3. 创建Fragment2
}
}
@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="#DC8888"
tools:context=".fragment.Fragment1">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="24sp"
android:text="第一个碎片" />
</FrameLayout>

3. 创建Fragment2

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.
4. 在活动中,点击按钮后切换Fragment
* @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="#77A8BD"
tools:context=".fragment.Fragment1">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="24sp"
android:text="第二个碎片" />
</FrameLayout>

4. 在活动中,点击按钮后切换Fragment

public class MainActivity5 extends AppCompatActivity {
private Button btn_fragment1, btn_fragment2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main5);
btn_fragment1 = findViewById(R.id.btn_fragment1);
btn_fragment2 = findViewById(R.id.btn_fragment2);
btn_fragment1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment1 fragment1 = new Fragment1();
getSupportFragmentManager().beginTransaction().replace(R.id.lay_fl,
fragment1).show(fragment1).commitAllowingStateLoss();
}
});
btn_fragment2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment2 fragment2 = new Fragment2();
getSupportFragmentManager().beginTransaction().replace(R.id.lay_fl,
fragment2).show(fragment2).commitAllowingStateLoss();
}
});
}

猜你喜欢

转载自blog.csdn.net/weixin_53431933/article/details/126149361
今日推荐