Android学习之在Adapter中调用Fragment
•前言
在学习《第一行代码》,4.5 小节——一个简易版的新闻应用的时候;
在为 RecyclerView 创建适配器的时候;
作者直接在 NewsTitleFragment.java 中新建了一个内部类 NewsAdapter 来作为 RecyclerView 的适配器;
我就在想,是不是可以将 NewsAdapter 摘出来,作为一个独立的类来使用;
本着求知若渴的态度,便产生了这篇博客;
•前行必备
在简易版的新闻应用中,为了区分平板和手机,新建了一个 layout-sw600dp 文件夹;
而本节的重点是如何在 Adapter 中调用 Fragment,所以一切从简;
新建一个项目,我命名为 TestFragment,并选择 Empty Activity;
这样 Android Studio 自动生成了 MainActivity.java 和 activity_main.xml 文件;
•渐入佳境
首先,准备好一个新闻实体类,新建类 News;
News.java
public class News {
String title;
String content; News(String title,String content){
this.title = title;
this.content = content;
} public String getTitle() {
return title;
} public String getContent() {
return content;
}
}title 表示新闻标题,content 表示新闻内容;
接着新建布局文件 right_fragment.xml,用于作为新闻内容的布局;
right_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"
android:background="@color/yello"> <TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="30sp"
android:textColor="@color/black"
/> <View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@color/black"/> <TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20sp"
android:textColor="@color/gray"
/> </LinearLayout>该代码的布局和新闻应用中的 news_content_frag.xml 布局大同小异,这里不再赘述;
在新建一个 RightFragment 类,继承自 Fragmet;
RightFragment.java
public class RightFragment extends Fragment { View view;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.right_fragment,container,false);
return view;
} public void refresh(String title,String content){
TextView mTitle = view.findViewById(R.id.title);
TextView mContent = view.findViewById(R.id.content); mTitle.setText(title);
mContent.setText(content);
}
}该代码的功能同新闻应用中的 NewsContentFragment 相同;
接下来创建一个用于显示新闻列表的布局,新建 left_fragment.xml;
left_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/green"
android:padding="10dp"> <androidx.recyclerview.widget.RecyclerView
android:id="@+id/left_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/> </LinearLayout>功能同新闻应用中的 news_title_frag;
新建 item.xml 作为 RecyclerView 子项的布局;
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <TextView
android:id="@+id/item_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
/> </LinearLayout>该代码中仅放置了一个 TextView 用于展示标题;
接下来我们就需要一个用于展示新闻列表的地方;
新建一个 LeftFragment 类作为展示新闻列表的碎片;
LeftFragment.java
public class LeftFragment extends Fragment { @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
} }在 onCreateView() 方法中加载了 left_fragment 布局;
接下来就是为 RecyclerView 添加适配器,有两种方式:
- 在 LeftFragment.java 中新建一个内部类 NewsAdapter 来作为 RecyclerView 的适配器
- 将 NewsAdapter 作为一个独立的类作为 RecyclerView 的适配器
•内部类方式
修改 LeftFragment.java 中的代码;
LeftFragment.java
public class LeftFragment extends Fragment { @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false); RecyclerView rv = view.findViewById(R.id.left_recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(null);
rv.setLayoutManager(manager); NewsAdapter adapter = new NewsAdapter(getData());
rv.setAdapter(adapter); return view;
} class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder>{ private List<News> mList; class ViewHolder extends RecyclerView.ViewHolder{ TextView title;
public ViewHolder(@NonNull View view) {
super(view);
title = view.findViewById(R.id.item_text_view);
}
} public NewsAdapter(List<News> list){
mList = list;
} @NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
ViewHolder holder = new ViewHolder(view); view.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
News news = mList.get(holder.getAdapterPosition());
FragmentManager manager = getFragmentManager();
RightFragment fragment = (RightFragment) manager.findFragmentById(R.id.right_fragment);
fragment.refresh(news.getTitle(),news.getContent());
}
});
return holder;
} @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
News news = mList.get(position);
holder.title.setText(news.getTitle());
} @Override
public int getItemCount() {
return mList.size();
}
} private List<News> getData() {
List<News> list = new ArrayList<>(); for (int i = 1; i <= 5; i++) {
list.add(new News("Title" + i, "Content" + i));
} return list;
}
}该方法同新闻应用中的添加适配器的方式相同,在此不再赘述;
运行效果
•独立类方式
新建一个 NewsAdapter 类,添加如下代码;
NewsAdapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> { private List<News> mList; public class ViewHolder extends RecyclerView.ViewHolder { TextView title; public ViewHolder(@NonNull View view) {
super(view);
title = view.findViewById(R.id.item_text_view);
} } public NewsAdapter(List<News> list) {
mList = list;
} @NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
ViewHolder holder = new ViewHolder(view); view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
News news = mList.get(holder.getAdapterPosition()); /**
* 此处会报错
* 因为 NewsAdapter 并没有继承自 Fragment
* 所以就无法使用 getFragmentManager() 方法获取到 FragmentManager
*/
// FragmentManager manager = getFragmentManager(); }
});
return holder;
} @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
News news = mList.get(position);
holder.title.setText(news.getTitle());
} @Override
public int getItemCount() {
return mList.size();
} }仔细品读,你会发现,这和内部类中的 NewsAdapter 代码相差无几;
其实不然,在内部类 NewsAdapter 中,由于外部类 LeftFragment 继承自 Fragment;
所以,在 view.setOnClickListener() 的 onClick() 中就可以使用 FragmentManager manager = getFragmentManager(); ;
但是,将 NewsAdapter 摘出来作为一个独立的类,其并没有继承自 Fragment,所以,不能使用 getFragmentManager() 方法;
那我们是不是可以这样做,在点击 item 的时候,通过 onClick() 方法中的 News news = mList.get(holder.getAdapterPosition()); 方法,将被点击项的 title 和 content 传递到 LeftFragment 中;
然后,在 LeftFragment 中进行 Fragment 的一系列操作?
你别说,还真行,这就需要通过 Java 的回调机制来实现;
鄙人不才,之前学了一点回调的知识,特此献上;
首先,我们在 NewsAdapter.java 中添加一个回调接口 CallBack,并在 NewsAdapter.java 中声明一个 CallBack;
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> { private List<News> mList;
private CallBack callBack;//声明一个 CallBack public class ViewHolder extends RecyclerView.ViewHolder {...} public NewsAdapter(List<News> list) {...} @NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {...} @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {...} @Override
public int getItemCount() {...} }
//添加一个回调接口 CallBack
interface CallBack{
void onClick(News news);
}接下来就是定义 setCallBack() 方法了;
修改 NewsAdapter.java 中的代码;
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> { private List<News> mList;
private CallBack callBack;//声明一个 CallBack public class ViewHolder extends RecyclerView.ViewHolder {...} public NewsAdapter(List<News> list) {...} //定义 setCallBack() 方法
public void setCallBack(CallBack callBack){
this.callBack = callBack;
} @NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {...} @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {...} @Override
public int getItemCount() {...} }
//添加一个回调接口 CallBack
interface CallBack{
void onClick(News news);
}然后,就是通过 onClick() 方法传递被点击项 title 和 content 了;
修改 view.setOnClickListener() 中的 onClick() 方法;
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { ... view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
News news = mList.get(holder.getAdapterPosition()); /**
* 此处会报错
* 因为 NewsAdapter 并没有继承自 Fragment
* 所以就无法使用 getFragmentManager() 方法获取到 FragmentManager
*/
// FragmentManager manager = getFragmentManager(); /**
* 把 news.getTitle() 和 news.getContent() 传递到 LeftFragment 中
* 这就需要使用回调方法
*/
callBack.onClick(news);
}
});
return holder;
}通过 callBack.onClick(news); 方法传递 title 和 content 信息;
接下来,就是在 LeftFragment.java 中通过回调接收 news 了;
修改 LeftFragment.java 中的代码;
public class LeftFragment extends Fragment { @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false); RecyclerView rv = view.findViewById(R.id.left_recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(null);
rv.setLayoutManager(manager); NewsAdapter adapter = new NewsAdapter(getData()); CallBack callBack = new CallBack() {
@Override
public void onClick(News news) {
FragmentManager manager1 = getFragmentManager();
RightFragment fragment = (RightFragment) manager1.findFragmentById(R.id.right_fragment);
fragment.refresh(news.getTitle(),news.getContent());
}
};
adapter.setCallBack(callBack); rv.setAdapter(adapter); return view;
} private List<News> getData() {
List<News> list = new ArrayList<>(); for (int i = 1; i <= 5; i++) {
list.add(new News("Title" + i, "Content" + i));
} return list;
}
}到这,就大功告成了;
运行一下,你会发现,成功实现内部类的实现效果;
•声明
参考资料:
Android学习之在Adapter中调用Fragment的更多相关文章
- 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题
ViewPager是android-support-v4.jar包中的一个系统控件,继承自ViewGroup,专门用以实现左右滑动切换View的效果,使用时需要首先在Project->prope ...
- 如何在adapter 中调用activity的方法
如何在adapter 中调用activity的方法 2015-08-07 17:06匿名 | 浏览 808 次 iWorkjavaAndroid public class HistoryData e ...
- 【转】 Pro Android学习笔记(三八):Fragment(3):基础小例子-续
目录(?)[-] Step 2实现Fragment指定调用类TitleFragment onInflate和onAttach onCreate和onCreateView onActivityCreat ...
- 【转】 Pro Android学习笔记(四一):Fragment(6):数据保留
目录(?)[-] 通过fragment参数实现数据保留 对TitleFragment进行修改 对DetailActivity进行修改 通过savedInstanceState进行数据保留 保留frag ...
- 【转】 Pro Android学习笔记(三九):Fragment(4):基础小例子-续
目录(?)[-] Step 3实现简介显示类DetailFragment 创建实例 编写所需的生命周期代码 Step 4实现showDetailint index如何管理fragment fragme ...
- 【转】Pro Android学习笔记(三六):Fragment(1):基本概念
目录(?)[-] 为何引入Fragment 大小屏幕的适配 横屏竖屏切换 返回键 什么是Fragment 为何引入Fragment 我们之前的Activity都是都是全屏处理较为简单的单一事务功能,适 ...
- 【转】 Pro Android学习笔记(三七):Fragment(2):基础小例子
目录(?)[-] 小例子运行效果 Pre-step一点准备 Step 1Activity的布局 小例子运行效果 这是一个书名和书简介的例子.运行如下图.Activity由左右两个Fragment组成, ...
- 67、activity中调用fragment内部自定义的方法
fragment: /** * author: Created by zzl on 15/11/19. */ @SuppressLint("validFragment") publ ...
- android学习日记04--开发中的通用细节
1.android中的计量单位 px (pixels)(像素):是屏幕的物理像素点,与密度相关,密度大了,单位面积上的px会比较多.通常不推荐使用这个 pt(磅):1/72英寸,也较少用 in(英寸) ...
随机推荐
- React Toolchains
React Toolchains Create React App / component library https://create-react-app.dev/docs/getting-star ...
- Chrome blocked third-party cookies
Chrome blocked third-party cookies Chrome Incognito Chrome 无痕模式 https://support.google.com/chrome/an ...
- Flutter & APP & UI Components
Flutter & APP & UI Components 下拉刷新或者上拉加载 https://github.com/OpenFlutter/flutter_screenutil h ...
- 【HTB系列】靶机Access的渗透测试详解
出品|MS08067实验室(www.ms08067.com) 本文作者:大方子(Ms08067实验室核心成员) Hack The Box是一个CTF挑战靶机平台,在线渗透测试平台.它能帮助你提升渗透测 ...
- 开源OA办公系统的“应用市场”,能够为协同办公开拓什么样的“前路”?
在我们的日常生活中,应用市场这个词,总是与智能手机划上等号,不管使用的是iPhone还是安卓,总会接触到手机上的APP应用市场,我们可以在应用市场中,选择自己所需要的APP应用软件,下载使用后,可以让 ...
- 用OkHttpGo和FastJson获取OneNET云平台数据(解析嵌套数组)
JSON数据格式有两种,一种是 { } 大括号表示的JSON对象,一种是 [ ] 中括号表示的JSON数组.从OneNET获取到的数组是这样的,并用Json解析网址查看https://jsonform ...
- springboot框架里的pom.xml文件里的m不显示,只有标红和<>符号的解决方法
这是因为没有把pom.xml文件加入到maven工程中,所以需要如图所示 亲测有效,原文链接:https://blog.csdn.net/qq_41026946/article/details/107 ...
- Linux安装jdk(两种方式)
最近在研究大数据方面的东西,业务场景是从设备采集数据经过处理然后存放DB. 建设上面的环境第一步肯定是安装jdk,所以和大家一起学一下基本知识centos7.5安装jdk1.8. 安装jdk有两种方法 ...
- `curl -L` 解决 GitHub 的 raw.githubusercontent.com 无法连接问题
解决 GitHub 的 raw.githubusercontent.com 无法连接问题 在使用 curl 下载文件时,如果出现以下情况 curl: (7) Failed to connect to ...
- WEB容器开启、关闭OPTIONS方法
发现 请求包随意,响应包信息如下: HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=utf-8 Vary ...