Fragments是什么?
碎片(Fragment)是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分
地利用大屏幕的空间,因而在平板上应用的非常广泛。
创建一个动态的、多窗格在Android用户界面,您需要将UI组件和Activity行为封装到模块,而这些模块你可以用来交换的活动。
您可以创建这些模块与Fragment类,这行为有点像一个嵌套的Activity,可以定义自己的布局和管理自己的生命周期。
Fragment 的生命周期
碎片的生命周期类似于活动的生命周期,可能的状态如下:
1. 运行状态
当一个碎片是可见的,并且它所关联的活动正处于运行状态时,该碎片也处于运行
状态。
2.暂停状态
当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与
它相关联的可见碎片就会进入到暂停状态。
3. 停止状态
当一个活动进入停止状态时,与它相关联的碎片就会进入到停止状态。或者通过调
用 FragmentTransaction 的 remove()、replace()方法将碎片从活动中移除,但有在事务提
交之前调用 addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入
停止状态的碎片对用户来说是完全不可见的,有可能会被系统回收。
4. 销毁状态
碎片总是依附于活动而存在的,因此当活动被销毁时,与它相关联的碎片就会进入
到销毁状态。或者通过调用 FragmentTransaction 的 remove()、replace()方法将碎片从活
动中移除,但在事务提交之前并没有调用 addToBackStack()方法,这时的碎片也会进入
到销毁状态。
Fragment 类中也提供了一系列的回调方法,以覆盖碎片生命周期的每个环节。其中,活动中有的回调方法,碎片
中几乎都有,不过碎片还提供了一些附加的回调方法,主要的如下:
1. onAttach()
当碎片和活动建立关联的时候调用。
2. onCreateView()
为碎片创建视图(加载布局)时调用。
3. onActivityCreated()
确保与碎片相关联的活动一定已经创建完毕的时候调用。
4. onDestroyView()
当与碎片关联的视图被移除的时候调用。
5. onDetach()
当碎片和活动解除关联的时候调用。
生命周期如图所示
创建一个 Fragment 类
为了创建一个Fragement,需要继承 Fragment 类,然后重写有关生命周期的方法并在其中插入你需要的逻辑,类似创建一个活动
唯一不同的一点就是你需要实现 onCreateView()
来返回定义的布局
需要自己定义一个XML布局
public class ArticleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.article_view, container, false); } }
就像一个活动,fragment也拥有生命周期函数,用来从活动中添加或删除和与活动的生命周期状态之间的对应。
例如当活动的onPause()被调用时,活动中的fragment也会收到调用onPause()
利用XML文件添加Fragment到活动中
添加 <fragment> 元素,并将 <fragment> 的 name 属性设置为创建的fragment类
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <fragment android:name="com.example.android.fragments.HeadlinesFragment" android:id="@+id/headlines_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.android.fragments.ArticleFragment" android:id="@+id/article_fragment" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>
在运行时向 Activity 添加 Fragment
你可以在 Activity 运行时向其添加 Fragment, 而不用使用 <fragment>
元素在布局文件中为 Activity 定义 Fragment。
如果你打算在 Activity 运行周期内更改 Fragment,就必须这样做。
要执行添加或移除 Fragment 等事务,你必须使用 FragmentManager
创建一个 FragmentTransaction
,后者可提供用于执行添加、移除、替换以及其他 Fragment 事务的 API。
在处理 Fragment(特别是在运行时添加的 Fragment )时,请谨记以下重要规则:
必须在布局中为 Fragment 提供
View
容器(比如FrameLayout),以便保存 Fragment 的布局。
步骤:
1. 创建待添加的碎片实例。
2. 获取到 FragmentManager,在活动中可以直接调用 getFragmentManager()方法得到。
3. 开启一个事务,通过调用 beginTransaction()方法开启。
4. 向容器内加入碎片,一般使用 replace()方法实现,需要传入容器的 id 和待添加的碎
片实例。
5. 提交事务,调用 commit()方法来完成。
import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { &Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_articles); // 确认 Activity 使用的布局版本包含 // fragment_container FrameLayout if (findViewById(R.id.fragment_container) != null) { // 不过,如果我们要从先前的状态还原, // 则无需执行任何操作而应返回 // 否则就会得到重叠的 Fragment 。 if (savedInstanceState != null) { return; } // 创建 Fragment 并为其添加一个参数,用来指定应显示的文章 ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 将 fragment_container View 中的内容替换为此 Fragment , // 然后将该事务添加到返回堆栈,以便用户可以向后导航 transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // 执行事务 transaction.commit(); } } }
请注意,当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所做更改。要通过 Fragment 事务允许用户向后导航,你必须调用 addToBackStack()
,然后再执行 FragmentTransaction
。
Fragment 通信
Fragment 向 Activity 传递数据
方法一:
1、在 Fragment 类中声明一个接口,并定义一个接口
2、在 onAttach 中将定义的接口与传进来的 activity 进行绑定
3、在 Activity 中实现 Fragment 中定义的接口
在 Fragement 中需要传给 activity 时调用定义的接口函数,实现将 Fragment 数据传给Activity
定义接口
public class HeadlinesFragment extends ListFragment { OnHeadlineSelectedListener mCallback; // Container Activity must implement this interface public interface OnHeadlineSelectedListener { public void onArticleSelected(int position); } @Override public void onAttach(Context context) { super.onAttach(context); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mCallback = (OnHeadlineSelectedListener) context; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnHeadlineSelectedListener"); } } ... }
传递数据给activity
@Override public void onListItemClick(ListView l, View v, int position, long id) { // Send the event to the host activity mCallback.onArticleSelected(position); }
实现接口
public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article } }
方法二:
可以在 Fragment 中调用 getActivity() 获取 Activity 实例,从而调动 Activity 方法
MainActivity activity = (MainActivity) getActivity();
向 Fragment 传递数据
为了方便碎片和活动之间进行通信, FragmentManager 提供了一个类似于 findViewById() 的方法,专门用于从布局文件中获取碎片的实例
可以通过 FragmentManager 的 findFragmentById() 获取 Fragment 的实例
例如上个例子中当选择了一个 Fragment 中的 item 时,需要向另一个 Fragment 更新数据时,获取另一个 Fragment 的实例调用更新,如下:
public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article ArticleFragment articleFrag = (ArticleFragment) getSupportFragmentManager().findFragmentById(R.id.article_fragment); if (articleFrag != null) { // If article frag is available, we're in two-pane layout... // Call a method in the ArticleFragment to update its content articleFrag.updateArticleView(position); } else { // Otherwise, we're in the one-pane layout and must swap frags... // Create fragment and give it an argument for the selected article ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack so the user can navigate back transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit(); } } }
来源:https://www.cnblogs.com/z5130761/p/5997814.html