昨天設好導覽列,要讓點擊導覽列按鈕會跳去不同的頁面,這個功能看起來和 Activity 切換相似,卻是使用好幾個 Fragment 在同一個 Activity 裡面,用這個簡單例子練習 Fragment 的 Layout 和 Button 點擊事件怎麼載入。
Fragment
依附在 Activity 上的類別,一個 Activity 可以存在多個 Fragment,一個 Fragment 也可以被多個 Activity 複用。而作為切換頁面或分割畫面的工具, Fragment 也有自己的生命周期:
設定 Fragment
//系統自動建立的class
class BlankFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false)
}
}
新的問題:
Fragment做好後,如何在 MainActivity 動態載入 Fragment?
首先要了解 Fragment 的載入方式,有分成靜態載入和動態載入兩種,靜態載入是在 layout.xml 中直接插入<Fragment>
,意味著在 Activity 建立之初就直接建立呼叫 Fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<fragment
android:id="@+id/frag"
class = "com.example.fish.day8_bottomnavigationfragmentintent.Fragment_0"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
動態載入則彈性很多,我們可以選擇在需要 Fragment 運作時才執行載入動作,基本動態載入會使用到 FragmentManager
及 FragmentTransaction
:
FragmentManager
用來管理 Fragment,處理其狀態及對它的生命週期進行監聽,可透過 getSupportFragmentManager() 方法來取得
val manager = supportFragmentManager
FragmentManager 有許多基本方法可以使用,比較常使用到的方法有 beginTransaction()、findFragmentById (id: Int)、findFragmentByTag (tag: String)等方法,這邊只會使用到第一種:
FragmentTransaction()
有了它之後可以對 Fragment做許多操作,例如載入 add、刪除 remove、顯示 show、隱藏 hide 等等,FragmentTransaction 可以透過 beginTransaction() 方法取得
val transaction = supportFragmentManager.beginTransaction()
稍微了解基本用法之後,就可以來把剛剛做的 Fragment 用進來,需要做的事情有以下幾種:
複習昨天 MainActivity 進度 ,只放到 NavigationButton的方法和做到一半的監聽器(如下)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navigation.setOnNavigationItemSelectedListener ()
}
private var listener = object :BottomNavigationView.OnNavigationItemSelectedListener {
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.item_fragment1 -> {
}
R.id.item_fragment2 -> {
}
R.id.item_fragment3 -> {
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val manager = supportFragmentManager
val transaction = manager.beginTransaction()
transaction.replace(R.id.frameLayout, BlankFragment()).commit()
navigation.setOnNavigationItemSelectedListener ()
}
FragmentTransaction 的方法有很多種,可以看小魚的Android Kotlin 實作 Day 8 來認識這幾種方法,add、remove、replace等等,這邊運用到「replace」是替換掉 container 中的 Fragment
FragmentTransaction replace (containerViewId: Int, fragment: Fragment, tag: String)
R.id.item_fragment2 -> {
val manager = supportFragmentManager
val transaction = manager.beginTransaction()
transaction.replace(R.id.frameLayout, BlankFragment2()).commit()
return true
}
navigation.setOnNavigationItemSelectedListener (listener)
做完之後才想到如果想為 Fragment 內的物件設置監聽事件,該怎麼做?
其實滿簡單的,只需要在 onCreateView()
實例化時操作、載入 View 的時候順便設置,例如想要在 Fragment2 放一個簡單的按紐,點擊之後會有 AlertDialog 對話方塊跳出來:
view.button_id.setOnClickListener{} //實例化view之後取得點擊方法
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_blank_fragment2, container, false)
view.btn_mail.setOnClickListener{
AlertDialog.Builder(this.context)
.setTitle("聯繫方式")
.setMessage("我的信箱:zoeaeen13@gmail.com ")
.setPositiveButton("確認"){dialog, _ ->
dialog.dismiss()
}
.show()
}
return view //回傳view
}