用户界面 - Fragment

目录(?) [-]
  1. Fragment简介
    1. 创建Fragment
    2. Fragment生命周期
      1. Fragment特有的生命周期事件
    3. 获取FragmentManager
    4. 添加Fragment到Activity中
    5. 使用FragmentTransaction
    6. 添加删除和替换Fragment
    7. 获取指定的Fragment
    8. 删除Fragment容器
    9. Fragment和BackStack
    10. FragmentTransaction的动画效果
    11. Fragment和宿主Activity之间的接口
      1. 没有UI的Fragment
      2. 常用的Fragment类

参考《Professional Android 4 Development》

Fragment简介

Fragment是我们可以将Activity分成不同的组成部分,这些组成部分拥有自己的生命周期和UI。它的最大用途在于适配不同的屏幕。

创建Fragment

FragmentActivity有很多相似之处,例如可以不带UI,但这样做对两者似乎都没什么意义。他们的创建方式也很相似,例如下面的代码:

  1. package test.fragments;  
  2. import android.app.Fragment;  
  3. import android.os.Bundle;  
  4. import android.view.LayoutInflater;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7. public class MySkeletonFragment extends Fragment {  
  8. @Override  
  9. public View onCreateView(LayoutInflater inflater,  
  10.   ViewGroup container,  
  11.   Bundle savedInstanceState) {  
  12.   // Create, or inflate the Fragment’s UI, and return it.  
  13.   // If this Fragment has no UI then return null.  
  14.   return inflater.inflate(R.layout.my_fragment, container, false);  
  15.   }  
  16. }  
package test.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MySkeletonFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater,
  ViewGroup container,
  Bundle savedInstanceState) {
  // Create, or inflate the Fragment’s UI, and return it.
  // If this Fragment has no UI then return null.
  return inflater.inflate(R.layout.my_fragment, container, false);
  }
}

Fragment生命周期

Fragment的生命周期和它的宿主Activity密切相关,几乎和宿主Activity的生命周期一致,他们之间最大的不同在于Activity可以增加或删除Fragment。下图总结了Fragment的生命周期:


Fragment特有的生命周期事件

  1. Attach and detach Fragment from the parent Activity
  2. Creating and destroying Fragment
  3. Creating and Destroying UI

获取Fragment Manager

每个Activity对象都内置了一个FragmentManager对象,使用getFragmentManager()即可获得:

FragmentManager fragmentManager = getFragmentManager();

添加FragmentActivity

在Activity中添加Fragment的最简单方法是使用layout配置文件,例如:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:orientation="horizontal"  
  4.   android:layout_width="match_parent"  
  5.   android:layout_height="match_parent">  
  6.   <fragment android:name="com.paad.weatherstation.MyListFragment"  
  7.   android:id="@+id/my_list_fragment"  
  8.   android:layout_width="match_parent"  
  9.   android:layout_height="match_parent"  
  10.   android:layout_weight="1"  
  11.   />  
  12.   <fragment android:name="com.paad.weatherstation.DetailsFragment"  
  13.   android:id="@+id/details_fragment"  
  14.   android:layout_width="match_parent"  
  15.   android:layout_height="match_parent"  
  16.   android:layout_weight="3"  
  17.   />  
  18. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <fragment android:name="com.paad.weatherstation.MyListFragment"
  android:id="@+id/my_list_fragment"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="1"
  />
  <fragment android:name="com.paad.weatherstation.DetailsFragment"
  android:id="@+id/details_fragment"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="3"
  />
</LinearLayout>

调用inflate方法生成Fragment的界面后,Fragment实际上是一个类似ViewGroup的角色,在Activity中管理自己的UI。

上面那种将Fragment添加到Activity的方法缺乏灵活性,不能实现动态地添加和删除,更好的方式是使用FragmentTranaction和类似下面这样的配置文件:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:orientation="horizontal"  
  4.   android:layout_width="match_parent"  
  5.   android:layout_height="match_parent">  
  6.   <FrameLayout  
  7.   android:id="@+id/ui_container"  
  8.   android:layout_width="match_parent"  
  9.   android:layout_height="match_parent"  
  10.   android:layout_weight="1"  
  11.   />  
  12.   <FrameLayout  
  13.   android:id="@+id/details_container"  
  14.   android:layout_width="match_parent"  
  15.   android:layout_height="match_parent"  
  16.   android:layout_weight="3"  
  17.   />  
  18. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <FrameLayout
  android:id="@+id/ui_container"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="1"
  />
  <FrameLayout
  android:id="@+id/details_container"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="3"
  />
