android基础知识之 - Fragment

  • android基础知识之 - Fragment
    • 1.1 碎片的简单用法
    • 1.2 动态添加碎片
    • 1.3 在碎片中模拟返回栈
    • 1.4 Fragment和Activity之间进行通信
    • 1.5 Fragment的生命周期

android基础知识之 - Fragment

1.1 碎片的简单用法

  • 需求:

    • 在一个Activity当中添加两个碎片,并让这两个碎片平分活动空间
  • 最终视图:
    android基础知识之 - Fragment_第1张图片

  • 源码:

  • 新建一个左侧Fragment布局left_fragment.xml :


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Button"
        />

LinearLayout>
  • 图示:
    android基础知识之 - Fragment_第2张图片

这个布局中放置了一个Button,并让它水平居中显示

  • 新建右侧Fragment布局right_fragment.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#00ff00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is right fragment"
        />

LinearLayout>
  • 图示:
    android基础知识之 - Fragment_第3张图片

这个布局的背景颜色设置成了绿色,并放置了一个TextView用于显示一段文本

  • 新建一个LeftFragment类,并让它继承自Fragment,这里选择继承support-v4库,另外我们不需要再build.gradle文件中添加support-v4库的依赖,因为build.gradle文件中已经添加了appcompat-v7库的依赖,而这个库会将support-v4库也一起引入进来

LeftFragment :

public class LeftFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;
    }

}

重写Fragment的onCreateView()方法,然后在这个方法中通过LayoutInflater的inflate()方法将刚才定义的left_fragment布局动态加载进来

  • 用同样的方法新建RightFragment :
public class RightFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        View view = inflater.inflate(R.layout.right_fragment, container, false);
        return view;
    }
}
  • 接下来修改activity_main.xml中的代码,将LeftFragment和RightFragment加载进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" >

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/right_fragment"
        android:name="com.example.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

LinearLayout>

可以看到使用标签在布局中添加碎片,这里通过android:name属性来显示指明要添加的碎片类名,注意一定要将类的包名也加上

  • 最终效果:
    android基础知识之 - Fragment_第4张图片
    两个Fragment平分整个活动的布局

1.2 动态添加碎片

  • 效果图:
    android基础知识之 - Fragment_第5张图片

Fragment真正强大之在于,它可以在程序运行时动态地添加到活动中

  • 在1.1的基础上修改源码
  • 新建another_right_fragment.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#ffff00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is another right fragment"
        />

LinearLayout>

这个布局和right_frgment.xml中的代码基本相同,只是将背景色改成黄色,并修改了显示的文字

  • 新建AnotherRightFragment作为另一个右侧碎片 :
public class AnotherRightFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.another_right_fragment, container, false);
        return view;
    }

}

同样是在onCreateView()方法中加载了刚刚创建的another_right_fragment布局

  • 准备好另一个Fragment之后,就来看一下如果将它动态地添加到活动中,修改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" >

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    // 新增布局
    <FrameLayout
        android:id="@+id/right_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1">
    FrameLayout>

LinearLayout>

可以看到,现在将右侧碎片替换成了一个FrameLayout,下面我们将在代码中想FrameLayout里添加内容,从而实现动态添加碎片的功能,修改MainActivity中的代码 :

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
        replaceFragment(new RightFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                replaceFragment(new AnotherRightFragment());
                break;
            default:
                break;
        }
    }

    private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.commit();
    }

}

可以看到,首先我们给左侧Fragment中的按钮注册了一个点击事件,然后调用replaceFragment()方法动态添加了RightFragment这个碎片,当点击左侧碎片中的按钮时,又会调用replaceFragment()方法将右侧碎片替换成AnotherRightFragment,结合replaceFragment()方法中的代码可以看出,动态添加Fragment主要分为5步:

  1. 创建待添加的碎片实例。这里是RightFragment()和AnotherRightFragment()
  2. 获取FragmentManager,在Activity中可以直接通过调用getSupportFragmentManager()方法得到
  3. 开启一个事务,通过调用FragmentManager的beginTransaction()方法开启
  4. 向容器内添加或替换Fragment,一般使用replace()方法实现,需要传入容器的id和待添加的Fragment实例
  5. 提交事务,调用commit()方法来完成
    这样就完成了在活动中动态添加碎片的功能

    • 最终效果:
      android基础知识之 - Fragment_第6张图片

可以看到,通过点击按钮添加了一个碎片之后,这时按下Back键程序就会直接退出

1.3 在碎片中模拟返回栈

  • 添加返回栈效果:

