【攻克Android (15)】Fragment 碎片 / 帧 / 片段

本文围绕以下三个部分展开:

一、Fragment 碎片 / 帧 / 片段
二、两个案例
    (一)、静态 Fragment
    附   代码补充
    (二)、动态 Fragment
    附   代码补充




一、Fragment 碎片 / 帧 / 片段

        1.Fragment 碎片 / 帧 / 片段

        从 android 3.0 加入 Fragment 的概念,目的是在不同类型屏幕下实现 UI 的动态和灵活设计。

        由于 Fragment 有独立的生命周期及可用复用,所以在设计复杂 UI 时(Tab 导航、 ViewPager 及 抽屉导航)应用极为广泛。



        创建 Activity 的时候,需要完成三步:1.XxxActivity ; 2. activity_Xxx.xml ; 3.在功能清单中注册。最后,在 Activity 之间还要实现跳转。
        Fragment 是轻量级的 Activity ,不需要在功能清单中注册。

        2.Fragment 生命周期





        3.Fragment 相关类

        (1)android.app.Fragment

        (2)android.app.FragmentManager

            Fragment 管理器,用于管理与当前活动关联的 Fragment .

        (3)android.app.FragmentTransaction

            Fragment 事务,开始一系列的 Fragment 操作。




二、两个案例

    案例(一)、静态 Fragment



    打开App后,默认主界面如下:



    当左边点击“Android”的时候,右边碎片正中间出现“Android”:



    同样,当点击其他项的时候,右边碎片正中间出现对应的内容:



    (1)创建 碎片 : LeftFragment & fragment_left.xml , RightFragment & fragment_right.xml 。





    (2)写两个碎片的内容。

    fragment_left.xml:一个ListView。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context="com.xiangdong.staticfragment.LeftFragment">

  <ListView
      android:id="@+id/listView"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"/>

</FrameLayout>


    fragment_right.xml:一个TextView。默认界面是在正中间显示本app的名字:“StaticFragment”。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:background="@android:color/holo_blue_light"
             tools:context="com.xiangdong.staticfragment.RightFragment">

  <!-- TODO: Update blank fragment layout -->
  <TextView
      android:id="@+id/tvContent"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_centerVertical="true"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:text="@string/app_name"
      android:textColor="@android:color/white"/>

</RelativeLayout>

<!--
  代码说明:
    (1)因为这两个碎片都会被调用,因此都要写 id。
    (2)android:background="@android:color/holo_blue_light"
         设置背景色为:浅蓝色。
    (3)android:textAppearance="?android:attr/textAppearanceLarge"
         一种大字体的格式。
-->


    (3)写主布局文件:activity_main.xml。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:paddingBottom="@dimen/activity_vertical_margin"
              tools:context=".MainActivity">

  <!--
  主界面上,显示两个 碎片(帧/片段) 界面
  -->
  <fragment
      android:id="@+id/leftFragment"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:name="com.xiangdong.staticfragment.LeftFragment"
      tools:layout="@layout/fragment_left"/>

  <fragment
      android:id="@+id/rightFragment"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:name="com.xiangdong.staticfragment.RightFragment"
      tools:layout="@layout/fragment_right"/>

</LinearLayout>

<!--
  代码说明:
    (1)主布局文件上,左右各放一个碎片,因此用 LinearLayout,方向需设为 水平。
        android:orientation="horizontal"
    (2)android:name="com.xiangdong.staticfragment.LeftFragment"
        主布局文件 与 LeftFragment 关联。
      tools:layout="@layout/fragment_left"
        主布局文件 与 fragment_left 关联。
-->


    (4)主活动:MainActivity 。创建的时候,就会有以下代码:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //  加载主布局文件,就会加载两个碎片界面。(在配置文件中,布局文件与Activity关联了)
        setContentView(R.layout.activity_main);
    }


    (5)LeftFragment。调用 onAttach() 方法:在 Fragment 与 Activity 关联时。

/**
     * Fragment 与 Activity 关联时调用
     * @param activity
     */
    @Override
    public void onAttach(Activity activity) {
        // 2. 关联时,会调用这个方法
        super.onAttach(activity);
        // 获得活动的引用
        if(activity instanceof OnFragmentListener){
            // 2.1 活动实现了监听器,即可回调活动中的方法
            callback = (OnFragmentListener) activity;
        }
    }

    //-----Fragment 与 Activity 传递参数------------------------------------
    private OnFragmentListener callback;
}


    代码说明:

    主活动要实现此碎片中定义的内部接口:

