kotlin的fragment

使用方式

简单用法

先从最简单的开始:一个页面包含左右两个fragment。新建FragmentTest,新建一个左侧fragment的布局left_fragment.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
 
    <Button 
        android:id="@+id/button" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center_horizontal" 
        android:text="Button" />

</LinearLayout>

再新建一个右侧fragment的布局right_fragment.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"  
    android:background="#00ff00"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
 
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center_horizontal" 
        android:textSize="24sp" 
        android:text="This is right fragment" />

</LinearLayout>

接着新建LeftFragment类,并继承ragment,此处继承的Fragment一定要是AndroidX库中的。编写LeftFragment:

class LeftFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return LayoutInflater.from(context).inflate(R.layout.left_fragment, container, false)
    }
}

接着创建RightFragment:

class RightFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return LayoutInflater.from(context).inflate(R.layout.right_fragment, container, false)
    }
}

修改activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <fragment
        android:id="@+id/leftFrag"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/rightFrag"
        android:name="com.example.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

 此时可运行。

动态添加fragment

fragment的强大之处在于,可以在程序运行时动态添加到activity,而根据具体情况动态地添加fragment,我们就可以将程序界面定制的更加多样化。

新建another_right_fragment.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffff00"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="This is another right fragment"
        android:textSize="24sp" />
</LinearLayout>

新建AnotherRightFragment作为另一个右侧fragment:

class AnotherRightFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return LayoutInflater.from(context).inflate(R.layout.another_right_fragment, container, false)
    }
}

修改activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <fragment
        android:id="@+id/leftFrag"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <FrameLayout
        android:id="@+id/rightLayout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

将右侧的fragment修改为了一个frameLayout,这是最简单的一种布局,所有空间默认都会摆放在布局的左上角。此处我们需要在布局中摆放一个fragment,不需要任何定位,因此非常适合使用。

修改MainActivity:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.setOnClickListener {
            replaceFragment(AnotherRightFragment())
        }
        replaceFragment(RightFragment())
    }

    private fun replaceFragment(fragment: Fragment) {
        //在activity中可以直接调用getSupportFragmentManager方法获取FragmentManager
        val fragmentManager = supportFragmentManager
        //开启事务
        val transaction = fragmentManager.beginTransaction()
        //向容器内添加或替换fragment,一般用replace方法
        transaction.replace(R.id.rightLayout, fragment)
        //提交事务
        transaction.commit()
    }
}

实现返回栈

实现了动态添加fragment的功能后,如果我们点击返回键,程序会直接退出。如果我们想实现按返回键可以回到上一个fragment、这样一个类似返回栈的效果,我们可以使用FragmentTransaction的addToBackStack方法,用于将一个事务添加到返回栈中。

class MainActivity : AppCompatActivity() { 
    ... 
    private fun replaceFragment(fragment: Fragment) { 
        val fragmentManager = supportFragmentManager 
        val transaction = fragmentManager.beginTransaction() 
        transaction.replace(R.id.rightLayout, fragment) 
        //可以接收名字描述返回栈的情况,一般传入null即可
        transaction.addToBackStack(null) 
        transaction.commit() 
    } 
}

Fragment和Activity之间的交互

虽然Fragment是嵌入在Activity中显示的,可是它们的关系并没有那么亲密。实际上,Fragment和Activity是各自存在于一个独立的类当中的,它们之间并没有那么明显的方式来直接进行交互。

为了方便Fragment和Activity之间进行交互,FragmentManager提供了一个类似于findViewById()的方法,专门用于从布局文件中获取Fragment的实例:

val fragment = supportFragmentManager.findFragmentById(R.id.leftFrag) as LeftFragment

另外,kotlin-android-extensions插件也对此进行了扩展:

val fragment = leftFrag as LeftFragment

无疑后者是更推荐的写法。

而如果我们想要在fragment中调用activity中的方法,直接使用fragment中的getActivity方法,就可以得到和当前fragment相关联的activity:

if (activity != null) {
    val mainActivity = activity as MainActivity
}

由于getActivity方法可能返回null,所以我们要先进行判空处理。另外当fragment需要context对象时,也可以使用getActivity方法,因为获取到的activity对象本身就是一个context对象。

而既然fragment可以和activity通信,那么fragment之间也可以做到,只需要在一个fragment中获取与之相关联的activity,再让这个activity去获取另一个我们想通信的fragment,这样就可以实现了。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值