第五章 探究Fragment
-
添加Fragment
-
XML中添加
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context=".chapter5.FragmentActivity"> <fragment android:id="@+id/leftFragment" android:name="com.youngly.firstlineofcode.chapter5.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="2" /> </LinearLayout>
-
动态添加
class FragmentActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_fragment) replaceFragment(RightFragment.newInstance()) } fun changeFragment(view: View) { replaceFragment(AnotherRightFragment.newInstance()) } private fun replaceFragment(newInstance: Fragment) { val beginTransaction = supportFragmentManager.beginTransaction() beginTransaction.replace(R.id.right_layout, newInstance) beginTransaction.commit() } }
-
实现返回栈
beginTransaction.addToBackStack(null)
-
-
生命周期
-
回调方法
onAttach(context: Context)
:当Fragment和Activity建立关联时调用onCreateView()
:为Fragment创建视图(加载布局)时调用onActivityCreated()
:确保与Fragment相关联的Activity已经创建完毕时调用onDestoryView()
:当与Fragment关联的视图被移除时调用onDetach()
:当Fragment和Activity解除关联时调用
-
-
动态加载布局技巧
-
使用限定符
layout-large
文件夹放置平板资源 -
使用最小宽度限定符
最小宽度限定符(smallest-width qualifier)这个对应的是开发者选项中最小宽度
最小宽度限定符允许我们对屏幕的宽度指定一个最小值(以dp为单位),以这个最小值为临界点,屏幕宽度大于这个值就加载这个目录下的布局。
-
-
最佳实践
实现一个app,手机端水果列表页面展示水果,点击某个水果跳转到水果详情页面。pad端左侧展示水果列表,右侧显示选中的水果详情。
-
实现两个Fragment:水果列表Fragment、水果详情Fragment
<?xml version="1.0" encoding="utf-8"?> <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" tools:context=".chapter5.FruitListFragment"> <ListView android:id="@+id/fruit_listview" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>
class FruitListFragment : Fragment() { private var fruitList = ArrayList<FruitListActivity.Fruit>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initFruits() } private fun initFruits() { repeat(20) { fruitList.add(FruitListActivity.Fruit(R.drawable.apple_pic, "Apple")) fruitList.add(FruitListActivity.Fruit(R.drawable.banana_pic, "Banana")) fruitList.add(FruitListActivity.Fruit(R.drawable.orange_pic, "Orange")) fruitList.add(FruitListActivity.Fruit(R.drawable.watermelon_pic, "Watermelon")) fruitList.add(FruitListActivity.Fruit(R.drawable.pear_pic, "Pear")) fruitList.add(FruitListActivity.Fruit(R.drawable.grape_pic, "Grape")) fruitList.add(FruitListActivity.Fruit(R.drawable.pineapple_pic, "PineApple")) fruitList.add(FruitListActivity.Fruit(R.drawable.strawberry_pic, "Strawberry")) fruitList.add(FruitListActivity.Fruit(R.drawable.cherry_pic, "Cherry")) fruitList.add(FruitListActivity.Fruit(R.drawable.mango_pic, "Mango")) } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_fruit_list, container, false) } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) view?.let { val fruitListView = it.findViewById<ListView>(R.id.fruit_listview) fruitListView.adapter = context?.let { it1 -> FruitAdapter(it1, R.layout.fruit_item, fruitList) } fruitListView.setOnItemClickListener { _, _, position, _ -> (context as FruitActivity).showFruit( fruitList[position].imgId, fruitList[position].name ) } } } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/constraint_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".chapter5.FruitFragment"> <ImageView android:id="@+id/fruit_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="268dp" android:src="@drawable/apple_pic" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/fruit_img" app:layout_constraintVertical_bias="0.118" /> </androidx.constraintlayout.widget.ConstraintLayout>
class FruitFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_fruit, container, false) } fun refreshView(resourceId: Int, name: String) { view?.apply { findViewById<ImageView>(R.id.fruit_img).setImageResource(resourceId) findViewById<TextView>(R.id.fruit_name).text = name } } }
-
实现Activity
-
手机布局
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".chapter5.FruitActivity"> <fragment android:id="@+id/chat_history" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.youngly.firstlineofcode.chapter5.FruitListFragment"/> </androidx.constraintlayout.widget.ConstraintLayout>
-
平板布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context=".chapter5.FruitActivity"> <fragment android:id="@+id/fruit_list_fragment" android:name="com.youngly.firstlineofcode.chapter5.FruitListFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/fruit_fragment" android:name="com.youngly.firstlineofcode.chapter5.FruitFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" /> </LinearLayout>
-
Activity代码
class FruitActivity : AppCompatActivity() { private var mIsLarge: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_fruit) // 通过判断右侧Fragment是否存在来判断是否是平板 mIsLarge = supportFragmentManager.findFragmentById(R.id.fruit_fragment) != null } fun showFruit(resourceId: Int, name: String) { if (mIsLarge) { (supportFragmentManager.findFragmentById(R.id.fruit_fragment) as FruitFragment).refreshView(resourceId, name) } else { val intent = Intent(this, FruitDetailActivity::class.java) intent.putExtra("resourceId", resourceId) intent.putExtra("name", name) startActivity(intent) } } }
-
-
-
Kotlin课堂
-
扩展函数
需求:统计字符串中字母个数
-
Java中编写Util类,定义函数获取字母个数
-
Kotlin中扩展函数
由于希望向String类中添加一个扩展函数,因此创建一个String.kt文件
fun String.letterCount(): Int { var count = 0 for (char in this) { if (char.isLetter()) count++ } return count }
-
-
运算符重载
运算符重载用的是
operator
关键字+
运算符对应的是plus()
函数下例是不同货币之间相加,得到同一货币
-
定义父类
/** * Creater: yanglei * Date: 2021/7/2 下午11:59 * Desc: * rate:汇率 */ open class Money(var value: Float, var rate: Float) { var symbol: String = "" operator fun plus(money: Money): Money { val newMoney = this::class.java.newInstance() this::class.java.superclass.getDeclaredField("value").set(newMoney, this.value + money.value * (money.rate / this.rate)) this::class.java.superclass.getDeclaredField("rate").set(newMoney, this.rate) newMoney.symbol = this.symbol return newMoney } override fun toString(): String { return "${this::class.java.simpleName}($symbol $value)" } }
-
定义人名币(汇率以人民币为基准)
class RMB(value: Float, rate: Float) : Money(value, rate) { constructor() : this(0f, 0f) init { symbol = "¥" } }
-
定义美元
class Dollar(value: Float, rate: Float) : Money(value, rate) { constructor() : this(0f, 0f) init { symbol = "$" } }
-
测试
fun main() { val fl = RMB(7f, 1f) + Dollar(1f, 7f) println(fl) val money = Dollar(1f, 7f) + RMB(7f, 1f) println(money) }
-
输出
RMB(¥ 14.0) Dollar($ 2.0)
-
-