public class MainActivity extends Activity implements LeftFragment.OnFragmentListener{}


    (6)LeftFragment。调用 onCreate() 方法:创建 Fragment 时调用,主要用来初始化数据(准备好要用的数据)。

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        data = new ArrayList<>();
        data.add("Android");
        data.add("IOS");
        data.add("Web");
        data.add("C");
        data.add("C#");
        data.add("C++");
    }


    (7)LeftFragment。调用 onCreateView() 方法:画界面。

    // 加载 Fragment 视图 (界面出来了)
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment 填充指定布局文件
        View view = inflater.inflate(R.layout.fragment_left, container, false);
        adapter = new ArrayAdapter<String>(this.getActivity(),
                android.R.layout.simple_list_item_1, data);
        listView = (ListView) view.findViewById(R.id.listView);
        listView.setAdapter(adapter);
        // 注册监听事件:设置当前(我自己)即可。
        listView.setOnItemClickListener(this);
        return view;
    }


    代码说明:

        simple_list_item_1 :有一个控件。一次只显示一行。
        simple_list_item_2 :有两个控件。一次显示二行。
        simple_list_item_activated_1 : 有一个控件。当选项选中时,背景色改变(即为激活状态)
        simple_list_item_activated_2 : 有两个控件。当选项选中时,背景色改变(即为激活状态)

    (8)MainActivity。获得碎片管理器,管理两个碎片。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 获得 Fragment 管理器 (这两个碎片都被 MainActivity管了)
        FragmentManager fm = this.getFragmentManager();
        leftFragment = (LeftFragment)fm.findFragmentById(R.id.leftFragment);
        rightFragment = (RightFragment) fm.findFragmentById(R.id.rightFragment);
    }


    (9)LeftFragment。写此碎片的事件处理方法:点击选项的事件。

/**
     * Fragment 中的事件处理方法
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    // 在 Fragment 中点击选项 (Fragment 要先实现 AdapterView.OnItemClickListener 接口)
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // 点击的文本 :要传给Activity
        String text = data.get(position);
        // 调用回调(Activity)中的方法
        // callback 是 MainActivity的实例,因此它做事情,就是在 MainActivity 中做事情
        callback.onItemClick(text);
    }


    代码说明:

    此处,通过 callback 这个 MainActivity的实例,主布局已经获得了左边碎片要传递的值:text 。

    Fragment 实现 AdapterView.OnItemClickListener 接口:

public class LeftFragment extends Fragment implements AdapterView.OnItemClickListener{}


    (10)MainActivity。主布局要获得 左边的碎片 中的数据(通过调用 LeftFragment 内部接口定义的回调方法,获得 LeftFragment 中点击选项的文本)

/**
     * LeftFragment 内部接口定义的回调方法
     * @param text
     */
    @Override
    public void onItemClick(String text) {
        // 获得 LeftFragment 中点击的选项的文本
        rightFragment.displayContent(text);
    }


    其中, LeftFragment 内部接口定义的回调方法如下:

    //-----Fragment 与 Activity 传递参数------------------------------------
    private OnFragmentListener callback;
    
    /**
     * 从 Fragment 往 Activity 传递数据 : 通过调用内部的接口去传。
     * 1. 在 Fragment 中定义接口 (内部接口)
     * 2. Activity 实现 Fragment 中定义的接口
     */
    interface OnFragmentListener {
        // 点击当前 Fragment 中控件,回调的方法
        void onItemClick(String text);
    }


    代码说明:

    此处,通过 rightFragment 这个 右边碎片的对象,来调用 右边碎片的displayContent()方法,右边碎片就获得了左边碎片传递给主布局的值:text。

    (11)RightFragment。右边的碎片 从主布局中已经获得了数据,在此定义 displayContent() 方法,让数据(文本:text)在右边碎片界面上面显示。

    // 让文字在控件上面显示
    public void displayContent(String text){
        // 显示文本
        tvContent.setText(text);
    }



附   代码补充



    1. fragment_left.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context="com.xiangdong.staticfragment.LeftFragment">

  <ListView
      android:id="@+id/listView"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"/>

