如有轉載,請申明:
轉載至 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與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。是以,一般情況下也沒有必要向下相容了。