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(英寸) ...
随机推荐
- HTML5 Animation Creator | Hype 官方文档
HTML5 Animation Creator | Hype 官方文档 HTML5 Animation Build 7个 专业术语 场景,元素,属性,关键帧,动画,时间线,操作 Hype 官方文档 h ...
- H5 下拉刷新、加载更多
H5 下拉刷新.加载更多 demos const autoLoadMore = (url = ``) => { // todo ... } refs xgqfrms 2012-2020 www. ...
- ES6 Arrow Function return Object
ES6 Arrow Function return Object https://github.com/lydiahallie/javascript-questions/issues/220#issu ...
- input number step
input number step <!DOCTYPE html> <html> <body> <h1>The input step attribute ...
- Captain technology INC:全球新能源汽车格局突变
美国能源信息署EIA的统计数据显示,2020年上半年全美含纯电动和插电混动在内的新能源乘用车总销量仅为11.1万辆,同比缩水25%.虽然特斯拉在第三季度靠着13.93万辆的销量迎来了环比387%.同比 ...
- 币圈沸腾!SPC空投上线!不要错过!
币圈最近处于沸腾的时刻,NGK侧链代币SPC已上线钱包,3.0公链NGK生态之SPC空投又来了,NGK的上一个项目BGV投资收益率最高破一千七百倍,NGK官方此次以算力持有者为中心,将发起第二轮福利- ...
- 详解Go语言调度循环源码实现
转载请声明出处哦~,本篇文章发布于luozhiyun的博客: https://www.luozhiyun.com/archives/448 本文使用的go的源码15.7 概述 提到"调度&q ...
- java自学第5期——Object、Date、Calender、System、StringBuilder、基本类型包装类
一.Object类 作用:对象操作 位置:java.lang.Object 方法: public String toString() :返回对象的字符串表示形式. public boolean equ ...
- scala:分别使用懒汉式和饿汉式实现单例模式
在java中,单例模式需要满足以下要求: 构造方法私有化,使得本类之外的地方不能使用构造方法new出对象 提供私有静态属性,接收单例对象 公共的.静态的getInstance方法,便于外界拿到单例对象 ...
- Java基础语法:标识符
Java所有的组成部分都需要名字. 类名.变量名 以及方法名 都被称为标识符. 一.规则 Ⅰ.首字符 规则:所有的标识符都应该以字母(A-Z 或者 a-z).美元符($).下划线(_)开始. 示例:t ...