</LinearLayout>

使用FragmentTransaction

FragmentTransaction可以在运行时添加,删除或替换Fragment,从而实现UI的动态变化。Fragment TransactionFragment ManagerbeginTransaction()方法创建,然后可以进行Fragment的添加,删除和替换,最后通过commit()方法提交修改。

  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2. // Add, remove, and/or replace Fragments.   
  3. // Specify animations.   
  4. // Add to back stack if required.   
  5. fragmentTransaction.commit();  
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Add, remove, and/or replace Fragments.
// Specify animations.
// Add to back stack if required.
fragmentTransaction.commit();

添加,删除和替换Fragment

使用FragmentTransactionadd方法可以添加一个新的Fragmentadd()方法的主要参数是Fragment的容器View(或其ID)及Fragment实例,例如:

  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2. fragmentTransaction.add(R.id.ui_container, new MyListFragment());  
  3. fragmentTransaction.commit();  
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.ui_container, new MyListFragment());
fragmentTransaction.commit();

删除Fragment需要FragmentTransaction的remove()方法,参数为Fragment对象,Fragment对象可以通过FragmentManager的findFragmentById()方法获得。

  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2. Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);  
  3. fragmentTransaction.remove(fragment);  
  4. fragmentTransaction.commit();  
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();

替换Fragment使用的是FragmentTransaction的replace()方法,参数分别为所要替代Fragment所在容器的ID和新的Fragment:

  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2. fragmentTransaction.replace(R.id.details_fragment, new DetailFragment(selected_index));  
  3. fragmentTransaction.commit();  
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.details_fragment, new DetailFragment(selected_index));
fragmentTransaction.commit();

获取指定的Fragment

有两种方法可以获取某个特定的Fragment,如果这个Fragment已经被添加到某个layout文件中,则可以使用xml文件中的id作为参数:

  1. MyFragment myFragment = (MyFragment)fragmentManager.findFragmentById(R.id.MyFragment);  
MyFragment myFragment = (MyFragment)fragmentManager.findFragmentById(R.id.MyFragment);

也可以通过创建Fragment时添加的tag获取特定的Fragment:

  1. MyFragment myFragment = (MyFragment)fragmentManager.findFragmentByTag(MY_FRAGMENT_TAG);  
MyFragment myFragment = (MyFragment)fragmentManager.findFragmentByTag(MY_FRAGMENT_TAG);

删除Fragment容器

在配置文件中将visibility的属性设为"gone",即可删除某个Fragment,例如:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:orientation="horizontal"  
  4.   android:layout_width="match_parent"  
  5.   android:layout_height="match_parent">  
  6.   <FrameLayout  
  7.   android:id="@+id/ui_container"  
  8.   android:layout_width="match_parent"  
  9.   android:layout_height="match_parent"  
  10.   android:layout_weight="1"  
  11.   />  
  12.   <FrameLayout  
  13.   android:id="@+id/details_container"  
  14.   android:layout_width="match_parent"  
  15.   android:layout_height="match_parent"  
  16.   android:layout_weight="3"  
  17.   android:visibility="gone"  
  18.   />  
  19. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <FrameLayout
  android:id="@+id/ui_container"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="1"
  />
  <FrameLayout
  android:id="@+id/details_container"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="3"
  android:visibility="gone"
  />
</LinearLayout>

FragmentBack Stack

Activity拥有Activity Stack,从而在用户按”返回”按钮时,回到前一个ActivityFragment也可以响应”返回”事件,方法是FragmentTransactioncommit之前调用addToBackStack()方法。这样,在用户按返回键后,Android会首先重现之前的UI布局。

  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2. fragmentTransaction.add(R.id.ui_container, new MyListFragment());  
  3. Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);  
  4. fragmentTransaction.remove(fragment);  
  5. String tag = null;  
  6. fragmentTransaction.addToBackStack(tag);  
  7. fragmentTransaction.commit();  
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.ui_container, new MyListFragment());
Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);
fragmentTransaction.remove(fragment);
String tag = null;
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commit();

