Android Fragment 完全解析

时间:2023-03-09 22:54:27
Android Fragment 完全解析

参考文章:http://blog.csdn.net/guolin_blog/article/details/8881711
http://blog.csdn.net/guolin_blog/article/details/13171191
Android Fragment应用实战,使用碎片向ActivityGroup说再见

界面如下:

Android Fragment 完全解析

实现步骤:

程序结构:

Android Fragment 完全解析

  1. 编写主界面的xml文件
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
    3.     android:orientation="vertical"
    4.     android:layout_width="fill_parent"
    5.     android:layout_height="fill_parent">
    6.     <FrameLayout
    7.         android:layout_width="match_parent"
    8.         android:layout_height="0dp"
    9.         android:layout_weight="1"
    10.         android:id="@+id/content">
    11.     </FrameLayout>
    12.         <LinearLayout
    13.             android:layout_width="match_parent"
    14.             android:layout_height="60dp"
    15.             android:background="@drawable/tab_bg">
    16.             <RelativeLayout
    17.                 android:layout_width="0dp"
    18.                 android:layout_height="match_parent"
    19.                 android:layout_weight="1"
    20.                 android:id="@+id/message_layout">
    21.                 <LinearLayout
    22.                     android:layout_width="match_parent"
    23.                     android:layout_height="wrap_content"
    24.                     android:layout_centerVertical="true"
    25.                     android:orientation="vertical">
    26.                     <ImageView
    27.                         android:layout_width="wrap_content"
    28.                         android:layout_height="wrap_content"
    29.                         android:layout_gravity="center_horizontal"
    30.                         android:src="@drawable/message_unselected"
    31.                         android:id="@+id/message_image"/>
    32.                     <TextView
    33.                         android:layout_width="wrap_content"
    34.                         android:layout_height="wrap_content"
    35.                         android:layout_gravity="center_horizontal"
    36.                         android:text="消息"
    37.                         android:id="@+id/message_text"
    38.                         android:textColor="#82858b"/>
    39.                 </LinearLayout>
    40.             </RelativeLayout>
    41.             <RelativeLayout
    42.                 android:layout_width="0dp"
    43.                 android:layout_height="match_parent"
    44.                 android:layout_weight="1"
    45.                 android:id="@+id/contacts_layout">
    46.                 <LinearLayout
    47.                     android:layout_width="match_parent"
    48.                     android:layout_height="wrap_content"
    49.                     android:layout_centerVertical="true"
    50.                     android:orientation="vertical">
    51.                     <ImageView
    52.                         android:layout_width="wrap_content"
    53.                         android:layout_height="wrap_content"
    54.                         android:layout_gravity="center_horizontal"
    55.                         android:src="@drawable/contacts_unselected"
    56.                         android:id="@+id/contacts_image"/>
    57.                     <TextView
    58.                         android:layout_width="wrap_content"
    59.                         android:layout_height="wrap_content"
    60.                         android:layout_gravity="center_horizontal"
    61.                         android:text="联系人"
    62.                         android:id="@+id/contacts_text"
    63.                         android:textColor="#82858b"/>
    64.                 </LinearLayout>
    65.             </RelativeLayout>
    66.             <RelativeLayout
    67.                 android:layout_width="0dp"
    68.                 android:layout_height="match_parent"
    69.                 android:layout_weight="1"
    70.                 android:id="@+id/news_layout">
    71.                 <LinearLayout
    72.                     android:layout_width="match_parent"
    73.                     android:layout_height="wrap_content"
    74.                     android:layout_centerVertical="true"
    75.                     android:orientation="vertical">
    76.                     <ImageView
    77.                         android:layout_width="wrap_content"
    78.                         android:layout_height="wrap_content"
    79.                         android:layout_gravity="center_horizontal"
    80.                         android:src="@drawable/news_unselected"
    81.                         android:id="@+id/news_image"/>
    82.                     <TextView
    83.                         android:layout_width="wrap_content"
    84.                         android:layout_height="wrap_content"
    85.                         android:layout_gravity="center_horizontal"
    86.                         android:text="动态"
    87.                         android:id="@+id/news_text"
    88.                         android:textColor="#82858b"/>
    89.                 </LinearLayout>
    90.             </RelativeLayout>
    91.             <RelativeLayout
    92.                 android:layout_width="0dp"
    93.                 android:layout_height="match_parent"
    94.                 android:layout_weight="1"
    95.                 android:id="@+id/setting_layout">
    96.                 <LinearLayout
    97.                     android:layout_width="match_parent"
    98.                     android:layout_height="wrap_content"
    99.                     android:layout_centerVertical="true"
    100.                     android:orientation="vertical">
    101.                     <ImageView
    102.                         android:layout_width="wrap_content"
    103.                         android:layout_height="wrap_content"
    104.                         android:layout_gravity="center_horizontal"
    105.                         android:src="@drawable/setting_unselected"
    106.                         android:id="@+id/setting_image"/>
    107.                     <TextView
    108.                         android:layout_width="wrap_content"
    109.                         android:layout_height="wrap_content"
    110.                         android:layout_gravity="center_horizontal"
    111.                         android:text="设置"
    112.                         android:id="@+id/setting_text"
    113.                         android:textColor="#82858b"/>
    114.                 </LinearLayout>
    115.             </RelativeLayout>
    116.         </LinearLayout>
    117. </LinearLayout>

    效果图如下:

    Android Fragment 完全解析

    这里面最上方是一个frameLayout,下面是一个大的LinearLayout套了四个RelativeLayout,每个RelativeLayout 里面有套了一个LinearLayout,然后此线性布局下面放了一个imageview和Textview。

    其中,四个相对布局都是用的weight权重来实现的。

     

  2. 分别编写每个fragment的xml。
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
    3.     android:layout_height="match_parent">
    4.     <LinearLayout
    5.         android:layout_width="wrap_content"
    6.         android:layout_height="wrap_content"
    7.         android:orientation="vertical"
    8.         android:layout_centerInParent="true">
    9.         <ImageView
    10.             android:layout_width="wrap_content"
    11.             android:layout_height="wrap_content"
    12.             android:layout_gravity="center_horizontal"
    13.             android:src="@drawable/message_selected"/>
    14.         <TextView
    15.             android:layout_width="wrap_content"
    16.             android:layout_height="wrap_content"
    17.             android:layout_gravity="center_horizontal"
    18.             android:padding="10dp"
    19.             android:text="这是消息界面"
    20.             android:textSize="20sp"/>
    21.     </LinearLayout>
    22. </RelativeLayout>

    Android Fragment 完全解析

    只举一个实例,其他一样。

  3. 为每个xml 定义各自的Fragment
    1. package com.example.FragmentDemo;
    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. /**
    8.  * Created by zhuxuekui on 2015/5/18.
    9.  */
    10. public
      class MessageFragment extends Fragment {
    11.     @Override
    12.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    13.         View messageLayout = inflater.inflate(R.layout.message_layout,container,false);
    14.         return messageLayout;
    15.     }
    16. }
  4. 编写业务逻辑层
    1. /**
    2.  * 项目的主Activity,所有的Fragment都嵌入在这里。
    3.  *
    4.  * @author guolin
    5.  */
    6. public
      class MainActivity extends Activity implements OnClickListener {
    7.    /**
    8.     * 用于展示消息的Fragment
    9.     */
    10.    private MessageFragment messageFragment;
    11.    /**
    12.     * 用于展示联系人的Fragment
    13.     */
    14.    private ContactsFragment contactsFragment;
    15.    /**
    16.     * 用于展示动态的Fragment
    17.     */
    18.    private NewsFragment newsFragment;
    19.    /**
    20.     * 用于展示设置的Fragment
    21.     */
    22.    private SettingFragment settingFragment;
    23.    /**
    24.     * 消息界面布局
    25.     */
    26.    private View messageLayout;
    27.    /**
    28.     * 联系人界面布局
    29.     */
    30.    private View contactsLayout;
    31.    /**
    32.     * 动态界面布局
    33.     */
    34.    private View newsLayout;
    35.    /**
    36.     * 设置界面布局
    37.     */
    38.    private View settingLayout;
    39.    /**
    40.     * 在Tab布局上显示消息图标的控件
    41.     */
    42.    private ImageView messageImage;
    43.    /**
    44.     * 在Tab布局上显示联系人图标的控件
    45.     */
    46.    private ImageView contactsImage;
    47.    /**
    48.     * 在Tab布局上显示动态图标的控件
    49.     */
    50.    private ImageView newsImage;
    51.    /**
    52.     * 在Tab布局上显示设置图标的控件
    53.     */
    54.    private ImageView settingImage;
    55.    /**
    56.     * 在Tab布局上显示消息标题的控件
    57.     */
    58.    private TextView messageText;
    59.    /**
    60.     * 在Tab布局上显示联系人标题的控件
    61.     */
    62.    private TextView contactsText;
    63.    /**
    64.     * 在Tab布局上显示动态标题的控件
    65.     */
    66.    private TextView newsText;
    67.    /**
    68.     * 在Tab布局上显示设置标题的控件
    69.     */
    70.    private TextView settingText;
    71.    /**
    72.     * 用于对Fragment进行管理
    73.     */
    74.    private FragmentManager fragmentManager;
    75.    @Override
    76.    protected
      void onCreate(Bundle savedInstanceState) {
    77.       super.onCreate(savedInstanceState);
    78.       requestWindowFeature(Window.FEATURE_NO_TITLE);
    79.       setContentView(R.layout.activity_main);
    80.       // 初始化布局元素
    81.       initViews();
    82.       fragmentManager = getFragmentManager();
    83.       // 第一次启动时选中第0个tab
    84.       setTabSelection(0);
    85.    }
    86.    /**
    87.     * 在这里获取到每个需要用到的控件的实例,并给它们设置好必要的点击事件。
    88.     */
    89.    private
      void initViews() {
    90.       messageLayout = findViewById(R.id.message_layout);
    91.       contactsLayout = findViewById(R.id.contacts_layout);
    92.       newsLayout = findViewById(R.id.news_layout);
    93.       settingLayout = findViewById(R.id.setting_layout);
    94.       messageImage = (ImageView) findViewById(R.id.message_image);
    95.       contactsImage = (ImageView) findViewById(R.id.contacts_image);
    96.       newsImage = (ImageView) findViewById(R.id.news_image);
    97.       settingImage = (ImageView) findViewById(R.id.setting_image);
    98.       messageText = (TextView) findViewById(R.id.message_text);
    99.       contactsText = (TextView) findViewById(R.id.contacts_text);
    100.       newsText = (TextView) findViewById(R.id.news_text);
    101.       settingText = (TextView) findViewById(R.id.setting_text);
    102.       messageLayout.setOnClickListener(this);
    103.       contactsLayout.setOnClickListener(this);
    104.       newsLayout.setOnClickListener(this);
    105.       settingLayout.setOnClickListener(this);
    106.    }
    107.    @Override
    108.    public
      void onClick(View v) {
    109.       switch (v.getId()) {
    110.       case R.id.message_layout:
    111.          // 当点击了消息tab时,选中第1个tab
    112.          setTabSelection(0);
    113.          break;
    114.       case R.id.contacts_layout:
    115.          // 当点击了联系人tab时,选中第2个tab
    116.          setTabSelection(1);
    117.          break;
    118.       case R.id.news_layout:
    119.          // 当点击了动态tab时,选中第3个tab
    120.          setTabSelection(2);
    121.          break;
    122.       case R.id.setting_layout:
    123.          // 当点击了设置tab时,选中第4个tab
    124.          setTabSelection(3);
    125.          break;
    126.       default:
    127.          break;
    128.       }
    129.    }
    130.    /**
    131.     * 根据传入的index参数来设置选中的tab页。
    132.     *
    133.     * @param index
    134.     * 每个tab页对应的下标。0表示消息,1表示联系人,2表示动态,3表示设置。
    135.     */
    136.    private
      void setTabSelection(int index) {
    137.       // 每次选中之前先清楚掉上次的选中状态
    138.       clearSelection();
    139.       // 开启一个Fragment事务
    140.       FragmentTransaction transaction = fragmentManager.beginTransaction();
    141.       // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况
    142.       hideFragments(transaction);
    143.       switch (index) {
    144.       case 0:
    145.          // 当点击了消息tab时,改变控件的图片和文字颜色
    146.          messageImage.setImageResource(R.drawable.message_selected);
    147.          messageText.setTextColor(Color.WHITE);
    148.          if (messageFragment == null) {
    149.             // 如果MessageFragment为空,则创建一个并添加到界面上
    150.             messageFragment = new MessageFragment();
    151.             transaction.add(R.id.content, messageFragment);
    152.          } else {
    153.             // 如果MessageFragment不为空,则直接将它显示出来
    154.             transaction.show(messageFragment);
    155.          }
    156.          break;
    157.       case 1:
    158.          // 当点击了联系人tab时,改变控件的图片和文字颜色
    159.          contactsImage.setImageResource(R.drawable.contacts_selected);
    160.          contactsText.setTextColor(Color.WHITE);
    161.          if (contactsFragment == null) {
    162.             // 如果ContactsFragment为空,则创建一个并添加到界面上
    163.             contactsFragment = new ContactsFragment();
    164.             transaction.add(R.id.content, contactsFragment);
    165.          } else {
    166.             // 如果ContactsFragment不为空,则直接将它显示出来
    167.             transaction.show(contactsFragment);
    168.          }
    169.          break;
    170.       case 2:
    171.          // 当点击了动态tab时,改变控件的图片和文字颜色
    172.          newsImage.setImageResource(R.drawable.news_selected);
    173.          newsText.setTextColor(Color.WHITE);
    174.          if (newsFragment == null) {
    175.             // 如果NewsFragment为空,则创建一个并添加到界面上
    176.             newsFragment = new NewsFragment();
    177.             transaction.add(R.id.content, newsFragment);
    178.          } else {
    179.             // 如果NewsFragment不为空,则直接将它显示出来
    180.             transaction.show(newsFragment);
    181.          }
    182.          break;
    183.       case 3:
    184.       default:
    185.          // 当点击了设置tab时,改变控件的图片和文字颜色
    186.          settingImage.setImageResource(R.drawable.setting_selected);
    187.          settingText.setTextColor(Color.WHITE);
    188.          if (settingFragment == null) {
    189.             // 如果SettingFragment为空,则创建一个并添加到界面上
    190.             settingFragment = new SettingFragment();
    191.             transaction.add(R.id.content, settingFragment);
    192.          } else {
    193.             // 如果SettingFragment不为空,则直接将它显示出来
    194.             transaction.show(settingFragment);
    195.          }
    196.          break;
    197.       }
    198.       transaction.commit();
    199.    }
    200.    /**
    201.     * 清除掉所有的选中状态。
    202.     */
    203.    private
      void clearSelection() {
    204.       messageImage.setImageResource(R.drawable.message_unselected);
    205.       messageText.setTextColor(Color.parseColor("#82858b"));
    206.       contactsImage.setImageResource(R.drawable.contacts_unselected);
    207.       contactsText.setTextColor(Color.parseColor("#82858b"));
    208.       newsImage.setImageResource(R.drawable.news_unselected);
    209.       newsText.setTextColor(Color.parseColor("#82858b"));
    210.       settingImage.setImageResource(R.drawable.setting_unselected);
    211.       settingText.setTextColor(Color.parseColor("#82858b"));
    212.    }
    213.    /**
    214.     * 将所有的Fragment都置为隐藏状态。
    215.     *
    216.     * @param transaction
    217.     * 用于对Fragment执行操作的事务
    218.     */
    219.    private
      void hideFragments(FragmentTransaction transaction) {
    220.       if (messageFragment != null) {
    221.          transaction.hide(messageFragment);
    222.       }
    223.       if (contactsFragment != null) {
    224.          transaction.hide(contactsFragment);
    225.       }
    226.       if (newsFragment != null) {
    227.          transaction.hide(newsFragment);
    228.       }
    229.       if (settingFragment != null) {
    230.          transaction.hide(settingFragment);
    231.       }
    232.    }
    233. }

首先在oncreate方法里面initview() 初始化各个控件,然后为每个layout 设置监听事件(相对布局的layout),当我们点击到某个layout时候,执行SetTabSelection(index)方法。

在刚刚的方法里面,我们首先执行clearSelection,将所有的imageview都设置为不选中状态,然后并隐藏hideFragment,这里我们用FragmentManager里面的FragmentTransaction来实现的。

这两个方法执行完之后,我们进入到switch条件语句,改变某个选中的图标的图片以及文字,这里面我们显示的是Fragment,没有用replace而是用的add,show,hide方法来实现。这样程序执行的效率会高一点,不然,用replace的话,被替换掉的fragment会彻底的被干掉,即声明周期结束,当我们又一次选中的时候,还要重新加载,这样变得麻烦。