Fragment 简介 基础知识 总结 MD
| Markdown版本笔记 | 我的GitHub首页 | 我的博客 | 我的微信 | 我的邮箱 |
|---|---|---|---|---|
| MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
目录
Fragment 知识点总结
FragmentActivity 简介
Fragment 和 Activity 的通讯
使用静态 Fragment
FragmentManager简介
带 RecyclerView 的 Fragment 模板代码
子 Fragment 的 onActivityResult 方法不被调用问题的解决方法
通过动态添加子 Fragment 的方式简化复杂的 Activity 或 Fragment
DialogFragment 使用简介
如何正确的判断当前的Fragment是否对用户可见
Fragment 知识点总结
FragmentActivity 简介
Fragment是3.0以后的东西,为了在低版本中使用Fragment就要用到android-support-v4兼容包,而Fragmentactivity就是这个兼容包里面的,它提供了操作Fragment的一些方法,其功能跟3.0及以后的版本的Activity的功能一样。
下面是API中的原话:
FragmentActivity is a special activity provided in the Support Library to handle fragments on system versions older than API level 11. If the lowest system version you support is API level 11 or higher, then you can use a regular Activity.
一些区别
- FragmentActivity继承自Activity,用来解决android3.0之前没有fragment的问题,所以在3.0前使用Fragment时需要导入support包,同时让Activity继承FragmentActivity,这样就能在Activity中使用Fragment了。
- 在3.0之后你直接继承自Activity就可以使用android.app.Fragment,但目前Google推荐使用support包中的Fragment。
- 两者获得FragmentManager的方式不同,3.0之前使用FragmentActivity时:getSupportFragmentManager(),3.0以后使用Activity时:getFragmentManager()
- 一定要保证你的Activity中和你的Fragment中导的包是一致的!
Fragment 和 Activity 的通讯
因为Fragment都是依附于Activity的,所以两者通信并不复杂,大概归纳为:
- 如果你Activity中包含此Fragment的引用,可以通过此引用直接访问Fragment所有的public方法
- 如果Activity中不保存此Fragment的引用,由于每个Fragment都有唯一的一个TAG或者ID,可以通过findFragmentByTag或者findFragmentById获得任何Fragment实例
- 在Fragment中可以通过getActivity得到当前绑定的Activity的实例
如果在Fragment中需要Context,可以通过调用getContext()或getActivity()或onAttach中的参数context获取,如果该Context需要在Activity被销毁后还存在,则使用getActivity().getApplicationContext()。
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.i("bqt", "【onAttach】" + (getContext() == getActivity()) + "-" + (context == getActivity())); //true-true
}
使用静态 Fragment
虽然简单,但有两点必须满足:
- 要通过
android:name属性指定所引用的fragment的全类名 - 必须给fragment设置
android:id,即使完全用不到
<fragment
android:id="@+id/fragment"
android:name="com.bqt.fragment.MyFragment"
android:layout_width="match_parent"
android:layout_height="45dp" />
FragmentManager简介
FragmentManager 可以做的事情:
- 使用 findFragmentById 或 findFragmentByTag 获取 activity 中存在的 fragment
- 使用 popBackStack() 将 fragment 从后台堆栈中弹出 (模拟用户按下BACK 命令)
- 使用 addOnBackStackChangeListener() 注册一个监听后台堆栈变化的 listener
- 开启一个事务 fm.benginTransatcion()
Fragment嵌套Fragment时,里面的Fragment要用
getChildFragmentManager获取到的FragmentManager
带 RecyclerView 的 Fragment 模板代码
public class MainBeaAppStoreFragment extends BaseFragment implements BaseQuickAdapter.OnItemClickListener {
private Context mContext;
private RecyclerView mRecyclerView;
private BeaAppStoreAdapter mAdapter;
private ArrayList<BeaAppItemInfo> list;
private static int REQUESTCODE_LOGIN_TONEWPAGE = 20094;
public static MainBeaAppStoreFragment newInstance(ArrayList<BeaAppItemInfo> list) {
MainBeaAppStoreFragment officeSimpleFragment = new MainBeaAppStoreFragment();
Bundle args = new Bundle();
args.putParcelableArrayList("list", list);
officeSimpleFragment.setArguments(args);
return officeSimpleFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getActivity();
list = getArguments() != null ? getArguments().getParcelableArrayList("list") : new ArrayList<>();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.bea_fragment_main_appstore, container, false);
mRecyclerView = view.findViewById(R.id.rv_group);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
int spanCount = list.size() >= 4 ? 4 : list.size();
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), spanCount));
//mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL));
mRecyclerView.addItemDecoration(new GridItemDecoration.Builder()
.spanCount(spanCount)//行数或列数
.spaceSize(SystemUtil.dp2px(15f))//行列间距大小
.mDivider(new ColorDrawable(Color.TRANSPARENT))
.includeLREdge(false).includeTBEdge(false)//是否包含上下左右边界
.drawLREdge(false).drawTBEdge(false)//是否绘制上下左右边界
.build());
mAdapter = new BeaAppStoreAdapter(list);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(this);
}
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
CherryCodeLogUtil.i("bqt", "【onActivityResult】" + requestCode);
//登录成功进行跳转
if (requestCode == REQUESTCODE_LOGIN_TONEWPAGE && resultCode == Activity.RESULT_OK) {
WebviewActivity.launche(mContext, true, "index.html", toNewPageSuffixUrl);
}
}
}
子 Fragment 的 onActivityResult 方法不被调用问题的解决方法
出现此问题的原因:程序bug,没有处理嵌套Fragment的情况,也就是说回调只到第一级Fragment,就没有继续分发。
我们可以实现一个自己的FragmentActiviy,来实现继续分发,如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
CherryCodeLogUtil.i("bqt", "【onActivityResult】" + requestCode);
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null && fragments.size() > 0) {
for (Fragment fragment : fragments) {
handleChildFragmentResult(fragment, requestCode, resultCode, data);
}
}
}
/**
* 递归调用,对所有的子Fragment生效
*/
private void handleChildFragmentResult(Fragment fragment, int requestCode, int resultCode, Intent data) {
fragment.onActivityResult(requestCode, resultCode, data);//调用每个Fragment的onActivityResult
List<Fragment> childFragments = fragment.getChildFragmentManager().getFragments(); //找到第二层Fragment
if (childFragments != null && childFragments.size() > 0) {
for (Fragment childFragment : childFragments) {
handleChildFragmentResult(childFragment, requestCode, resultCode, data);
}
}
}
通过动态添加子 Fragment 的方式简化复杂的 Activity 或 Fragment
根据情况使用【getFragmentManager】【getSupportFragmentManager】【getChildFragmentManager】
private void addFragment() {
Fragment fragment1 = fragmentManager.findFragmentById(R.id.fl_search);
Fragment fragment2 = fragmentManager.findFragmentById(R.id.fl_appstore);
Fragment fragment3 = fragmentManager.findFragmentById(R.id.fl_pic);
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (fragment1 == null) transaction.add(R.id.fl_search, SearchFragment.newInstance(name));
if (fragment2 == null) transaction.add(R.id.fl_appstore, AppStoreFragment.newInstance());
if (fragment3 == null) transaction.add(R.id.fl_pic, PicFragment.newInstance(picList));
transaction.commit();
}
DialogFragment 使用简介
在 DialogFragment 产生之前,我们创建对话框一般采用 AlertDialog 和 Dialog,DialogFragment 在 android 3.0 时被引入,是一种特殊的Fragment,用于在 Activity 的内容之上展示一个模态的对话框。
public class DialogFragment extends Fragment implements OnCancelListener, OnDismissListener {}
interface OnCancelListener { void onCancel(DialogInterface dialog); }
interface OnDismissListener { void onDismiss(DialogInterface dialog); }
传统的 AlertDialog 在屏幕旋转时,既不会保存用户输入的值,对话框也不会重建,还可能会报异常。而使用 DialogFragment 来管理对话框,当旋转屏幕和按下后退键时可以更好的管理其生命周期(自动重建),它和 Fragment 有着基本一致的生命周期。
使用 DialogFragment 需要实现onCreateView或者onCreateDIalog方法,onCreateView即使用自定义的 xml 布局文件展示 Dialog,onCreateDialog 则可利用 AlertDialog 或者 Dialog 创建出 Dialog。
DialogFragment 也允许开发者把 Dialog 作为内嵌的组件进行重用,类似 Fragment 可以在大屏幕和小屏幕显示出不同的效果(需要向Fragment那样,在onCreateView中返回Fragment的视图,而不应在onCreateDialog中创建Dialog的视图)。
DialogFragment 使用案例
调用方式:
MyDialogFragment.newInstance(position).show(fragmentManager, titles[position]);
fragmentManager.beginTransaction().add(R.id.id_container, MyDialogFragment.newInstance(position), titles[position]).commit();
DialogFragment实现类:
public class MyDialogFragment extends DialogFragment {
public static final String ARGUMENT = "returnType";
private int returnType = 0;
public static MyDialogFragment newInstance(int returnType) {
MyDialogFragment fragment = new MyDialogFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARGUMENT, returnType);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
returnType = bundle != null ? bundle.getInt(ARGUMENT) : 0;
Log.i("bqt", "【onCreate】" + returnType);
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Log.i("bqt", "【*********************onCreateDialog*********************】");//在 onCreateView 之前回调
if (returnType == 0) {
return super.onCreateDialog(savedInstanceState);
} else {
View rootView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_tab, null);
TextView tv = rootView.findViewById(R.id.tv);
tv.setText(returnType + ":" + new SimpleDateFormat("HH:mm:ss SSS", Locale.getDefault()).format(new Date()));
tv.setBackgroundColor(0xFF000000 + new Random().nextInt(0xFFFFFF));
if (returnType == 1) {
AlertDialog alertDialog = new AlertDialog.Builder(getContext()).setView(rootView).create();
alertDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);//设置AlertDialog背景透明效果
return alertDialog;
} else {
Dialog dialog = new Dialog(getContext());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);//设置Dialog没有标题。需在setContentView之前设置,在之后设置会报错
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);//设置Dialog背景透明效果
dialog.setContentView(rootView);
return dialog;
}
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("bqt", "【onCreateView】Dialog是否为null:" + (getDialog() == null));
if (returnType == 0) {
View rootView = inflater.inflate(R.layout.fragment_tab, container, false);
TextView tv = rootView.findViewById(R.id.tv);
tv.setText(returnType + ":" + new SimpleDateFormat("HH:mm:ss SSS", Locale.getDefault()).format(new Date()));
tv.setBackgroundColor(0xFF000000 + new Random().nextInt(0xFFFFFF));
return rootView;
} else {
return null;
}
}
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
Log.i("bqt", "【onCancel】");//在 onDismiss 之前回调
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
Log.i("bqt", "【*********************onDismiss*********************】"); //在 onPause 之前回调
}
}
如何正确的判断当前的Fragment是否对用户可见
- onResume:适用于单一Activity嵌套单一Fragment的场景,跟随载体Activity的生命周期,能得出正确的判断
- onHiddenChanged:适用于通过FragmentManager添加多个Fragment并且在点击切换Fragment的场景,通过FragmentManager的hide和show方法触发,能得出正确的判断
- setUserVisibleHint:适用于ViewPager中嵌套Fragment的场景,在PagerAdapter中左右滑动时通过设置当前显示的Fragment会触发该方法,能得出正确的判断
Fragment 简介 基础知识 总结 MD的更多相关文章
- SpringCloud(1) 架构演进和基础知识简介
一.传统架构演进到分布式架构 简介:讲解单机应用和分布式应用架构演进基础知识 (画图) 高可用 LVS+keepalive 1.单体应用:开发速度慢.启动时间长.依赖庞大.等等 2.微服务:易开发.理 ...
- Linq的简介和基础知识学习
学习LINQ之前,我们要知道LINQ是干什么,解决什么问题的,怎样学习? 一.LINQ简介 1.什么是LINQ? 什么是LINQ?LINQ中文翻译为语言集成查询(Language Integrated ...
- Mongodb 笔记01 MongoDB 简介、MongoDB基础知识、启动和停止MongoDB
MongoDB 简介 1. 易于使用:没有固定的模式,根据需要添加和删除字段更加容易 2. 易于扩展:MongoDB的设计采用横向扩展.面向文档的数据模型使它能很容易的再多台服务器之间进行分割.自动处 ...
- Java基础知识强化之集合框架笔记76:ConcurrentHashMap之 ConcurrentHashMap简介
1. ConcurrentHashMap简介: ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和Hashtable功能相同但是线程安全的方法.Conc ...
- Servlet学习笔记【1】--- 背景和基础知识(CGI、Web服务器发展史、Servlet简介、任务、继承结构)
本文主要讲Servlet的基础知识和背景知识. 1 CGI简介 CGI(Common Gateway Interface 公共网关接口)是WWW技术中最重要的技术之一,有着不可替代的重要地位.CGI是 ...
- PON系统基础知识简介
一 PON基础知识 1.1 PON技术概念 PON(Passive Optical Network)即无源光网络,一种基于点到多点(P2MP)拓朴的技术.“无源”指ODN(光分配网络)不含有任何电子 ...
- Vue基础知识简介
基础知识: vue的生命周期: beforeCreate/created.beforeMount/mounted.beforeUpdate/updated.beforeDestory/destorye ...
- 【SQL】- 基础知识梳理(二) - SQL简介
一.引言 在梳理这些知识之前,说实话,如果有人问我SQL是什么?我可能会回答就是“INSERT,DELETE,UPDATE,SELECT”语句呗,还能是啥. 二.SQL概念 SQL是什么? SQL是S ...
- IOS开发基础知识碎片-导航
1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...
随机推荐
- 高版本 eclipse 如何安装 fatjar 插件以及使用 fatjar 将 Java 程序打成 Jar 包
高版本 eclipse 如何安装 fatjar 插件以及使用 fatjar 将 Java 程序打成 Jar 包 Eclipse Version: Neon.3 Release (4.6.3) Welc ...
- Java String class methods
Java String class methods 现在不推荐使用 StringTokenizer 类.建议使用 String 类的 split()方法或 regex(正则表达式). String c ...
- Servlet技术——Servlet基础
Servlet是运行在Web服务器端的Java应用程序,它使用Java语言编写,具有Java语言的优点.与Java程序的区别是,Servlet对象主要封装了对HTTP请求的处理,并且它的运行需要Ser ...
- Unity 游戏开发技巧集锦之制作一个望远镜与查看器摄像机
Unity 游戏开发技巧集锦之制作一个望远镜与查看器摄像机 Unity中制作一个望远镜 本节制作的望远镜,在鼠标左键按下时,看到的视图会变大:当不再按下的时候,会慢慢缩小成原来的视图.游戏中时常出现的 ...
- FastReport.Net使用:[3]简单报表一
如何设置报表栏 1.右键报表栏相关模块进行删除. 2.使用菜单栏中的报表菜单进行添加/删除相应的栏目,选中栏目的背景会变得高亮. 3.使用报表栏编辑器. 可通过点击报表栏顶部的“设置报表栏”或者菜单栏 ...
- SOJ 4552 [期望,概率]
题目链接:[http://acm.scu.edu.cn/soj/problem.action?id=4552] 题意:给你n种卡牌,每种卡牌有无限多个,每次从中抽取一张卡牌,问:1.集齐这n种卡牌需要 ...
- 51nod1821 最优集合 贪心
首先考虑一个集合的最大优美值怎么求出 考虑新增一个数,假设我们现在的优美值已经达到了$V$,那么只需要一个$[1, V + 1]$的数就可以使$V$达到更大 为了保证能添加尽可能多的数进来,我们这么构 ...
- [ARC053D]2 つの山札
题意:给定排列$a_{1\cdots n},b_{1\cdots n}$,执行以下操作$2n-2$次来生成一个长度为$2n-2$的序列:选择$a,b$之一(选择的序列长度要$\geq2$),删除它的第 ...
- centos 7 修改ssh登录端口
在阿里云上面使用的oneinstack镜像,默认是使用的22端口,每次登录总会发现有人在暴力破解我的服务器,所以想想还是修改一下比较安全. 1.在防火墙打开新的端口 iptables -I INPUT ...
- 自定义的tabBarController的几种方法
本文转载自:http://blog.sina.com.cn/s/blog_79c5bdc30100t88i.html 我自己实现的一种可以很方便的实现更换TabBarController图片的方法,代 ...