原理和Activity类似,调用addToBackStack()后,Fragment会被push到back stack中,而不是销毁。

Fragment Transaction的动画效果

Fragment Transaction有两种方法实现动画效果,分别是:

  • 设置渐进
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

  • 设置动画效果
  1. fragmentTransaction.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right);  
fragmentTransaction.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right);

Fragment和宿主Activity之间的接口

Fragment可以通过getActivity()方法获得宿主Activity对象:

  1. TextView textView = (TextView)getActivity().findViewById(R.id.textview);  
TextView textView = (TextView)getActivity().findViewById(R.id.textview);

另一种常见的FragmentActivity之间的交互方式是使用回调函数:

  1. <SPAN style="FONT-SIZE: 12px">public interface OnSeasonSelectedListener {  
  2.   public void onSeasonSelected(Season season);  
  3. }  
  4. private OnSeasonSelectedListener onSeasonSelectedListener;  
  5.   private Season currentSeason;  
  6.   @Override  
  7.   public void onAttach(Activity activity) {  
  8.   super.onAttach(activity);  
  9.   try {  
  10.   onSeasonSelectedListener = (OnSeasonSelectedListener)activity;  
  11.   } catch (ClassCastException e) {  
  12.   throw new ClassCastException(activity.toString() +"must implement OnSeasonSelectedListener");  
  13.   }  
  14.   }  
  15.   private void setSeason(Season season) {  
  16.   currentSeason = season;  
  17.   onSeasonSelectedListener.onSeasonSelected(season);  
  18. }</SPAN>  
<span style="font-size:12px;">public interface OnSeasonSelectedListener {
  public void onSeasonSelected(Season season);
}
private OnSeasonSelectedListener onSeasonSelectedListener;
  private Season currentSeason;
  @Override
  public void onAttach(Activity activity) {
  super.onAttach(activity);
  try {
  onSeasonSelectedListener = (OnSeasonSelectedListener)activity;
  } catch (ClassCastException e) {
  throw new ClassCastException(activity.toString() +"must implement OnSeasonSelectedListener");
  }
  }
  private void setSeason(Season season) {
  currentSeason = season;
  onSeasonSelectedListener.onSeasonSelected(season);
}</span>

没有UI的Fragment

尽管不常见,但Fragment的确是可以没有UI的,好处也许是拥有了更灵活的生命周期控制。没有UI的Fragment生命周期事件有这些:
  1. public class NewItemFragment extends Fragment {  
  2.   @Override  
  3.   public void onAttach(Activity activity) {  
  4.   <SPAN style="WHITE-SPACE: pre">   </SPAN>super.onAttach(activity);  
  5.  <SPAN style="WHITE-SPACE: pre">    </SPAN>// Get a type-safe reference to the parent Activity.   
  6.   }  
  7.   @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9. <SPAN style="WHITE-SPACE: pre"> </SPAN>  super.onCreate(savedInstanceState);  
  10. <SPAN style="WHITE-SPACE: pre"> </SPAN>  // Create background worker threads and tasks.   
  11.   }  
  12.   @Override  
  13.   public void onActivityCreated(Bundle savedInstanceState) {  
  14. <SPAN style="WHITE-SPACE: pre"> </SPAN>  super.onActivityCreated(savedInstanceState);  
  15. <SPAN style="WHITE-SPACE: pre"> </SPAN>  // Initiate worker threads and tasks.   
  16.   }  
  17. }  
public class NewItemFragment extends Fragment {
  @Override
  public void onAttach(Activity activity) {
  <span style="WHITE-SPACE: pre">	</span>super.onAttach(activity);
 <span style="WHITE-SPACE: pre">	</span>// Get a type-safe reference to the parent Activity.
  }
  @Override
    public void onCreate(Bundle savedInstanceState) {
<span style="WHITE-SPACE: pre">	</span>  super.onCreate(savedInstanceState);
<span style="WHITE-SPACE: pre">	</span>  // Create background worker threads and tasks.
  }
  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
<span style="WHITE-SPACE: pre">	</span>  super.onActivityCreated(savedInstanceState);
<span style="WHITE-SPACE: pre">	</span>  // Initiate worker threads and tasks.
  }
}

常用的Fragment类

  • DiagFragment
  • ListFragment
  • webViewFragment
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值