参考《Professional Android 4 Development》

Fragment简介

Fragment是我们可以将Activity分成不同的组成部分,这些组成部分拥有自己的生命周期和UI。它的最大用途在于适配不同的屏幕。

创建Fragment

Fragment和Activity有很多相似之处,例如可以不带UI,但这样做对两者似乎都没什么意义。他们的创建方式也很相似,例如下面的代码:

package test.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MySkeletonFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {// Create, or inflate the Fragment’s UI, and return it.// If this Fragment has no UI then return null.return inflater.inflate(R.layout.my_fragment, container, false);}
}

Fragment生命周期

Fragment的生命周期和它的宿主Activity密切相关,几乎和宿主Activity的生命周期一致,他们之间最大的不同在于Activity可以增加或删除Fragment。下图总结了Fragment的生命周期:

Fragment特有的生命周期事件

  1. Attach and detach Fragment from the parent Activity
  2. Creating and destroying Fragment
  3. Creating and Destroying UI

获取Fragment Manager

每个Activity对象都内置了一个FragmentManager对象,使用getFragmentManager()即可获得:

FragmentManager fragmentManager = getFragmentManager();

添加Fragment到Activity中

在Activity中添加Fragment的最简单方法是使用layout配置文件,例如:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><fragment android:name="com.paad.weatherstation.MyListFragment"android:id="@+id/my_list_fragment"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"/><fragment android:name="com.paad.weatherstation.DetailsFragment"android:id="@+id/details_fragment"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="3"/>
</LinearLayout>

调用inflate方法生成Fragment的界面后,Fragment实际上是一个类似ViewGroup的角色,在Activity中管理自己的UI。

上面那种将Fragment添加到Activity的方法缺乏灵活性,不能实现动态地添加和删除,更好的方式是使用FragmentTranaction和类似下面这样的配置文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayoutandroid:id="@+id/ui_container"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/details_container"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="3"/>
</LinearLayout>

使用FragmentTransaction

FragmentTransaction可以在运行时添加,删除或替换Fragment,从而实现UI的动态变化。Fragment Transaction由Fragment Manager的beginTransaction()方法创建,然后可以进行Fragment的添加,删除和替换,最后通过commit()方法提交修改。

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Add, remove, and/or replace Fragments.
// Specify animations.
// Add to back stack if required.
fragmentTransaction.commit();

添加,删除和替换Fragment

使用FragmentTransaction的add方法可以添加一个新的Fragment,add()方法的主要参数是Fragment的容器View(或其ID)及Fragment实例,例如:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.ui_container, new MyListFragment());
fragmentTransaction.commit();

删除Fragment需要FragmentTransaction的remove()方法,参数为Fragment对象,Fragment对象可以通过FragmentManager的findFragmentById()方法获得。

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();

替换Fragment使用的是FragmentTransaction的replace()方法,参数分别为所要替代Fragment所在容器的ID和新的Fragment:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.details_fragment, new DetailFragment(selected_index));
fragmentTransaction.commit();

获取指定的Fragment

有两种方法可以获取某个特定的Fragment,如果这个Fragment已经被添加到某个layout文件中,则可以使用xml文件中的id作为参数:

MyFragment myFragment = (MyFragment)fragmentManager.findFragmentById(R.id.MyFragment);

也可以通过创建Fragment时添加的tag获取特定的Fragment:

MyFragment myFragment = (MyFragment)fragmentManager.findFragmentByTag(MY_FRAGMENT_TAG);

删除Fragment容器

在配置文件中将visibility的属性设为"gone",即可删除某个Fragment,例如:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayoutandroid:id="@+id/ui_container"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/details_container"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="3"android:visibility="gone"/>
</LinearLayout>

Fragment和Back Stack

Activity拥有Activity Stack,从而在用户按”返回”按钮时,回到前一个Activity。Fragment也可以响应”返回”事件,方法是FragmentTransaction在commit之前调用addToBackStack()方法。这样,在用户按返回键后,Android会首先重现之前的UI布局。

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.ui_container, new MyListFragment());
Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);
fragmentTransaction.remove(fragment);
String tag = null;
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commit();

原理和Activity类似,调用addToBackStack()后,Fragment会被push到back stack中,而不是销毁。

Fragment Transaction的动画效果

Fragment Transaction有两种方法实现动画效果,分别是:

  • 设置渐进:

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

  • 设置动画效果:
fragmentTransaction.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right);

Fragment和宿主Activity之间的接口

Fragment可以通过getActivity()方法获得宿主Activity对象:

TextView textView = (TextView)getActivity().findViewById(R.id.textview);

另一种常见的Fragment和Activity之间的交互方式是使用回调函数:

public interface OnSeasonSelectedListener {public void onSeasonSelected(Season season);
}
private OnSeasonSelectedListener onSeasonSelectedListener;private Season currentSeason;@Overridepublic void onAttach(Activity activity) {super.onAttach(activity);try {onSeasonSelectedListener = (OnSeasonSelectedListener)activity;} catch (ClassCastException e) {throw new ClassCastException(activity.toString() +"must implement OnSeasonSelectedListener");}}private void setSeason(Season season) {currentSeason = season;onSeasonSelectedListener.onSeasonSelected(season);
}

没有UI的Fragment

