安卓开发 - 简单使用 Android Fragment

初学 Android ,只是作为课外知识简单了解,偶尔写一写好玩的东西。今天照着书敲一个游戏,到晚上了记录下一天的收获,写一下 Android Fragment 的简单用法。

Fragment 是什么

Android 设备的分辨率非常不统一,所以适配分辨率是一个很头疼的发问题。于是在 Android 3.0 里, Android 提出了 Fragment ,解决了不同分别率适配的问题。
同时 Fragment 还可以动态添加删除,还有自己的生命周期,非常好用。目前貌似原生安卓的代码绝大多数都用到了 Fragment 。
Fragment 可以作为 Activity 的一个组件存在,甚至整个 Activity 都可以由 Fragment 构成。

Fragment 的生命周期

用一个图即可很清晰的说明:
1.png

上面这张图对应了 Fragment 和 Activity 的生命周期。

Fragment 的基本使用

Fragment最基本的使用,就是把它作为一个组件的放在 Activity 的布局文件中,用 android:name 属性或者 class 属性指定好相应 Fragment 的 Java 类,在 Java 类中 onCreateView() 方法 inflate 它即可。接下来 show the code :

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="net.conw.fragmenttest.MainActivity">

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="net.conw.fragmenttest.MainFragment" />

</RelativeLayout>

MainActivity.java

package net.conw.fragmenttest;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="net.conw.fragmenttest.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="There is a TextView in the fragment." />

</RelativeLayout>

MainFragment.java

package net.conw.fragmenttest;

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

public class MainFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_main, container, false);
    }
}

很简单的代码演示了 Fragment 最基本的用法,但是如果这么用 Fragment 貌似就没有什么用处了,接下来看动态使用 Fragment 的方法。

Fragment 的动态使用(使用 FragmentTransaction 的 replace() 方法)

若要动态的管理Fragment,应该使用 FragmentTransaction 。下面简单演示在两个 Fragment 之间的切换:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="net.conw.fragmenttest.MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center">
        <Button
            android:id="@+id/btn_fir"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="First Fragment" />

        <Button
            android:id="@+id/btn_sec"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Second Fragment" />
    </LinearLayout>

    <fragment
        android:id="@+id/fragment_main"
        android:name="net.conw.fragmenttest.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

MainActivity.java

package net.conw.fragmenttest;

import android.app.FragmentTransaction;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity implements View.OnClickListener {

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

        findViewById(R.id.btn_fir).setOnClickListener(this);
        findViewById(R.id.btn_sec).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        if(v.getId() == R.id.btn_fir) {
            transaction.replace(R.id.fragment_main, new FirstFragment());
        } else {
            transaction.replace(R.id.fragment_main, new SecondFragment());
        }

        transaction.commit();
    }
}

fragment_first.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="#7fff7f7f"
    tools:context="net.conw.fragmenttest.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is the first fragment" />

</RelativeLayout>

FirstFragment.java

package net.conw.fragmenttest;

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

public class FirstFragment extends Fragment {

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

fragment_second.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="#7f7f7fff"
    tools:context="net.conw.fragmenttest.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is the second fragment" />

</RelativeLayout>

SecondFragment.java

package net.conw.fragmenttest;

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

public class SecondFragment extends Fragment {

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

这样就实现了 Fragment 之间的切换了,上述方式每次都创建了一个新的 Fragment,下面介绍另一个方案。

Fragment 的动态使用(使用 FragmentTransaction 的 add(), hide(), show() 方法)

首先声明两个 Fragment 并创建两个对象,保证他们在整个类中可以访问:

private FirstFragment firstFragment = new FirstFragment();
private SecondFragment secondFragment = new SecondFragment();

然后是在 onCreate() 中把需要切换的 Fragment 都加入到 FragmentTransaction 中:

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.fragment_main, firstFragment);
transaction.add(R.id.fragment_main, secondFragment);
transaction.commit();
hideAll();

这里面的 hideAll() 方法是隐藏所有 Fragment。

private void hideAll() {
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.hide(firstFragment);
    transaction.hide(secondFragment);
    transaction.commit();
}

然后就是修改过的 onClick() 方法:

public void onClick(View v) {
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    if(v.getId() == R.id.btn_fir) {
        hideAll();
        transaction.show(firstFragment);
    } else {
        hideAll();
        transaction.show(secondFragment);
    }
    transaction.commit();
}

这样就大工告成了。

注意在布局文件中都用 name 属性或者 class 属性指定了一个默认 Fragment ,如果不指定就会报错。
还有就是我这里使用的是 import android.app.Fragment ,现在用 Android Studio 创建新 Fragment 通常都是 import android.support.v4.app.Fragment ,这里只需要把 getFragmentManager() 改为 getSupportFragmentManager() 就可以了。

标签: 安卓

添加新评论