</FrameLayout>


    2. fragment_right.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:background="@android:color/holo_blue_light"
             tools:context="com.xiangdong.staticfragment.RightFragment">

  <!-- TODO: Update blank fragment layout -->
  <TextView
      android:id="@+id/tvContent"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_centerVertical="true"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:text="@string/app_name"
      android:textColor="@android:color/white"/>

</RelativeLayout>


    3. activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:paddingBottom="@dimen/activity_vertical_margin"
              tools:context=".MainActivity">

  <!--fragment:是类型。
  主界面上,显示两个 碎片(帧/片段) 界面
  -->
  <fragment
      android:id="@+id/leftFragment"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:name="com.xiangdong.staticfragment.LeftFragment"
      tools:layout="@layout/fragment_left"/>

  <fragment
      android:id="@+id/rightFragment"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:name="com.xiangdong.staticfragment.RightFragment"
      tools:layout="@layout/fragment_right"/>

</LinearLayout>


    4. MainActivity

package com.xiangdong.staticfragment;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

/**
 * Activity 实现 Fragment 中定义的接口
 */
public class MainActivity extends Activity implements LeftFragment.OnFragmentListener {
    private LeftFragment leftFragment;
    private RightFragment rightFragment;

    /**
     * LeftFragment 内部接口定义的回调方法
     *
     * @param text
     */
    @Override
    public void onItemClick(String text) {
        // 7. 获得 LeftFragment 中点击的选项的文本
        rightFragment.displayContent(text);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.v("FRAGMENT", "activity.onCreate............");
        super.onCreate(savedInstanceState);
        // 1. 加载主布局文件,就会加载两个碎片界面。(在配置文件中,布局文件与Activity关联了)
        setContentView(R.layout.activity_main);

        // 5. 获得 Fragment 管理器 (这两个碎片都被 MainActivity管了)
        FragmentManager fm = this.getFragmentManager();
        leftFragment = (LeftFragment) fm.findFragmentById(R.id.leftFragment);
        rightFragment = (RightFragment) fm.findFragmentById(R.id.rightFragment);
    }

    //----------------------------------------------------------------
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


}


    5. LeftFragment

package com.xiangdong.staticfragment;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class LeftFragment extends Fragment implements AdapterView.OnItemClickListener{
    private static final String TAG = "FRAGMENT";
    private ListView listView;
    private List<String> data;
    private ArrayAdapter<String> adapter;

    // 3. 创建 Fragment 时调用,主要用来初始化数据(准备好要用的数据)
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.v(TAG,"onCreate............");
        super.onCreate(savedInstanceState);
        data = new ArrayList<>();
        data.add("Android");
        data.add("IOS");
        data.add("Web");
        data.add("C");
        data.add("C#");
        data.add("C++");
    }

    // 4.加载 Fragment 视图 (界面出来了)
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 附件:看 Fragment 生命周期
        Log.v(TAG,"onCreateView............");
        // Inflate the layout for this fragment 填充指定布局文件
        View view = inflater.inflate(R.layout.fragment_left, container, false);
        // simple_list_item_1:一次只显示一行文字
        adapter = new ArrayAdapter<String>(this.getActivity(),
                android.R.layout.simple_list_item_1, data);
        listView = (ListView) view.findViewById(R.id.listView);
        listView.setAdapter(adapter);
        // 注册监听事件:设置当前(我自己)即可。
        listView.setOnItemClickListener(this);
        return view;
    }



    // AdapterView.OnItemClickListener :实现的接口
    /**
     * Fragment 中的事件处理方法
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    // 6. 在 Fragment 中点击选项
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // 点击的文本 :要传给Activity
        String text = data.get(position);
        // 调用回调(Activity)中的方法
        // 6.1 callback 是 MainActivity的实例,因此它做事情,就是在 MainActivity 中做事情
        callback.onItemClick(text);
    }

    /**
     * Fragment 与 Activity 关联时调用
     * @param activity
     */
    @Override
    public void onAttach(Activity activity) {
        Log.v(TAG, "onAttach............");
        // 2. 关联时,会调用这个方法
        super.onAttach(activity);
        // 获得活动的引用
        if(activity instanceof OnFragmentListener){
            // 2.1 活动实现了监听器,即可回调活动中的方法
            callback = (OnFragmentListener) activity;
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.v(TAG, "onActivityCreated............");
    }

    //-----Fragment 与 Activity 传递参数------------------------------------
    private OnFragmentListener callback;

    /**
     * 从 Fragment 往 Activity 传递数据 : 通过调用内部的接口去传。
     * 1. 在 Fragment 中定义接口 (内部接口)
     * 2. Activity 实现 Fragment 中定义的接口
     */
    interface OnFragmentListener {
        // 点击当前 Fragment 中控件,回调的方法
        void onItemClick(String text);
    }
}


    6. RightFragment

