Android Fragment简记
Fragment一般可以理解成Activity的一部分(视图,UI)。
定义Fragment
一个Fragment包含两部分,View和Java类。
View可以是XML布局,也可以是纯Java代码的View。
Java类需要继承自Fragment类。在support library v4中的Fragment类可最低支持Android 2.1(API-7)。
在Activity中加入Fragment
首先Activity要支持Fragment:如果使用的是support library中的Fragment,那么Activity也需要继承自support library中的FragmentActivity。
添加的方式有两种——静态的和动态的。
静态
直接在Activity的XML布局文件中加入Fragment。
class属性指定Java类。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<fragment
android:id="@+id/fooFragment"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
class="com.example.android.FooFragment" ></fragment>
</LinearLayout>
动态
使用FragmentManager。
但首先也需要在Activity的布局中有一个place holder给Fragment提供位置。
// Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace the container with the new fragment
ft.replace(R.id.your_placeholder, new FooFragment());
// or ft.add(R.id.your_placeholder, new FooFragment());
// Execute the changes specified
ft.commit();
生命周期
-
onAttach()
Fragment attach到Activity时调用 -
onCreate()
对Fragment做初始化 -
onCreateView()
当Fragment需要创建View时调用 -
onActivityCreated()
当宿主Activity完成了onCreate()
方法时被调用 -
onDestroyView()
当Fragment开始被销毁时调用 -
onStart()
当Fragment可见时调用 -
onResume()
- 获取一些昂贵的资源,如位置、传感器等 -
onPause()
- 释放昂贵资源,提交更改
与Fragment的交互
Fragment不应该相互间直接通信,而应通过Activity来进行。有三个方法可以在Fragment和Activity之间进行通信。
带参数的Fragment
在某些情况下,Fragment可能需要特定的参数。(用来初始化Fragment。)
一个常用模式是使用newInstance()
来创建带参数的Fragment。(这样做的原因是Fragment只能有一个无参的构造方法。)
public class DemoFragment extends Fragment {
// Creates a new fragment given an int and title
// DemoFragment.newInstance(5, "Hello");
public static DemoFragment newInstance(int someInt, String someTitle) {
DemoFragment fragmentDemo = new DemoFragment();
Bundle args = new Bundle();
args.putInt("someInt", someInt);
args.putString("someTitle", someTitle);
fragmentDemo.setArguments(args);
return fragmentDemo;
}
}
public class DemoFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get back arguments
int SomeInt = getArguments().getInt("someInt", 0);
String someTitle = getArguments().getString("someTitle", "");
}
}
Activity调用Fragment方法
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DemoFragment fragmentDemo = (DemoFragment)
getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
fragmentDemo.doSomething("some param");
}
}
在Fragment中的Listener
如果Fragment需要共享事件给Activity,则需要利用这种方法。
Fragment中定义一个接口,并且由Activity来实现这个接口。在onAttach()
方法中将实现了这个接口的Activity获取到。
public class MyListFragment extends Fragment {
// ...
// Define the listener of the interface type
// listener is the activity itself
private OnItemSelectedListener listener;
// Define the events that the fragment will use to communicate
public interface OnItemSelectedListener {
public void onRssItemSelected(String link);
}
// Store the listener (activity) that will have events fired once the fragment is attached
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnItemSelectedListener) {
listener = (OnItemSelectedListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
// Now we can fire the event when the user selects something in the fragment
public void onSomeClick(View v) {
listener.onRssItemSelected("some link");
}
}
public class RssfeedActivity extends FragmentActivity implements
MyListFragment.OnItemSelectedListener {
DetailFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rssfeed);
fragment = (DetailFragment) getSupportFragmentManager()
.findFragmentById(R.id.detailFragment);
}
// Now we can define the action to take in the activity when the fragment event fires
@Override
public void onRssItemSelected(String link) {
if (fragment != null && fragment.isInLayout()) {
fragment.setText(link);
}
}
}
Fragment与ActionBar菜单项
如果Fragment中有相关联的ActionBar菜单项,可以在Fragment中通过onCreateOptionsMenu()
方法来进行设置,就与Activity中一致。
需要注意的是,只有事件没有在Activity中被处理掉时,Fragment中的事件回调才会被调用。
但你需要设置该Fragment中有菜单项。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
创建菜单:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
}
响应:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// handle item selection
switch (item.getItemId()) {
case R.id.edit_item:
// do s.th.
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Fragment间的导航
可用:
- ActionBar Tabs
- Fragment Navigation Drawer
- ViewPager
管理Fragment的回退栈
如果需要用后退键来回退Fragment,则在FragmentTransaction中调用addToBackstack()
即可。
// Create the transaction
FragmentTransaction fts = getSupportFragmentManager().beginTransaction();
// Replace the content of the container
fts.replace(R.id.flContainer, new FirstFragment());
// Append this transaction to the backstack
fts.addToBackStack("optional tag");
// Commit the changes
fts.commit();
也可进行弹出:
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
}