尝试用kotlin做一个app(四)
本来是应该为主页加载数据库数据了,但是想着做后台,之前写jsp后台写吐了,所以先拖几天。把之前的代码完善一下,或者添加些新内容。
......
多个fragment切换卡顿
首先修正一个bug。从主页切换到别的页面,再返回主页,耗时很长。原因是之前响应bottombar点击事件切换Fragment,使用的是transAction.replace方法。我的理解是这样,replace会先执行remove,移除之前的fragment;再执行add方法,添加需要添加的Fragment。所以每次replace的时候,都要重新创建一个Fragment实例。那解决办法是直接使用add方法
transAction.add在不移除被覆盖的Fragment的同时,把新的Fragment覆盖在上面
所以尝试直接把replace换成add
val transAction = supportFragmentManager.beginTransaction() // transAction.replace(R.id.contentContainer,FragmentManage.fragmentManage.getFragment(it)!!,it.toString()) transAction.add(R.id.contentContainer,FragmentManage.fragmentManage.getFragment(it)!!) transAction.commit()
运行一开始,后面fragment的内容会叠加到前面fragment上面
多次点击切换同一个fragment时会报错,java.lang.IllegalStateException: Fragment already added:
说是fragment已经被添加,那应该是一个fragment添加一次,就在内存中被保存起来了,继续添加其他的fragment不会影响之前的fragment在其他内存中的状态
所以要加个判断fragment.Added,如果已经添加过,那就只要调用fragment.show就好了,同时使用hide方法把显示的fragment隐藏起来
最后修改成这样
private var targetFragment:BaseFragment?=null private var currentFragment:BaseFragment?=null override fun initData() { bottomBar.setOnTabSelectListener { //it即是tab的id // println(it) val transAction = supportFragmentManager.beginTransaction() //transAction.replace(R.id.contentContainer,FragmentManage.fragmentManage.getFragment(it)!!,it.toString()) targetFragment=FragmentManage.fragmentManage.getFragment(it)!! if(targetFragment!!.isAdded) { transAction.hide(currentFragment!!) transAction.show(targetFragment!!) transAction.commit() currentFragment=targetFragment }else{ if(currentFragment!=null) { transAction.hide(currentFragment!!) } transAction.add(R.id.contentContainer, targetFragment!!) transAction.commit() currentFragment= targetFragment!! } } }
这样就可以了。更详细的内容可以参考这个Android解决多个fragment来回切换时布局重新实例化问题
设置状态栏透明 statusBar
状态栏指的就是这个吧
参考的是这篇文章android透明状态栏——你要的只是几个方法
在android 4.4之后使用下面这段代码可以实现(我这模拟器android版本是5.1)
fun makeStatusBarTransparent(activity: Activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } var window: Window = activity.getWindow() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); var option:Int = window.getDecorView().getSystemUiVisibility() or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN window.getDecorView().setSystemUiVisibility(option); window.setStatusBarColor(Color.TRANSPARENT); } else { window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } }
效果
有个问题,我这里设置了NoActionbar主题AppTheme,如果在AppTheme中设置别的actionbar样式,那actionbar的位置是不会变的。但是如果是在布局文件中自定义的Actionbar(我试的是toolbar),那Actionbar就会和状态栏重合。
为了理解这个程序先补充一点知识
·DecorView(activity窗口的根视图)
DecorView是PhoneWindow的一个实例,分为两个部分Actionbar和ContentParent,我们在activity通过setContentView设置的是ContentParent,通过getWindow获得PhoneWindow对象
一些方法
window.getDecorView()获得它的DecorView
window.getDecorView.getWindowVisibleDisplayFrame(rect)获得显示区域尺寸信息。据说这样不包含状态栏,但是我模拟器上测试状态栏也包含进去了,跟windowManager.defaultDisplay.getRectSize(rect2)返回结果是一样
那为了获得状态栏的高度可以使用
var resourceId=resources.getIdentifier("status_bar_height","dimen","android")
var height=resources.getDimensionPixelSize(resourceId)
SystemUI Flag
改变状态栏颜色
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.KITKAT){ return }else{ var window=this.window window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) window.statusBarColor=Color.BLUE }