package com.xiangdong.staticfragment;


import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


public class RightFragment extends Fragment {
    private TextView tvContent;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment 填充指定布局文件
        View view = inflater.inflate(R.layout.fragment_right, container, false);
        tvContent = (TextView) view.findViewById(R.id.tvContent);
        return view;
    }

    // 让文字在控件上面显示
    public void displayContent(String text){
        // 8. 显示文本
        tvContent.setText(text);
    }
}



    案例(二)、动态 Fragment



    打开app后,默认加载的是“聊天”界面:



    当点击“聊天”按钮的时候,加载“聊天”界面,“聊天”字体变绿:



    当点击“联系人”按钮的时候,加载“联系人”界面,“联系人”字体变绿:



    当点击“朋友圈”按钮的时候,加载“朋友圈”界面,“朋友圈”字体变绿:




    (1)修改 activity_main.xml 。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

  <LinearLayout
      android:id="@+id/headLayout"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">

    <Button
        android:id="@+id/btnChat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="@string/chat"
        android:layout_weight="1"
        style="@android:style/Widget.Material.Button.Borderless"/>

    <Button
        android:id="@+id/btnContact"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="@string/contact"
        android:layout_weight="1"
        style="@android:style/Widget.Material.Button.Borderless"/>

    <Button
        android:id="@+id/btnDiscover"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="@string/discover"
        android:layout_weight="1"
        style="@android:style/Widget.Material.Button.Borderless"/>
  </LinearLayout>

  <LinearLayout
      android:id="@+id/contentLayout"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_below="@id/headLayout"
      android:orientation="horizontal">
  </LinearLayout>

</RelativeLayout>


    (3)创建三个碎片: ChatFragment & fragment_chat.xml,ContactFragment & fragment_contact.xml,DiscoverFragment & fragment_discover.xml 。并在三个碎片的布局文件中填入内容。



<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:paddingLeft="@dimen/activity_horizontal_margin"
             android:paddingRight="@dimen/activity_horizontal_margin"
             android:paddingTop="@dimen/activity_vertical_margin"
             android:paddingBottom="@dimen/activity_vertical_margin"
             tools:context="com.xiangdong.dynamicfragment.ChatFragment">

  <!-- TODO: Update blank fragment layout -->
  <TextView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:text="@string/chat"/>

</FrameLayout>




<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:paddingLeft="@dimen/activity_horizontal_margin"
             android:paddingRight="@dimen/activity_horizontal_margin"
             android:paddingTop="@dimen/activity_vertical_margin"
             android:paddingBottom="@dimen/activity_vertical_margin"
             tools:context="com.xiangdong.dynamicfragment.ContactFragment">

  <!-- TODO: Update blank fragment layout -->
  <TextView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:text="@string/contact"/>

</FrameLayout>




<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:paddingLeft="@dimen/activity_horizontal_margin"
             android:paddingRight="@dimen/activity_horizontal_margin"
             android:paddingTop="@dimen/activity_vertical_margin"
             android:paddingBottom="@dimen/activity_vertical_margin"
             tools:context="com.xiangdong.dynamicfragment.DiscoverFragment">

  <!-- TODO: Update blank fragment layout -->
  <TextView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:text="@string/discover"/>

</FrameLayout>


    (4)修改 MainActivity 。