1.2中通过点击按钮添加了一个碎片之后,这时按下Back键程序就会直接退出,如果这里我们要模拟返回栈的效果,按下Back键可以回到上一个碎片,要实现这种效果其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以用于将一个事务添加到返回栈中,修改MainActivity中的代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ...
    private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        // 添加
        transaction.addToBackStack(null);
        transaction.commit();
    }
}

在这里我们在事务提交之前条用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,一般传入null即可

  • 最终效果:
    android基础知识之 - Fragment_第7张图片

1.4 Fragment和Activity之间进行通信

虽然Fragment都是嵌入在Activity中显示的,可是实际上它们之间的关系并没有那么亲密,可以看出Fragment和Activity都是各自存在于一个独立的类当中的,它们之间并没有那么明显的方式来直接进行通信,如果想要在Activity中调用Fragment的方法,或者在Fragment中调用Activity方法,应该如何实现?

为了方便Fragment和Activity之间进行通信,FragmentManager提供了一个findFragmentById()的方法,专门用于从布局文件中获取碎片的实例:

NewsContentFragment newsContentFragment = (NewsContentFragment)getFragmentManager().findFragmentById(R.id.news_content_fragment);

调用FragmentManager的findFragmentById()方法,可以在Activity中得到相应Fragment的实例,然后就可以轻松地调用Fragment里面的方法了

那么Fragment又是怎样调用Activity里面的方法呢?在每个Fragment中都可以通过getActivity()方法来得到和当前Fragment相关联的Activity实例:

MainActivity activity = (MainActivity)getActivity();

有了Activity实例后,在Fragment中调用Activity里的方法就变得轻而易举了,当碎片中需要使用Context对象时,也可以使用getActivity()方法,因为获得的Activity本身就是个Context对象

那么Fragment与Fragment之间如何进行通信呢?

首先在Fragment中可以得到与它相关联的Activity,然后再通过这个Activity去获取另外一个Fragment的实例,这样也就实现了不同Fragment之间的通信功能

1.5 Fragment的生命周期

和Activity一样,Fragment也有自己的生命周期,理解Fragment的生命周期非常重要,我们通过代码的方式来瞧一瞧Fragment的生命周期是什么样的:

public class Fragment1 extends Fragment {  
    public static final String TAG = "Fragment1";  

    @Override  
    public void onAttach(Activity activity) {  
        super.onAttach(activity);  
        Log.d(TAG, "onAttach");  
    }  

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

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
        Log.d(TAG, "onCreateView");  
        return inflater.inflate(R.layout.fragment1, container, false);  
    }  

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

    @Override  
    public void onStart() {  
        super.onStart();  
        Log.d(TAG, "onStart");  
    }  

    @Override  
    public void onResume() {  
        super.onResume();  
        Log.d(TAG, "onResume");  
    }  

    @Override  
    public void onPause() {  
        super.onPause();  
        Log.d(TAG, "onPause");  
    }  

    @Override  
    public void onStop() {  
        super.onStop();  
        Log.d(TAG, "onStop");  
    }  

    @Override  
    public void onDestroyView() {  
        super.onDestroyView();  
        Log.d(TAG, "onDestroyView");  
    }  

    @Override  
    public void onDestroy() {  
        super.onDestroy();  
        Log.d(TAG, "onDestroy");  
    }  

    @Override  
    public void onDetach() {  
        super.onDetach();  
        Log.d(TAG, "onDetach");  
    }  

}  

可以看到,上面的代码在每个生命周期的方法里都打印了日志,然后我们来运行一下程序,可以看到打印日志如下:
android基础知识之 - Fragment_第8张图片
这时点击一下home键,打印日志如下:
这里写图片描述
如果你再重新进入进入程序,打印日志如下:
这里写图片描述
然后点击back键退出程序,打印日志如下:
android基础知识之 - Fragment_第9张图片
看到这里,我相信大多数朋友已经非常明白了,因为这和Activity的生命周期太相似了。只是有几个Activity中没有的新方法,这里需要重点介绍一下:

  • onAttach方法:Fragment和Activity建立关联的时候调用。
  • onCreateView方法:为Fragment加载布局时调用。
  • onActivityCreated方法:当Activity中的onCreate方法执行完后调用。
  • onDestroyView方法:Fragment中的布局被移除时调用。
  • onDetach方法:Fragment和Activity解除关联的时候调用。

参考:
Android Fragment完全解析,关于碎片你所需知道的一切
https://blog.csdn.net/guolin_blog/article/details/8881711

你可能感兴趣的:(Android)