天天看點

安卓Fragment快速入門 Fragment的作用Fragment的編寫Fragment的靜态引用Fragment的動态引用Fragment與Activity互動Fragment向下相容

如有轉載,請申明:

轉載至 http://blog.csdn.net/qq_35064774/article/details/52622714

Fragment雖然不是四大元件之一,但在界面布局方面非常重要。

Fragment的作用

Fragment是API11時新引入的輕量級”Activity”。目的是為了更友善的适配大小螢幕,在平闆和手機上可以有完全不同的Fragment。可以很友善的動态添加删除Fragment。

Fragment的編寫

Fragment類似于Activity,隻要繼承Fragment類即可。

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.ittianyu.basictest.R;
 
public class StaticUseFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
 
        return inflater.inflate(R.layout.fragment_display, container, false);
    }
}
           

上述代碼為最簡單的Fragment,隻有onCreateView這一個生命周期方法。

這個方法會在建立Fragment視圖時調用,需要傳回要顯示的View。

這裡傳回的是fragment_display.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:background="#440000ff"
    tools:context="com.ittianyu.basictest.fragmentquickstart.DisplayFragment">
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="display fragment" />
 
</FrameLayout>
           

Fragment的靜态引用

自己編寫的Fragment可以像其他控件一樣,直接在xml中引用。

具體引用代碼如下。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="com.ittianyu.basictest.fragmentquickstart.FragmentQuickStartActivity">
 
    <fragment
        android:id="@+id/f_static_use"
        android:name="com.ittianyu.basictest.fragmentquickstart.StaticUseFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
 
</LinearLayout>
           

隻需要使用fragment标簽,然後加上name屬性,指定要引用的Fragment對象即可。

但值得注意的時,這樣做的時候,我的Android Studio IDE報了一個警告,不推薦這麼做。

Fragment的動态引用

先分别編寫3個Fragment

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
 
import com.ittianyu.basictest.R;
 
public class SoundFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_sound, container, false);
        return view;
    }
}
 
 
 
package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.ittianyu.basictest.R;
 
 
public class SaveFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_save, container, false);
    }
}
 
 
package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.ittianyu.basictest.R;
 
public class DisplayFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_display, container, false);
    }
}
           

這三個Fragment和最開始介紹的編寫方式差不多,隻是換了個xml界面。

接下來是三個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:background="#44ff0000"
    tools:context="com.ittianyu.basictest.fragmentquickstart.SoundFragment">
 
    <Button
        android:id="@+id/btn_get_text"
        android:text="擷取activity中的文本内容"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
 
</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:background="#4400ff00"
    tools:context="com.ittianyu.basictest.fragmentquickstart.SaveFragment">
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="save fragment" />
 
</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:background="#440000ff"
    tools:context="com.ittianyu.basictest.fragmentquickstart.DisplayFragment">
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="display fragment" />
 
</FrameLayout>
           

有了Fragment,我們接下來寫動态引用Fragment的類。

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
 
import com.ittianyu.basictest.R;
 
public class FragmentQuickStartActivity extends AppCompatActivity implements View.OnClickListener {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment_quick_start);
 
        init();
    }
 
    /**
     * 初始化按鈕事件
     */
    private void init() {
        findViewById(R.id.sound).setOnClickListener(this);
        findViewById(R.id.display).setOnClickListener(this);
        findViewById(R.id.save).setOnClickListener(this);
 
        sound();
    }
 
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sound:
                sound();
                break;
            case R.id.display:
                display();
                break;
            case R.id.save:
                save();
                break;
        }
    }
 
    /**
     * 顯示sound fragment
     */
    private void sound() {
        // 獲得fragment管理對象(使用v4包向下相容)
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.frame, new SoundFragment());
        transaction.commit();
    }
    /**
     * 顯示sound fragment
     */
    private void save() {
        // 獲得fragment管理對象(使用v4包向下相容)
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.frame, new SaveFragment());
        transaction.commit();
    }
    /**
     * 顯示sound fragment
     */
    private void display() {
        // 獲得fragment管理對象(使用v4包向下相容)
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.frame, new DisplayFragment());
        transaction.commit();
    }
}
           

