•前言

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

最新文章

  1. python os.walk()
  2. 解决discuz论坛搬家:“Table ‘common_syscache’ is read only”问题
  3. 9月java货车版速记
  4. WPF实现3D翻转的动画效果
  5. python 实现斐波那契数列
  6. (2)在vs2010上配置opengl
  7. 使用java远程调试技术监控代码运行
  8. 关于“ubuntu18.04下网易云无法启动”的问题解决方案
  9. noip飞扬的小鸟
  10. [leetcode] 329. Longest Increasing Path in a Matrix My Submissions Question
  11. HDU 3033 分组背包(至少选一个)
  12. [leetcode]131. Palindrome Partitioning字符串分割成回文子串
  13. POJ1015 DP
  14. u3d局域网游戏网络(c# socket select 模型)
  15. compoer 全局和单个项目切换源 composer update killed
  16. javascript 数组排序
  17. Oracle sql 中的 ALL,ANY,SOME
  18. request bs4
  19. 用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具
  20. Ubuntu 16.04安装双显卡驱动方法收集

热门文章

  1. 2020 Web 全栈面经
  2. 微信小程序 UI 组件库
  3. CSS3 Animation &amp; Weather Icons
  4. Learning CSS with Chrome DevTools
  5. console.log &amp; front-end jobs
  6. 关于Python 编码的一点认识
  7. mysql explain type详解
  8. 宝塔面板配置Let&#39;s Encrypt证书自动续签失效及解决方案
  9. 生成类库项目时同时生成的pdb文件是什么东东?
  10. 【Notes】现代图形学入门_02