< TextView android : layout _ width = " match _ parent " android : layout _ height = " 100 dp " android : gravity = " center " android : text = " Good Boy " / > < fragment android : id = " @ + id / myfragment " android : name = " com . usher . fragment . MyFragment " android : layout _ width = " match _ parent " android : layout _ height = " match _ parent " / > < / LinearLayout > public class MyFragment extends Fragment { public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View v = inflater . inflate ( R . layout . item _ fragment , container , false ) ; return v ; } } public class MyFragment 2 extends Fragment { public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View v = inflater . inflate ( R . layout . item _ fragment 2 , container , false ) ; return v ; } } < LinearLayout xmlns : android = " http : / / schemas . android . com / apk / res / android " xmlns : tools = " http : / / schemas . android . com / tools " android : layout _ width = " match _ parent " android : layout _ height = " match _ parent " android : orientation = " vertical " tools : context = " com . usher . fragment . MainActivity " > < Button android : id = " @ + id / bt _ red " android : layout _ width = " match _ parent " android : layout _ height = " wrap _ content " android : text = " Red " / > < Button android : id = " @ + id / bt _ blue " android : layout _ width = " match _ parent " android : layout _ height = " wrap _ content " android : text = " Blue " / > < FrameLayout android : id = " @ + id / myframelayout " android : layout _ width = " match _ parent " android : layout _ height = " match _ parent " / > < / LinearLayout > public class MainActivity extends AppCompatActivity { private Button bt _ red ; private Button bt _ blue ; private FragmentManager manager ; private MyFragment fragment 1 ; private MyFragment 2 fragment 2 ; @ Override protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ) ; setContentView ( R . layout . activity _ main ) ; initView ( ) ; fragment 1 = new MyFragment ( ) ; fragment 2 = new MyFragment 2 ( ) ; / / 初始 化 FragmentManager 对象 manager = getSupportFragmentManager ( ) ; / / 使用 FragmentManager 对象 用来 开启 一个 Fragment 事务 FragmentTransaction transaction = manager . beginTransaction ( ) ; / / 默认 显示 fragment 1 transaction . add ( R . id . myframelayout , fragment 1 ) . commit ( ) ; / / 对 bt _ red 设置 监听 bt _ red . setOnClickListener ( new View . OnClickListener ( ) { @ Override public void onClick ( View v ) { FragmentTransaction transaction = manager . beginTransaction ( ) ; transaction . replace ( R . id . myframelayout , fragment 1 ) . commit ( ) ; } } ) ; / / 对 bt _ blue 设置 监听 bt _ blue . setOnClickListener ( new View . OnClickListener ( ) { @ Override public void onClick ( View v ) { FragmentTransaction transaction = manager . beginTransaction ( ) ; transaction . replace ( R . id . myframelayout , fragment 2 ) . commit ( ) ; } } ) ; } private void initView ( ) { bt _ red = ( Button ) findViewById ( R . id . bt _ red ) ; bt _ blue = ( Button ) findViewById ( R . id . bt _ blue ) ; } } 运行 效果 图 默认 显示 点击 BLUE 按钮 时 点击 RED 按钮 时 以上 代码 我 写 的 比较 臃肿 但是 比较 容易 看 明白 : ① 在 Acitivity 对应 的 布局 中 写 上 一个 FramLayout 控件 , 此 空间 的 作用 是 当作 Fragment 的 容器 , Fragment 通过 FrameLayout 显示 在 Acitivity 里 , 这 两 个 单词 容易 混淆 , 请 注意 ② 准备 好 你 的 Fragment , 然后 再 Activity 中 实例 化 , v4 包 的 Fragment 是 通过 getSupportFragmentManager ( ) 方法 新建 Fragment 管理 器 对象 , 此处 不 讨论 app 包 下 的 Fragment ③ 然后 通过 Fragment 管理 器 对象 调用 beginTransaction ( ) 方法 , 实例 化 FragmentTransaction 对象 , 有 人称 之 为 事务 ④ FragmentTransaction 对象 【 以下 直接 用 transaction 代替 】 , transaction 的 方法 主要 有 以下 几 种 : transaction . add ( ) 向 Activity 中 添加 一个 Fragment transaction . remove ( ) 从 Activity 中 移除 一个 Fragment , 如果 被 移除 的 Fragment 没有 添加 到 回 退 栈 ( 回 退 栈 后面 会 详细 说 ) , 这 个 Fragment 实例 将 会 被 销毁 transaction . replace ( ) 使用 另 一个 Fragment 替换 当前 的 , 实际 上 就是 remove ( ) 然后 add ( ) 的 合体 transaction . hide ( ) 隐藏 当前 的 Fragment , 仅仅 是 设 为 不 可见 , 并 不会 销毁 transaction . show ( ) 显示 之前 隐藏 的 Fragment detach ( ) 会 将 view 从 UI 中 移除 , 和 remove ( ) 不同 , 此时 fragment 的 状态 依然 由 FragmentManager 维护 attach ( ) 重建 view 视图 , 附加 到 UI 上 并 显示 ransatcion . commit ( ) 提交 事务 注意 : 在 add / replace / hide / show 以后 都 要 commit 其 效果 才 会 在 屏幕 上 显示 出来 4 . 什么 是 Fragment 的 回 退 栈 Fragment 的 回 退 栈 是 用来 保存 每 一次 Fragment 事务 发生 的 变化 。 如果 你 将 Fragment 任务 添加 到 回 退 栈 , 当 用户 点击 回 退 按钮 时 , 将 看到 上 一次 的 保存 的 Fragment 。 一旦 Fragment 完全 从 回 退 栈 中 退出 , 用户 再次 点击 回 退 键 , 则 退出 当前 Activity 那么 这 句 话 要 怎么 理解 ? 首先 我们 来 看 一下 这 个 东西 : 首先 , 显示 第 一 个 FragmentOne 页面 有 一个 Button in FragmentOne 按钮 , 上面 有 个 输入 框 显示 的 是 Fragment One 然后 输入 change , 点击 Button in FragmentOne 按钮 , 然后 显示 第 二 个 Fragment , 里面 有 一个 Button in FragmentTwo 按钮 , 一个 输入 框 显示 Fragment Two 然后 继续 输入 change , 点击 Button in FragmentTwo 按钮 , 显示 第 三 个 Fragment , 里面 有 个 Button in FragmentThree 按钮 , 点击 按钮 显示 出 一个 Toast 【 注意 】 点击 返回 键 , 跳转 到 前 一个 FragmentTwo , 这 个 时候 可以 看到 上面 的 输入 框 中 显示 的 是 Fragment Two change , 也 就是 说 保留 了 我们 离开 这 个 Fragment 时候 他 所 呈现 的 状态 【 注意 】 但 我们 再 点击 返回 键 , 跳转 到 FragmentOne , 但是 这 个 时候 我们 可以 看到 上面 的 输入 框 中 只有 Fragment One , 并 没有 change 这 几 个 字母 那么 原因 是 什么 呢 ? 这里 先 要 学习 一个 方法 : FragmentTransaction . addToBackStack ( String ) 【 把 当前 事务 的 变化 情况 添加 到 回 退 栈 】 代码 如下 : MainActivity 的 布局 文件 public class MainActivity extends Activity { protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ) ; requestWindowFeature ( Window . FEATURE _ NO _ TITLE ) ; setContentView ( R . layout . activity _ main ) ; FragmentManager fm = getFragmentManager ( ) ; FragmentTransaction tx = fm . beginTransaction ( ) ; tx . add ( R . id . id _ content , new FragmentOne ( ) , " ONE " ) ; tx . commit ( ) ; } } public class FragmentOne extends Fragment implements OnClickListener { private Button mBtn ; @ Override public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View view = inflater . inflate ( R . layout . fragment _ one , container , false ) ; mBtn = ( Button ) view . findViewById ( R . id . id _ fragment _ one _ btn ) ; mBtn . setOnClickListener ( this ) ; return view ; } @ Override public void onClick ( View v ) { FragmentTwo fTwo = new FragmentTwo ( ) ; FragmentManager fm = getFragmentManager ( ) ; FragmentTransaction tx = fm . beginTransaction ( ) ; tx . replace ( R . id . id _ content , fTwo , " TWO " ) ; tx . addToBackStack ( null ) ; tx . commit ( ) ; } } Fragment 的 点击 事件 里 写 的 是 replace 方法 , 相当 于 remove 和 add 的 合体 , 并且 如果 不 添加 事务 到 回 退 栈 , 前 一个 Fragment 实例 会 被 销毁 。 这里 很 明显 , 我们 调用 tx . addToBackStack ( null ) 将 当前 的 事务 添加 到 了 回 退 栈 , 所以 FragmentOne 实例 不会 被 销毁 , 但是 视图 层次 依然 会 被 销毁 , 即 会 调用 onDestoryView 和 onCreateView 。 所以 【 请 注意 】 , 当 之后 我们 从 FragmentTwo 返回 到 前 一个 页面 的 时候 , 视图 层 仍旧 是 重新 按照 代码 绘制 , 这里 仅仅 是 是 实例 没有 销毁 , 因此 显示 的 页面 中 没有 change 几 个 字 。 FragmentTwo . java 文件 public class FragmentTwo extends Fragment implements OnClickListener { private Button mBtn ; @ Override public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View view = inflater . inflate ( R . layout . fragment _ two , container , false ) ; mBtn = ( Button ) view . findViewById ( R . id . id _ fragment _ two _ btn ) ; mBtn . setOnClickListener ( this ) ; return view ; } @ Override public void onClick ( View v ) { FragmentThree fThree = new FragmentThree ( ) ; FragmentManager fm = getFragmentManager ( ) ; FragmentTransaction tx = fm . beginTransaction ( ) ; tx . hide ( this ) ; tx . add ( R . id . id _ content , fThree , " THREE " ) ; / / tx . replace ( R . id . id _ content , fThree , " THREE " ) ; tx . addToBackStack ( null ) ; tx . commit ( ) ; } } 这里 点击 时 , 我们 没有 使用 replace , 而是 先 隐藏 了 当前 的 Fragment , 然后 添加 了 FragmentThree 的 实例 , 最后 将 事务 添加 到 回 退 栈 。 这样 做 的 目的 是 为了 给 大家 提供 一 种 方案 : 如果 不 希望 视图 重 绘 该 怎么 做 , 请 再次 仔细 看 效果 图 , 我们 在 FragmentTwo 的 EditText 填写 的 内容 , 用户 点击 返回 键 回来 时 , 内容 还 在 。 FragmentThree . java 文件 public class FragmentThree extends Fragment implements OnClickListener { private Button mBtn ; @ Override public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View view = inflater . inflate ( R . layout . fragment _ three , container , false ) ; mBtn = ( Button ) view . findViewById ( R . id . id _ fragment _ three _ btn ) ; mBtn . setOnClickListener ( this ) ; return view ; } @ Override public void onClick ( View v ) { Toast . makeText ( getActivity ( ) , " i am a btn in Fragment three " , Toast . LENGTH _ SHORT ) . show ( ) ; } } 如果 你 还是 不 明白 请 仔细 将 上面 的 代码 反复 敲 几 遍 5 . Fragment 与 Activity 之间 的 通信 Fragment 依附 于 Activity 存在 , 因此 与 Activity 之间 的 通信 可以 归纳 为 以下 几 点 : 如果 你 Activity 中 包含 自己 管理 的 Fragment 的 引用 , 可以 通过 引用 直接 访问 所有 的 Fragment 的 public 方法 如果 Activity 中 未 保存 任何 Fragment 的 引用 , 那么 没 关系 , 每 个 Fragment 都 有 一个 唯一 的 TAG 或者 ID , 可以 通过 getFragmentManager . findFragmentByTag ( ) 或者 findFragmentById ( ) 获得 任何 Fragment 实例 , 然后 进行 操作 Fragment 中 可以 通过 getActivity ( ) 得到 当前 绑定 的 Activity 的 实例 , 然后 进行 操作 。 点击 查看 Activity 与 Fragment 通信 实例 6 . Fragment 与 Activity 通信 的 优化 因为 要 考虑 Fragment 的 重复 使用 , 所以 必须 降低 Fragment 与 Activity 的 耦合 , 而且 Fragment 更 不 应该 直接 操作 别的 Fragment , 毕竟 Fragment 操作 应该 由 它 的 管理 者 Activity 来 决定 。 实现 与 上 一个 代码 案例 一模一样 的 功能 与 效果 FragmentOne . java 文件 public class FragmentOne extends Fragment implements OnClickListener { private Button mBtn ; / / 设置 按钮 点击 的 回 调 public interface FOneBtnClickListener { void onFOneBtnClick ( ) ; } @ Override public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View view = inflater . inflate ( R . layout . fragment _ one , container , false ) ; mBtn = ( Button ) view . findViewById ( R . id . id _ fragment _ one _ btn ) ; mBtn . setOnClickListener ( this ) ; return view ; } / / 交给 宿主 Activity 处理 , 如果 他 希望 处理 @ Override public void onClick ( View v ) { if ( getActivity ( ) instanceof FOneBtnClickListener ) { ( ( FOneBtnClickListener ) getActivity ( ) ) . onFOneBtnClick ( ) ; } } } 可以 看到 , 现在 的 FragmentOne 不 和 任何 Activity 耦合 , 任何 Activity 都 可以 使用 , 并且 我们 声明 了 一个 接口 , 来回 调 其 点击 事件 , 想 要 重写 其 点击 事件 的 Activity 实现 此 接口 即可 , 可以 看到 我们 在 onClick 中 首先 判断 了 当前 绑定 的 Activity 是否 实现 了 该 接口 , 如果 实现 了 则 调用 。 FragmentTwo . java 文件 public class FragmentTwo extends Fragment implements OnClickListener { private Button mBtn ; private FTwoBtnClickListener fTwoBtnClickListener ; public interface FTwoBtnClickListener { void onFTwoBtnClick ( ) ; } / / 设置 回 调 接口 public void setfTwoBtnClickListener ( FTwoBtnClickListener fTwoBtnClickListener ) { this . fTwoBtnClickListener = fTwoBtnClickListener ; } @ Override public View onCreateView ( LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) { View view = inflater . inflate ( R . layout . fragment _ two , container , false ) ; mBtn = ( Button ) view . findViewById ( R . id . id _ fragment _ two _ btn ) ; mBtn . setOnClickListener ( this ) ; return view ; } @ Override public void onClick ( View v ) { if ( fTwoBtnClickListener ! = null ) { fTwoBtnClickListener . onFTwoBtnClick ( ) ; } } } 与 FragmentOne 极其 类似 , 但是 我们 提供 了 setListener 这样 的 方法 , 意味 着 Activity 不仅 需要 实现 该 接口 , 还 必须 显示 调用 mFTwo . setfTwoBtnClickListener ( this ) 。 MainActivity . java 文件" />
您当前的位置:首页 > 博客教程

安卓fragment详解_安卓fragment详解

时间:2023-11-19 05:08 阅读数:7852人阅读

∪▽∪

Non-compliance ICP Filing

?0?

i7加速器部分文章、数据、图片来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知删除。邮箱:xxxxxxx@qq.com

上一篇:安卓fragment详解

下一篇:安卓fragment