完整代码Gitee地址:kotlin-demo: 10天Kotlin学习计划
第四天学习内容代码:Chapter4
目录
Fragment简介
知识点1:Fragment生命周期
知识点2:TabLayout + ViewPager
Fragment是Android3.0后引入的一个新的API,他出现的初衷是为了适应大屏幕的平板电脑, 当然现在他仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会加入这个Fragment,我们可以把他看成一个小型的Activity,又称Activity片段。
如果一个很大的界面,我们就一个布局,写起界面来会有多麻烦,而且如果组件多的话是管理起来也很麻烦!而使用Fragment我们可以把屏幕划分成几块,然后进行分组,进行一个模块化的管理!从而可以更加方便的在运行过程中动态地更新Activity的用户界面!
另外Fragment并不能单独使用,他需要嵌套在Activity中使用,尽管他拥有自己的生命周期,但是还是会受到宿主Activity的生命周期的影响。比如,当Activity暂停时,其中的所有片段也会暂停;当Activity被销毁时,所有片段也会被销毁。 不过,当Activity 正在运行(处于已恢复生命周期状态)时,您可以独立操纵每个片段,如添加或移除它们。 当您执行此类片段事务时,您也可以将其添加到由Activity管理的返回栈,Activity中的每个返回栈条目都是一条已发生片段事务的记录。返回栈让用户可以通过按返回按钮撤消片段事务(后退)。
因为我们主要是学习Kotlin,直接上实例重点记录。
还记得每个Activity在其生命周期内可能会有哪几种状态吗?没错,一共有运行状态、暂停状态、停止状态和销毁状态这4种。类似地,每个Fragment在其生命周期内也可能会经历这几种状态,只不过在一些细小的地方会有部分区别。
运行状态
当一个Fragment所关联的Activity正处于运行状态时,该Fragment也处于运行状态。
暂停状态
当一个Activity进入暂停状态时(由于另一个未占满屏幕的Activity被添加到了栈顶),与它相关联的Fragment就会进入暂停状态。
停止状态
当一个Activity进入停止状态时,与它相关联的Fragment就会进入停止状态,或者通过调用FragmentTransaction的remove()、replace()方法将Fragment从Activity中移除,但在事务提交之前调用了addToBackStack()方法,这时的Fragment也会进入停止状态。总的来说,进入停止状态的Fragment对用户来说是完全不可见的,有可能会被系统回收。
销毁状态
Fragment总是依附于Activity而存在,因此当Activity被销毁时,与它相关联的Fragment就会进入销毁状态。或者通过调用FragmentTransaction的remove()、replace()方法将Fragment从Activity中移除,但在事务提交之前并没有调用addToBackStack()方法,这时的Fragment也会进入销毁状态。
结合之前的Activity状态,相信你理解起来应该毫不费力吧。同样地,Fragment类中也提供了一系列的回调方法,以覆盖它生命周期的每个环节。其中,Activity中有的回调方法,Fragment中基本上也有,不过Fragment还提供了一些附加的回调方法,下面我们就重点看一下这几个回调。
● onAttach():当Fragment和Activity建立关联时调用。
● onCreateView():为Fragment创建视图(加载布局)时调用。
● onActivityCreated():确保与Fragment相关联的Activity已经创建完毕时调用。
● onDestroyView():当与Fragment关联的视图被移除时调用。
Fragment完整的生命周期可参考图:
我们使用Tablayout用作页面切换指示器,ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view。
TabLayout属性:
app:tabIndicatorColor :指示线的颜色
app:tabIndicatorHeight : 指示线的高度
app:tabIndicatorFullWidth="false" 指示线是否铺满宽度
app:tabSelectedTextColor : tab选中时的字体颜色
app:tabTextColor="@color/colorPrimary" :未选中字体颜色
app:tabBackground="color" : 整个tablayout颜色
app:tabMode="scrollable" : 默认是fixed,固定的;scrollable:可滚动的
下面我们通过一个例子来学习一下它的用法 ,开始编写布局,新建activity_learn4.xml:
新建Learn4Activity,来加载TabLayout与ViewPager:
class Learn4Activity : BaseActivity() {
//使用lateinit必须初始化
private lateinit var tabLayout: TabLayout
private lateinit var viewPager: ViewPager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_learn4)
val title: TextView = findViewById(R.id.tv_title)
title.text = "Fragment"
tabLayout = findViewById(R.id.tab_main)
viewPager = findViewById(R.id.viewPager)
tabLayout.addTab(tabLayout.newTab().setText("首页"))
tabLayout.addTab(tabLayout.newTab().setText("资讯"))
tabLayout.addTab(tabLayout.newTab().setText("我的"))
tabLayout.tabGravity = TabLayout.GRAVITY_FILL
val adapter = MyAdapter(supportFragmentManager, tabLayout.tabCount)
viewPager.adapter = adapter
viewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
viewPager.currentItem = tab.position
}
override fun onTabUnselected(tab: TabLayout.Tab) {
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
}
class MyAdapter(fm: FragmentManager, private var totalTabs: Int) :
FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment {
return when (position) {
0 -> HomeFragment()
1 -> NewsFragment()
2 -> MineFragment()
else -> throw IllegalArgumentException()
}
}
override fun getCount(): Int {
return totalTabs
}
}
}
实体类UserBean:
class UserBean(val herd: Int, val name: String, val phone: String)
接下来新建一个HomeFragment类,继承自Fragment,代码如下所示:
class HomeFragment : Fragment() {
private var mContext: Context? = null
private val userList = ArrayList()
private lateinit var mAdapter: UserNewAdapter
override fun onAttach(context: Context) {
super.onAttach(context)
mContext = context
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
initUser()
initView(recyclerView)
return view
}
private fun initView(recyclerView: RecyclerView) {
mAdapter = UserNewAdapter(userList)
recyclerView.layoutManager = LinearLayoutManager(activity)
recyclerView.adapter = mAdapter
//mAdapter.addData(userList)//添加数据
}
private fun initUser() {
repeat(1) {
userList.add(UserBean(R.mipmap.image_nv, "迪丽不热", "17321341289"))
userList.add(UserBean(R.mipmap.image_nan, "杀手不冷", "17377621412"))
userList.add(UserBean(R.mipmap.image_nv, "赵思露", "19987878221"))
userList.add(UserBean(R.mipmap.image_nv, "井川里予", "13612344637"))
userList.add(UserBean(R.mipmap.image_nan, "阿斯顿", "13635465678"))
userList.add(UserBean(R.mipmap.image_nan, "没啥用科技", "13801940921"))
userList.add(UserBean(R.mipmap.image_nv, "阿瑟东", "16622348923"))
}
}
}
UserNewAdapter适配器,代码如下:
class UserNewAdapter(userList: ArrayList) :
BaseQuickAdapter(R.layout.item_rcy_cont, userList) {
override fun convert(holder: BaseViewHolder, item: UserBean) {
//获取控件ID
val icon = holder.getView(R.id.iv_herd)
//展示图片
icon.setImageResource(item.herd)
//直接设置文本内容
holder.setText(R.id.tv_name, item.name)
holder.setText(R.id.tv_phone, item.phone)
}
}
HomeFragment的局部代码,新建fragment_home.xml:
运行效果图:
通过这个例子,对Fragment的理解一定又加深了许多,稍作修改可以运用到实际项目。