// 声明变量
    private FragmentTransaction ft;  // 事务
    private FragmentManager fm;
    private Button btnChat;
    private Button btnContact;
    private Button btnDiscover;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnChat = (Button) findViewById(R.id.btnChat);
        btnContact = (Button) findViewById(R.id.btnContact);
        btnDiscover = (Button) findViewById(R.id.btnDiscover);

        // 获得 Fragment 管理器
        fm = this.getFragmentManager();
        // 开启事务
        ft = fm.beginTransaction();
        // 使用 Fragment 替换原来的界面(替换contentLayout:原来定义的线性布局。)
        ft.replace(R.id.contentLayout,new ChatFragment());
        // 提交事务
        ft.commit();
    }

    /**
     * 动态 Fragment:点击了谁,下面就显示相应的界面。
     * 并没有涉及 碎片之间传递数据(静态 Fragment),因此更简单些。
     * @param view
     */
    public void onClick(View view){
        // 开启事务
        ft = fm.beginTransaction();
        // 动态体现在这儿
        switch (view.getId()){
            case R.id.btnChat:
                // 使用 Fragment 替换原来的界面(替换contentLayout:原来定义的线性布局。)
                ft.replace(R.id.contentLayout,new ChatFragment());
                btnChat.setTextColor(Color.GREEN);
                btnContact.setTextColor(Color.BLACK);
                btnDiscover.setTextColor(Color.BLACK);
                break;
            case R.id.btnContact:
                ft.replace(R.id.contentLayout,new ContactFragment());
                btnChat.setTextColor(Color.BLACK);
                btnContact.setTextColor(Color.GREEN);
                btnDiscover.setTextColor(Color.BLACK);
                break;
            case R.id.btnDiscover:
                ft.replace(R.id.contentLayout,new DiscoverFragment());
                btnChat.setTextColor(Color.BLACK);
                btnContact.setTextColor(Color.BLACK);
                btnDiscover.setTextColor(Color.GREEN);
                break;
        }
        // 提交事务
        ft.commit();
    }



    附   代码补充



    1. strings.xml

<resources>
  <string name="app_name">DynamicFragment</string>

  <string name="action_settings">Settings</string>

  <string name="chat">聊天</string>
  <string name="contact">联系人</string>
  <string name="discover">朋友圈</string>
  
</resources>


    2. activity_main.xml

    3. 三个碎片的布局文件

    4. MainActivity

package com.xiangdong.dynamicfragment;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;


public class MainActivity extends Activity {
    // 动态 Fragment 步骤:
    // 1. 新建 Module
    // 2. 修改 activity_main.xml
    // 3. 创建 XxxFragment 和 fragment_Xxx.xml
    // 4. 修改 MainActivity

    // 4.1 声明变量
    private FragmentTransaction ft;  // 事务
    private FragmentManager fm;
    private Button btnChat;
    private Button btnContact;
    private Button btnDiscover;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnChat = (Button) findViewById(R.id.btnChat);
        btnContact = (Button) findViewById(R.id.btnContact);
        btnDiscover = (Button) findViewById(R.id.btnDiscover);

        // 4.2 获得 Fragment 管理器
        fm = this.getFragmentManager();
        // 4.3 开启事务
        ft = fm.beginTransaction();
        // 4.4 使用 Fragment 替换原来的界面(替换contentLayout:原来定义的线性布局。)
        ft.replace(R.id.contentLayout,new ChatFragment());
        // 4.5 提交事务
        ft.commit();
    }

    /**
     * 动态 Fragment:点击了谁,下面就显示相应的界面。
     * 并没有涉及 碎片之间传递数据(静态 Fragment),因此更简单些。
     * @param view
     */
    public void onClick(View view){
        // 4.3 开启事务
        ft = fm.beginTransaction();
        // 动态体现在这儿
        switch (view.getId()){
            case R.id.btnChat:
                // 4.4 使用 Fragment 替换原来的界面(替换contentLayout:原来定义的线性布局。)
                ft.replace(R.id.contentLayout,new ChatFragment());
                btnChat.setTextColor(Color.GREEN);
                btnContact.setTextColor(Color.BLACK);
                btnDiscover.setTextColor(Color.BLACK);
                break;
            case R.id.btnContact:
                ft.replace(R.id.contentLayout,new ContactFragment());
                btnChat.setTextColor(Color.BLACK);
                btnContact.setTextColor(Color.GREEN);
                btnDiscover.setTextColor(Color.BLACK);
                break;
            case R.id.btnDiscover:
                ft.replace(R.id.contentLayout,new DiscoverFragment());
                btnChat.setTextColor(Color.BLACK);
                btnContact.setTextColor(Color.BLACK);
                btnDiscover.setTextColor(Color.GREEN);
                break;
        }
        // 4.5 提交事务
        ft.commit();
    }


    //------------------------------------------------------------------------
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

猜你喜欢

转载自xiangdonglee.iteye.com/blog/2218344