•前言

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

  到这,就大功告成了;

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

•声明

  参考资料:

  【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. MathJax TeX & LaTeX

    MathJax TeX & LaTeX mathcal https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-z ...

  2. Vue 组件之间通信 All in One

    Vue 组件之间通信 All in One 组件间通信 1. 父子组件之间通信 https://stackblitz.com/edit/vue-parent-child-commutation?fil ...

  3. very useful English Acronyms in Programming for Programmer

    very useful English Acronyms in Programming for Programmer alias / shorthand / acronyms 别名 / 简写 / 缩略 ...

  4. Redis all in one

    Redis all in one Redis: REmote DIctionary Server https://redis.io/topics/quickstart Download, extrac ...

  5. Flutter: The getter 'futureDynamicType' was called on null.

    > flutter packages pub upgrade

  6. DeFi 热潮下,NGK将成为下一个财富密码

    区块链正在脱虚向实,处于大规模落地,赋能实体产业的前夜,而在这个关键的关口,一个万亿市场的蓝海正在缓缓生成,成为区块链落地的急先锋,这个先锋便是DeFi. DeFi,即Decentralized Fi ...

  7. RecycleView 点击事件监听

    1.定义RecycleView 监听接口类 1 package com.example.*****; 2 3 import android.view.View; 4 5 public interfac ...

  8. winform导入excel或者csv

    if (txt01.Text != "") { this.lbzhantie.Items.Clear(); this.dtzhuanhuo.Rows.Clear(); if (tx ...

  9. EasyExcel学习

    导入依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</a ...

  10. 微软YARP初体验

    本文讨论了微软的反向代理--YARP.YARP是一个可以创建高性能.高度可定制的反向代理服务器的类库.那么什么是反向代理呢?反向代理是位于用户与目标服务器之间的中间连接点.它接收初始的HTTP连接请求 ...