尽管不常见,但Fragment的确是可以没有UI的,好处也许是拥有了更灵活的生命周期控制。没有UI的Fragment生命周期事件有这些:

public class NewItemFragment extends Fragment {@Overridepublic void onAttach(Activity activity) {  super.onAttach(activity);   // Get a type-safe reference to the parent Activity.}@Overridepublic void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      // Create background worker threads and tasks.}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);
      // Initiate worker threads and tasks.}
}

常用的Fragment类

  • DiagFragment
  • ListFragment
  • webViewFragment

Android 4学习(8):用户界面 - Fragment相关推荐

  1. Android Studio初学者实例:Fragment学习--仿美团外卖界面

    本次课程为Fragment为主题,课程的示例仿美团外卖界面,不同于底部导航栏的Fragment案例,此界面分为左侧切换与顶部切换.本文先是发布代码与效果,后续讲解将会在后续补充.先看看效果: 首先是布 ...

  2. android fragment 菜单栏,android UI:底部菜单栏的学习与制作——Fragment碎片一

    碎片(Fragment) 嵌入与活动中的UI片段,为了合理的分配布局而存在,这是我的简单理解.多用于兼顾手机与平板的UI,也适用于灵活高级的UI制作. Demo 简单的按键切换两片不同的Demo 新建 ...

  3. android fragment 教程,Android app开发中的Fragment入门学习教程

    在Android3.0上开始引入了一个新概念叫Fragment.它有自己的布局文件,可以作为组件排布,也可以相互组合去实现不同的布局显示.使用Fragment可以重复利用代码,并且可以满足不同设备尺寸 ...

  4. 疯狂Android讲义 - 学习笔记(二)

    疯狂Android讲义 - 学习笔记(二) Android应用的用户界面编程 2.1 界面编程与视图(View)组件 Android应用的绝大部分UI组件放在android.widget.androi ...

  5. Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数

     Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数 时间 2014-04-19 23:05:55 CSDN博客 原文  http ...

  6. Android:日常学习笔记(8)———探究UI开发(2)

    Android:日常学习笔记(8)---探究UI开发(2) 对话框 说明: 对话框是提示用户作出决定或输入额外信息的小窗口. 对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模式事件. 提示 ...

  7. Android开发之ViewPager+ActionBar+Fragment实现响应式可滑动Tab

    今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可以 ...

  8. Android开发学习之基于ViewPager实现Gallery画廊效果

    通过我们前面的学习,我们知道ViewPager是可以做出近乎完美的滑动体验,回顾整个Android,我们发现Gallery具备同样的特点,于是我们大胆地猜想,Gallery是否和ViewPager之间 ...

  9. Android 开发学习笔记:七大知识点板块汇总

    前言 我从事 Android 开发行业也有些年头,工作期间也接触过很多 Android 开发者, 因此也非常清楚 程序员最大的限制并非年龄而是实力: 但大多数初中级Android工程师,想要提升技能, ...

  10. Android简单学习使用PictureSelector框架图片选取裁剪

    Android简单学习使用PictureSelector框架图片选取裁剪 关于 效果图 第一步,添加引用 第二步,新建activity_main.xml布局文件 第三步,修改MainActivity. ...

最新文章

  1. MySQL5.5复制新特性
  2. 小工匠聊架构-分布式场景下的并发幂等性常见的解决方案
  3. dp 扔鸡蛋_使用动态编程(DP)的鸡蛋掉落问题
  4. javascript函数式_JavaScript中的函数式编程原理
  5. openstack私有云_OpenStack-下一代私有云的未来
  6. html字符串替换src,替换html字符串中img标签src的值.
  7. [RMAN]表空间的恢复
  8. python email模块详解_Python使用email模块对邮件进行编码和解码的实例教程
  9. html5 播放加密视频播放器,.NET MVC对接POLYV——HTML5播放器播放加密视频
  10. sql家庭成员、收入支出数据库
  11. 3904三极管是什么功能_新方法讲解三极管工作原理
  12. 橙子君正在维护服务器,橙子VR常见问题有哪些 橙子VR常见问题答案汇总
  13. 2013/06 事情发生之后都会显得云淡风轻
  14. BUUCTF~Misc~Test5
  15. 【flutter】整合高德地图amap_base
  16. 浅谈人工智能与游戏思维
  17. java抽象类有什么用_java中抽象类的作用是什么?抽象类作用的例子
  18. CCF CSP 201609-2 火车购票 C++实现 100分
  19. android音频系统(7):通话过程中的音频输出设备切换
  20. 自制Darknet Yolo目标快速标注工具

热门文章

  1. python函数封装的好处_C++用类封装函数有什么好处么?
  2. CMD的基本使用方法
  3. 2022世界杯La‘eeb肖像,python海龟实现啦
  4. 明星软件工程师的10种特质
  5. 网络安全工程师入门之-信息收集(完整版)
  6. 解决问题】AttributeError: module 'pandas' has no attribute 'ewma'报错解决方法
  7. 痛心!阿里员工在家跳楼去世!
  8. 每日一个小技巧:想知道音频转文字怎么操作?1分钟帮你解决
  9. 小黄的刷题之路(九)——码题集OJ赛-列表实现简单“合成2048”
  10. 领域建模的思想和方法 1