Android学习之在Adapter中调用Fragment

时间:2022-01-07 22:41:56

•前言

  在学习《第一行代码》,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;
}
}

  该方法同新闻应用中的添加适配器的方式相同,在此不再赘述;

运行效果

  Android学习之在Adapter中调用Fragment

•独立类方式

  新建一个 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;
}
}

  到这,就大功告成了;

  运行一下,你会发现,成功实现内部类的实现效果;

•声明

  参考资料:

  【adapter调用fragment中的方法

  【在适配器Adapter中回调他的点击事件到activity或者fragment当中

Android学习之在Adapter中调用Fragment的更多相关文章

  1. 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题

    ViewPager是android-support-v4.jar包中的一个系统控件,继承自ViewGroup,专门用以实现左右滑动切换View的效果,使用时需要首先在Project->prope ...

  2. 如何在adapter 中调用activity的方法

    如何在adapter 中调用activity的方法 2015-08-07 17:06匿名 | 浏览 808 次  iWorkjavaAndroid public class HistoryData e ...

  3. 【转】 Pro Android学习笔记(三八):Fragment(3):基础小例子-续

    目录(?)[-] Step 2实现Fragment指定调用类TitleFragment onInflate和onAttach onCreate和onCreateView onActivityCreat ...

  4. 【转】 Pro Android学习笔记(四一):Fragment(6):数据保留

    目录(?)[-] 通过fragment参数实现数据保留 对TitleFragment进行修改 对DetailActivity进行修改 通过savedInstanceState进行数据保留 保留frag ...

  5. 【转】 Pro Android学习笔记(三九):Fragment(4):基础小例子-续

    目录(?)[-] Step 3实现简介显示类DetailFragment 创建实例 编写所需的生命周期代码 Step 4实现showDetailint index如何管理fragment fragme ...

  6. 【转】Pro Android学习笔记(三六):Fragment(1):基本概念

    目录(?)[-] 为何引入Fragment 大小屏幕的适配 横屏竖屏切换 返回键 什么是Fragment 为何引入Fragment 我们之前的Activity都是都是全屏处理较为简单的单一事务功能,适 ...

  7. 【转】 Pro Android学习笔记(三七):Fragment(2):基础小例子

    目录(?)[-] 小例子运行效果 Pre-step一点准备 Step 1Activity的布局 小例子运行效果 这是一个书名和书简介的例子.运行如下图.Activity由左右两个Fragment组成, ...

  8. 67、activity中调用fragment内部自定义的方法

    fragment: /** * author: Created by zzl on 15/11/19. */ @SuppressLint("validFragment") publ ...

  9. android学习日记04--开发中的通用细节

    1.android中的计量单位 px (pixels)(像素):是屏幕的物理像素点,与密度相关,密度大了,单位面积上的px会比较多.通常不推荐使用这个 pt(磅):1/72英寸,也较少用 in(英寸) ...

随机推荐

  1. 关于JNI的使用方法

    1首先在java里面定义你需要的native方法 2打开cmd,进入doc窗口,如果是android项目就进入到你当前项目的bin目录下,在doc里面输入cd E:\workspace\Test1 也 ...

  2. init&period;sh 学习(转

    cd /mnt insmod ss_triger_drv.ko insmod ss_led_alarm_drv.ko insmod ss_img_prc_drv.ko insmod ss_post_i ...

  3. MVC 安装

    mvc 4 支持window xp,window 7,window 8, mvc 4 支持vs2010,vs2012 vs2012中包含mvc4; vs2010中需要安装mvc4 安装包:

  4. 设置TabBarItem选中时的图片及文字颜色

    TabBarItem选中时,默认文字和图片都变为蓝色.使用以下代码可以进行修改. MainViewController *mainVC = [[MainViewController alloc] in ...

  5. javascript 概述及基础知识点(变量,常量,运算符,数据类型)

    JavaScript概述 1.1 什么是JavaScript: javaScript(简称js),是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言.同时也是一种广泛用于客户端Web开发的脚本语 ...

  6. DTCoreText

    背景:使用DTCoreText实现epub阅读器的内容排版 基础准备:coretext,HTML+CSS渲染机制,epub文件格式 一:ios端epub实现:主要是两种,coretext,webvie ...

  7. LoadRunner

    LoadRunner,是一种预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找LoadRunner能够对整个企业架构进行测试.通过使用LoadRunne ...

  8. X级联动

    前端数据 @{ ViewBag.Title = "Index"; } <script src="~/Scripts/jquery-1.10.2.js"&g ...

  9. CentOS 6&period;8 配置防火墙,开放8080端口

    打开配置文件 sudo vim /etc/sysconfig/iptables 按下a,进入编辑 加入这一行 -A INPUT -m state --state NEW -m tcp -p tcp - ...

  10. Jqgrid pager 关于&OpenCurlyDoubleQuote;local” dataType 动态加载数据分页的研究(没好用的研究结果)

    系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...