Create a Fragment Class
- 如何创建一个Fragment
- 继承Fragment类并覆盖关键的生命周期方法,和操作activity差不多。
- 唯一的不同就是你需要在Fragment中使用onCreateView()方法去加载布局。
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;
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);
}
}
Add a Fragment to an Activity using XML
- 这里是一个将两个fragment添加到一个activity的例子
- 将布局添加到你的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_articles);
}
}
Note:
- 如果你使用的是v7 appcompat library,你的activity需要继承APPCompatActivity,它是FragmentActivity的一个子类。
- 当你的使用在layout XML File中定义Fragment这一方式添加fragment时,你不能在运行时移除fragment。如何你想在用户交互的时候替换fragment,你必须在activity第一次启动时添加fragment。
Buildinga Flexible UI
我们需要在的布局中使用重复的fragment,可根据屏幕尺寸的不同进行适配。比如在手机上可能只能显示一个fragment,而在平板电脑上需要并排显示两个fragment。
利用FragmentManager类提供的方法,你就可以在运行时添加、删除和替换Activity中的Fragment,为用户提供一种动态的体验。
Fragment added at runtime to Activity
- 如果你想添加或移除Fragment和其他事物,你必须使用FragmentManager创建一个FragmentTransaction,这是一个可以添加、删除和替换Fragment和其他事物的Fragemnt API。
- 在处理Fragment(特别是在运行时添加Fragment)时,请谨记以下重要规则:必须在布局中为 Fragment 提供 View 容器,以便保存 Fragment 的布局。
- 要用一个Fragment替换另一个Fragment,Activity的布局中需要包含一个作为Fragment容器的空FrameLayout。
- 在Activity内部,使用Support Library API调用getSupportFragmentManager()以获取FragmentManager,然后调用beginTransaction()创建FragmentTransaction,同时调用add()添加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_articles);
// 确认 Activity 使用的布局版本包含
// fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// 不过,如果我们要从先前的状态还原,
// 则无需执行任何操作而应返回
// 否则就会得到重叠的 Fragment 。
if (savedInstanceState != null) {
return;
}
// 创建一个要放入 Activity 布局中的新 Fragment
HeadlinesFragment firstFragment = new HeadlinesFragment();
// 如果此 Activity 是通过 Intent 发出的特殊指令来启动的,
// 请将该 Intent 的 extras 以参数形式传递给该 Fragment
firstFragment.setArguments(getIntent().getExtras());
// 将该 Fragment 添加到“fragment_container”FrameLayout 中
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}
用一个 Fragment 替换另一个 Fragment
- 替换Fragment的步骤和添加Fragment的步骤差不多,只不过add()换成replace()
- 当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所做更改。要通过 Fragment 事务允许用户向后导航,你必须调用 addToBackStack(),然后再执行 FragmentTransaction。
- 当你移除或替换 Fragment 并向返回堆栈添加事务时,已移除的 Fragment 会停止(而不是销毁)。如果用户向后导航,还原该 Fragment,它会重新启动。如果你没有向返回堆栈添加事务,那么该 Fragment 在移除或替换时就会被销毁。
// 创建 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();
Communication with Other Fragment
- Fragment无法直接与Fragment通信,但是可以通过Activity进行通信。
Define an Interface
为了让Fragment和Activity通信需要一下几步:
- 在Fragment中定义一个接口,并且在Activity中实现这个接口
- Fragment在onAttach()方法中捕获接口的实现
- 调用接口方法与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(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
现在Fragment通过调用onArticleSelected()方法(或者interface中其他的方法)就可以传递messages给activity了。
例如,以下Fragment中的方法当用户点击一个菜单项时被调用。fragment通过回调接口传递事件给父级activity。
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Send the event to the host activity
mCallback.onArticleSelected(position);
}
Implement the Interface
为了接收到来自fragment的事件,activity必须实现定义在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
}
}
Deliver a Message to a Fragment
activity可以通过findFragmentById获取Fragment实例,然后直接调用fragment的public方法。
举个例子,假如上述的例子中的activity包含另一个fragment用于显示item指定的回调方法中返回的数据。这样,activity可以将回调方法中收到的数据传递到其他的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();
}
}
}