XML
文件
<com.gallery20.app.MyLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_green_light"
android:gravity="center"
android:orientation="vertical">
<com.gallery20.app.MyView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@android:color/holo_blue_light"/>
<com.gallery20.app.MyButton
android:id="@+id/my_btn"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@android:color/holo_red_light"/>
</com.gallery20.app.MyLinearLayout>
Activity
文件
const val TAG = "Yang"
class MainActivity : AppCompatActivity() {
private var mViewGroup : LinearLayout ?= null
private var mButton : Button ?= null
private var mView : View?= null
private var mMainHandler = Handler(Looper.getMainLooper())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mViewGroup = findViewById(R.id.my_ll)
mButton = findViewById(R.id.my_btn)
mView = findViewById(R.id.my_view)
mMainHandler.postDelayed({
Log.i("yang", "")
mView?.requestLayout()
}, 2000)
}
}
自定义View
代码
class MyButton(context: Context, attrs: AttributeSet) : AppCompatButton(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
Log.d(TAG, "MyButton onMeasure")
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
Log.d(TAG, "MyButton onLayout")
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
Log.d(TAG, "MyButton onDraw")
}
}
class MyLinearLayout(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
Log.d(TAG, "MyLinearLayout onMeasure")
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
Log.d(TAG, "MyLinearLayout onLayout")
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
Log.d(TAG, "MyLinearLayout onDraw")
}
}
class MyView(context: Context, attrs: AttributeSet) : View(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
Log.d(TAG, "MyView onMeasure")
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
Log.d(TAG, "MyView onLayout")
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
Log.d(TAG, "MyView onDraw")
}
fun updateView() {
val layoutParams = layoutParams
layoutParams.height += 100
}
}
requestLayout()
方法
mMainHandler.postDelayed({
Log.i("yang", "")
mView?.requestLayout()
}, 2000)
2024-06-09 08:42:24.081 4438-4438 yang I <-------requestLayout------->
2024-06-09 08:42:24.089 4438-4438 Yang D MyView onMeasure
2024-06-09 08:42:24.089 4438-4438 Yang D MyLinearLayout onMeasure
2024-06-09 08:42:24.089 4438-4438 Yang D MyView onLayout
2024-06-09 08:42:24.089 4438-4438 Yang D MyLinearLayout onLayout
2024-06-09 08:42:24.089 4438-4438 Yang D MyLinearLayout onDraw
2024-06-09 08:42:24.089 4438-4438 Yang D MyView onDraw
mMainHandler.postDelayed({
Log.i("yang", "")
mView?.updateView()
mView?.requestLayout()
}, 2000)
2024-06-09 08:50:21.373 4943-4943 yang I <-------requestLayout------->
2024-06-09 08:50:21.376 4943-4943 Yang D MyView onMeasure
2024-06-09 08:50:21.376 4943-4943 Yang D MyLinearLayout onMeasure
2024-06-09 08:50:21.376 4943-4943 Yang D MyView onLayout
2024-06-09 08:50:21.376 4943-4943 Yang D MyButton onLayout
2024-06-09 08:50:21.376 4943-4943 Yang D MyLinearLayout onLayout
2024-06-09 08:50:21.377 4943-4943 Yang D MyLinearLayout onDraw
2024-06-09 08:50:21.377 4943-4943 Yang D MyView onDraw
2024-06-09 08:50:21.384 4943-4943 Yang D MyView onDraw
forceLayout()
方法
mMainHandler.postDelayed({
Log.i("yang", "")
mView?.forceLayout()
}, 2000)
没有改变View的可见性、改变View的大小或位置,无任何Log输出
mMainHandler.postDelayed({
Log.i("yang", "")
mView?.updateView()
mView?.forceLayout()
}, 2000)
2024-06-09 08:57:53.732 5625-5625 yang I <-------forceLayout------->
2024-06-09 08:57:53.741 5625-5625 Yang D MyView onMeasure
2024-06-09 08:57:53.741 5625-5625 Yang D MyLinearLayout onMeasure
2024-06-09 08:57:53.741 5625-5625 Yang D MyView onLayout
2024-06-09 08:57:53.741 5625-5625 Yang D MyButton onLayout
2024-06-09 08:57:53.741 5625-5625 Yang D MyLinearLayout onLayout
2024-06-09 08:57:53.741 5625-5625 Yang D MyLinearLayout onDraw
2024-06-09 08:57:53.742 5625-5625 Yang D MyView onDraw
2024-06-09 08:57:53.748 5625-5625 Yang D MyView onDraw
总结
forceLayout()
和requestLayout()
的主要区别在于影响范围:forceLayout()
将当前View
标记为需要重新布局,但并不会立即触发布局过程。只有在下次draw(Canvas)
方法被调用时,才会对其进行重新布局requestLayout()
将当前View
以及其所有父View
标记为需要重新布局。并不意味兄弟View
也会被重新测量和布局。只有当这个View
的父View
的布局参数(如宽度、高度、权重等)发生变化,或者父View
的onLayout()
方法被重写改变子View
的布局方式时,兄弟View
才可能会被重新测量和布局- 仅调用
forceLayout()
或requestLayout()
并不会影响到其兄弟View
的测量和布局,除非父View
的布局参数或布局方式发生了变化