- 如何在onResume方法中获取到View的宽高?
有两种方式:post和addOnGlobalLayoutListener
override fun onResume() {
super.onResume()
Log.e("onresume",tabBottom.width.toString()+"--"+tabBottom.height.toString())
//view.post之所以能够拿到宽高,是因为在绘制之前,会将获取宽高的任务放到Handler的消息队列,等到View的绘制结束之后,便会执行。
tabBottom.post {
Log.e("onresume:post",tabBottom.width.toString()+"--"+tabBottom.height.toString())
}
tabBottom.viewTreeObserver.addOnGlobalLayoutListener {
tabBottom.viewTreeObserver.removeOnGlobalLayoutListener{this}//防止被多次绘制
Log.e("onresume:viewTreeObserver",tabBottom.width.toString()+"--"+tabBottom.height.toString())
}
}
-
为什么无法在onCreate或onResume方法中获取到View的宽高?
因为这个时候view的绘制流程还没有开始。要拿到View的宽高,那么View的绘制流程(measure—layout—draw)至少要完成measure阶段。
有看过onCreate方法源码的同学应该知道:- onCreate流程中的setContentView只是解析了xml,初始化了DecorView,创建了各个控件的对象;即将xml中的 转化为一个TextView对象。并没有启动View的绘制流程。
- 调用performResumeActivity, 该方法中r.activity.performResume(r.startsNotResumed, reason);会调用Activity的onResume方法。执行完Activity的onResume后调用了wm.addView(decor, l);,到这里,开始将此前创建的DecorView添加到视图中,也就是在这之后才开始布局的绘制流程,真正开始是在ViewRootImpl类里面的。
-
子线程中真的不能更新UI吗?
各位读者可以参考这篇博客:https://www.jianshu.com/p/fbd748a533e1 -
接下来,我们来认识下ViewRootImpl类的相关功能:
-
View的三大流程主要涉及到的核心类,笔者列在下面了:
-
手势分发
具体逻辑可以参考靠=笔者之前写的博客:https://blog.csdn.net/qq_36828822/article/details/103658941 -
如何获取栈顶的activity以及监听activity前后台切换
总所周知:Android的sdk并没有提供相关的api。那么,我们如何设计一个管理任务栈的工具类呢?
package com.example.myapplication.demo
import android.app.Activity
import android.app.Application
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle
import java.lang.ref.WeakReference
class ActivityManager private constructor() {
private val activityRefs = ArrayList<WeakReference<Activity>>()
private val frontbackCallback = ArrayList<FrontBackCallback>()
private var activityStartCount =0
private var front = true
fun init(application: Application){
application.registerActivityLifecycleCallbacks()
}
inner class InnerActivityLifecycleCallbacks:ActivityLifecycleCallbacks{
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
activityRefs.add(WeakReference(activity))
}
override fun onActivityStarted(activity: Activity) {
activityStartCount++
//activityStartCount>0 说明应用处于可见状态,也就是应用在前台
//!front 之前是不是在后台
if(!front && activityStartCount>0){
front = true
onFrontBackChanged(front)
}
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
activityStartCount--;
if(activityStartCount<=0&&front){
front = false
onFrontBackChanged(front)
}
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityDestroyed(activity: Activity) {
for (activityRef in activityRefs){
if(activityRef!=null && activityRef.get()==activity){
activityRefs.remove(activityRef)
break
}
}
}
}
private fun onFrontBackChanged(front: Boolean){
for (callback in frontbackCallback){
callback.onChanged(front)
}
}
val topActivity:Activity?
get() {
if (activityRefs.size<=0){
return null
}else{
return activityRefs[activityRefs.size-1].get()
}
return null
}
fun addFrontBackCallback(callback: FrontBackCallback){
frontbackCallback.add(callback)
}
fun removeFrontBackCallback(callback: FrontBackCallback){
frontbackCallback.remove(callback)
}
interface FrontBackCallback {
fun onChanged(front: Boolean)
}
}