結構很簡單的代碼,三個按鈕點選之後,分别顯示相應的Fragment。

對了,還沒貼出該Activity對應的xml。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="com.ittianyu.basictest.fragmentquickstart.FragmentQuickStartActivity">
 
    <EditText
        android:id="@+id/et_content"
        android:hint="請輸入内容"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
 
    <FrameLayout
        android:id="@+id/frame"
        android:layout_weight="3"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>
 
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/sound"
            android:text="聲音"
            android:layout_weight="1"
            android:layout_width="0dip"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/display"
            android:text="顯示"
            android:layout_weight="1"
            android:layout_width="0dip"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/save"
            android:text="存儲"
            android:layout_weight="1"
            android:layout_width="0dip"
            android:layout_height="wrap_content" />
    </LinearLayout>
 
</LinearLayout>
           

下面解釋一下如何動态引用fragment。

首先我們要管理fragment就需要一個FragmentManager。

FragmentManager manager = getSupportFragmentManager();

然後通過管理器,開啟一個事務,這樣是為了一次性送出,防止界面花屏。

FragmentTransaction transaction = manager.beginTransaction();

拿着事務去替換fragment,也就是把Fragment放入到了id為frame的控件中。

transaction.replace(R.id.frame, new DisplayFragment());

最後送出修改

transaction.commit();

運作之後,我們應該會看到如下界面。

點選不同的按鈕會切換到相應的Fragment。

然後你會看到圖中Fragment中有個按鈕是用來擷取Activity中的EditText的中内容的。但是上面代碼并沒有實作,那麼如何實作呢?

請繼續往下看。

安卓Fragment快速入門 Fragment的作用Fragment的編寫Fragment的靜态引用Fragment的動态引用Fragment與Activity互動Fragment向下相容

Fragment與Activity互動

Fragment必須依賴Activity才能存在,是以一般來說都會持有Activity的引用,事實上API也是這樣設計的。

在Fragment類中,可以通過getActivity拿到Fragment所在的Activity引用。

是以,要實作點選Fragment中的按鈕擷取Activity控件内容,也變得很容易。

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
 
import com.ittianyu.basictest.R;
 
public class SoundFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_sound, container, false);
        // 設定fragment中的按鈕的點選事件
        view.findViewById(R.id.btn_get_text).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 拿到fragment所處的activity,然後擷取其中的edittext的内容,顯示出來
                EditText etContent = (EditText) getActivity().findViewById(R.id.et_content);
                String content = etContent.getText().toString().trim();
                if(TextUtils.isEmpty(content)) {
                    Toast.makeText(getActivity(), "文本内容為空", Toast.LENGTH_SHORT).show();
                   return;
                }
                Toast.makeText(getActivity(), content, Toast.LENGTH_SHORT).show();
            }
        });
 
        return view;
    }
}
           

Fragment向下相容

在文章開頭就介紹了Fragment是API11時才加入安卓的,也就是安卓3.0以後才可以使用Fragment,然而谷歌早就看穿了一切,為我們提供了向下相容包,也就是常說的support包。

為了在低版本中使用Fragment,我們需要使用的是support.v4中的Fragment,而我們上面的代碼也是這樣做的,細心的你應該會發現我導入的是

import android.support.v4.app.Fragment;

而不是

import android.app.Fragment;

同樣的,在Activity中,導入的也是v4的包

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentTransaction;

使用v4包的Fragment與正常的Fragment幾乎沒有差别,但有一個地方需要注意。

用V4包時,擷取FragmentManager要用getSupportFragmentManager,也就是如下。

FragmentManager manager = getSupportFragmentManager();

而如果是非相容的API,則用的是getFragmentManager()。

最後還需要提醒一點的是,現在(2016年)安卓4.0以下的裝置非常少了,基本都是上5.0。是以,一般情況下也沒有必要向下相容了。

繼續閱讀