fragment 是一种模块 可以在android中创建动态的多版面的界面布局。 Fragment 类对象是activity中的一个模块 就像一个小型的activity,可以定义自己的布局亦可以管理自己的生命周期。
当fragment指定你的布局的时候,fragment 可以根据屏幕尺寸 联合其他的frament 在activity中设置不同的排列组合 ,例如:在大屏幕的时候可以显示多个fragment,而在小屏幕的时候只显示一个fragment.
fragment可以创建动态的界面模块,优化用户体验支持不同尺寸的设备。
创建一个静态的fragment
我们要创建一个fragment ,需要集成Fragment类,复写生命周期中的回调方法,这个有点类似于activity类。
不同点是要定义一个Fragment类必须要调用回调方法onCreateView()来定义布局。 如果你想让fragment运行起来,你只需要重写这个回调方法就可以了。
例1:
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.ViewGroup; public class FirstFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.first_view, container, false); } }
当然fragment也可以继承 , 其他的回调方法,来管理fragment的生命周期。 当fragment所在的activity在不同的生命周期状态之间转化的时候,内部的fragment也发生改变,当activity调用onstop()方法时fragment 也调用onstop()方法。
res/layout/first_view.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/first" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" android:textSize="18sp" />
添加一个fragment到activity中去
res/layout-large/news_activity.xml
<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.SecondFragment" 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.FirstFragment" android:id="@+id/article_fragment" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>注意:上述的xml的文件路径为res/layout-large/ 意思是只有在大屏幕的设备上才会这个布局。
应用布局到activity中去
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_activity); } }当你使用的是 v7appcompat library库的时候,你应该继承的类是
AppCompatActivity
。
以上是在Activity中静态的添加fragment,不能随时添加或者移除fragment.
在运行时向 Activity 添加 Fragment
利用FragmentManager
类提供的方法,你可以在运行时添加、移除和替换 Activity 中的 Fragment,以便为用户提供一种动态体验。
你可以在 Activity 运行时向其添加 Fragment,而不用像上一课中介绍的那样,使用 <fragment>
元素在布局文件中为 Activity 定义 Fragment。如果你打算在 Activity 运行周期内更改 Fragment,就必须这样做。
要执行添加或移除 Fragment 等事务,你必须使用 FragmentManager
创建一个 FragmentTransaction
,后者可提供用于执行添加、移除、替换以及其他 Fragment 事务的 API。
如果 Activity 中的 Fragment 可以移除和替换,你应在调用 Activity 的 onCreate()
方法期间为 Activity 添加初始 Fragment(s)。
在处理 Fragment(特别是在运行时添加的 Fragment )时,请谨记以下重要规则:必须在布局中为 Fragment 提供 View
容器,以便保存 Fragment 的布局。
下面是上一课所示布局的替代布局,这种布局一次只会显示一个 Fragment。要用一个 Fragment 替换另一个 Fragment, Activity 的布局中需要包含一个作为 Fragment 容器的空 FrameLayout
。
large
这一限定符。因此,此布局会在设备屏幕小于“large”的情况下使用,原因是尺寸较小的屏幕不适合同时显示两个 Fragment。
res/layout/news_acitivity.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />
在 Activity 内部,使用 Support Library API 调用 getSupportFragmentManager()
以获取 FragmentManager
,然后调用 beginTransaction()
创建 FragmentTransaction
,同时调用 add()
添加 Fragment。
你可以使用同一个 FragmentTransaction
对 Activity 执行多 Fragment 事务。当你准备好进行更改时,必须调用 commit()
。
例如,下面介绍了如何为上述布局添加 Fragment :
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_activity); // 确认 Activity 使用的布局版本包含 // fragment_container FrameLayout if (findViewById(R.id.fragment_container) != null) { // 不过,如果我们要从先前的状态还原, // 则无需执行任何操作而应返回 // 否则就会得到重叠的 Fragment 。 if (savedInstanceState != null) { return; } // 创建一个要放入 Activity 布局中的新 Fragment SecondFragment secondFragment = new SecondFragment(); // 如果此 Activity 是通过 Intent 发出的特殊指令来启动的, // 请将该 Intent 的 extras 以参数形式传递给该 Fragment secondFragment.setArguments(getIntent().getExtras()); // 将该 Fragment 添加到“fragment_container”FrameLayout 中 getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit(); } } }由于该 Fragment 已在运行时添加到
FrameLayout
容器中,而不是在 Activity 布局中通过
<fragment>
元素进行定义,因此该 Activity 可以移除和替换这个 Fragment 。
用一个 Fragment 替换另一个 Fragment
替换 Fragment 的步骤与添加 Fragment 的步骤相似,但需要调用 replace()
方法,而非 add()
。
请注意,当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所做更改。要通过 Fragment 事务允许用户向后导航,你必须调用 addToBackStack()
,然后再执行 FragmentTransaction
。
注意:当你移除或替换 Fragment 并向返回堆栈添加事务时,已移除的 Fragment 会停止(而不是销毁)。如果用户向后导航,还原该 Fragment,它会重新启动。如果你没有向返回堆栈添加事务,那么该 Fragment 在移除或替换时就会被销毁。
替换 Fragment 的示例:
// 创建 Fragment 并为其添加一个参数,用来指定应显示的文章
FirstFragment firstFragment = new FirstFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
firstFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// 将 fragment_container View
中的内容替换为此 Fragment ,
// 然后将该事务添加到返回堆栈,以便用户可以向后导航
transaction.replace(R.id.fragment_container, firstFragment);
transaction.addToBackStack(null);
// 执行事务
transaction.commit();
addToBackStack()
方法可接受可选的字符串参数,来为事务指定独一无二的名称。除非你打算使用
FragmentManager.BackStackEntry
API 执行高级 Fragment 操作,否则无需使用此名称。