如何在Android中实现带动画的对话框旋转并解决内容裁剪问题
问题原因
View的rotation属性仅触发绘制层面的变换,不会修改视图本身的测量宽高,对话框的窗口大小会沿用竖屏状态下的测量结果,旋转后内容宽高超出窗口裁剪区域就会出现被截断的问题。
解决方案
方案1:修改对话框窗口配置(推荐)
创建对话框时调整Window属性,让窗口占满全屏、背景透明且不裁剪子内容,从根源避免裁剪问题:
// 对话框初始化阶段添加配置 settingsDialog.window?.apply { // 背景设为透明,去掉系统默认对话框边距 setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // 窗口宽高占满全屏 setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT) // 关闭裁剪 val decorView = decorView as ViewGroup decorView.clipChildren = false decorView.clipToPadding = false findViewById<ViewGroup>(android.R.id.content)?.apply { clipChildren = false clipToPadding = false } }
方案2:修改旋转逻辑,添加平移补偿
旋转视图时同步计算平移量,保证旋转后内容居中,不会超出原窗口裁剪范围:
private fun rotateView(view: View?, angle: Float) { if (view == null) return view.animate().cancel() view.doOnPreDraw { val width = it.width.toFloat() val height = it.height.toFloat() val targetRotation = (it.rotation + angle) % 360 // 旋转90/270度时计算平移偏移,修正位置 val offsetX = if (targetRotation % 180 == 90f) (height - width) / 2 else 0f val offsetY = if (targetRotation % 180 == 90f) (width - height) / 2 else 0f view.animate() .rotationBy(angle) .translationX(offsetX) .translationY(offsetY) .setDuration(400) .setInterpolator(LinearInterpolator()) .start() } }
方案3:动态调整根布局宽高
横竖屏切换时交换根布局的宽高参数,让测量尺寸适配旋转后的内容:
override fun onOrientationChange(orientation: Int) { val root = settingsDialog.findViewById<ViewGroup>(R.id.root) ?: return val lp = root.layoutParams if (orientation % 180 == 90) { // 横屏状态交换宽高 val temp = lp.width lp.width = lp.height lp.height = temp } else { // 竖屏状态恢复原始宽高配置 lp.width = ViewGroup.LayoutParams.MATCH_PARENT lp.height = ViewGroup.LayoutParams.WRAP_CONTENT } root.layoutParams = lp rotateView(root, iconRotation) }
内容的提问来源于stack exchange,提问作者Shyam Singh
相关产品推荐
相关产品推荐

