ITPub博客

首页 > 移动开发 > ANDROID > 从动态缩放自定义View,聊聊为什么不要把问题复杂化

从动态缩放自定义View,聊聊为什么不要把问题复杂化

原创 ANDROID 作者:山有木xi 时间:2025-08-27 18:04:43 0 删除 编辑

前言

我的项目中,关于动态修改 View 的大小的技术方案进阶之路,在之前的文章中其实有讲到,强烈建议有兴趣的小伙伴可以去看看《 产品需求驱动下的技术演进:动态缩放View 的不同方案 》,因为这是我们团队历经 2-3 年的技术迭代过程。

 

今天其实想聊聊在我们上线的方案之后,其实还有更简单也更有效的方案,在我们走过的那些路中有很多问题其实我们把问题想的太复杂了,用的方法也太复杂了,如果 “跳出三界之外”,再回过头看看,或许有更简单有效的做法。

 

回顾一下之前的方案

在之前的方案中,我们经历了从生成 ImageView 到手动处理所有的子 view ,以及遇到的性能问题、边界值计算问题、清晰度问题、视觉和真实大小不一致带来的问题等等各种问题,有相同想法的可以去看看。

 

把问题简单化

缩放的本质其实就是修改原本定义在 layout 中的数值,我们所做的操作其实也就是围绕着这一块做的,而我们的 xml 中的布局,在一开始就有默认的大小,也就是系统自己会处理好所有事情,那为什么我们不能依靠系统处理好呢?

 

在我们的布局中,一般来说布局文件长这样

<LinearLayout
    android:layout_width="@dimen/container_width"
    android:layout_height="@dimen/container_height"
    android:padding="@dimen/container_padding">
    
    <TextView
        android:layout_width="@dimen/child_width"
        android:layout_height="@dimen/child_height"
        android:margin="@dimen/child_margin"/>
</LinearLayout>

 

宽度、大小、字体都用 dimens 管理,那如果我们直接修改 dimens 的值或者直接替换成套的 dimens ,是不是就可以最简单的解决问题?

在res/values 、 res/values-swxxxdp (或自定义后缀,如 values-size1 、 values-size2 )下创建多套 dimens.xml ,每套文件中用相同的 dimen 名称定义不同的尺寸值,对应 10 种缩放比例。
例如:

values-size1/dimens.xml(最小尺寸):
<<dimen name="container_width">100dp</</dimen>
<<dimen name="child_width">80dp</</dimen>
values-size2/dimens.xml(次小尺寸):
<<dimen name="container_width">120dp</</dimen>
<<dimen name="child_width">96dp</</dimen>
...(依此类推定义 10 套)

 

然后在使用的时候切换即可

val config = Configuration(resources.configuration)
// 这里需要自定义 "qualifier"(但非标准 swNNNdp/语言/方向等很难生效)
val newContext = createConfigurationContext(config)
val view = LayoutInflater.from(newContext).inflate(R.layout.my_layout, null)

 

需要注意的是,采用这个方案切换后需要重新执行 infalte 的一套流程,单纯靠 requestLayout 是没有办法刷新触发新的 dimens 的

 

这个方案自然也有弊端,所有的 “可能性”都需要提前预设,例如原本的缩放比例是 1-100% 自由缩放,如果采用在这个方案下就可能需要提前预设 100 套方案,那是不是应该修改相关的产品测的策略,将进度变成以每 10% 为一个可调整区间,这样只需要预设 10 套 dimens 即可

 

进阶的方案

动态切换 dimens 的思路是完全正确的,但是如果我们直接修改 dimens 可能会带来一些意想不到的问题:

只能按系统 qualifier ( sw600dp 、 values-xxhdpi )自动匹配,很难在运行时手动切换。

并且切换时需要 模拟系统配置变更,可能导致 Activity 重建甚至全局刷新。

 

那既然知道问题,咱们就解决问题,首先在 dimens 的方案上,继续定义多套 dimens ,然后在主题中定义不同的 style

<!-- 默认尺寸 -->
<style name="AppTheme.Size1" parent="Theme.AppCompat.Light">
    <item name="containerWidth">@dimen/size1_container_width</item>
    <item name="textSize">@dimen/size1_text_size</item>
</style>
 
<!-- 第二套尺寸 -->
<style name="AppTheme.Size2" parent="Theme.AppCompat.Light">
    <item name="containerWidth">@dimen/size2_container_width</item>
    <item name="textSize">@dimen/size2_text_size</item>
</style>

 

然后在布局中不直接写 @dimen/... ,而是写 ?attr/textSize ,这样才会跟随 theme 切换

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="?attr/textSize"/>

 

在自定义 view 中这样切换

context.setTheme(R.style.AppTheme_Size2)
LayoutInflater.from(context).inflate(R.layout.my_custom_view, this, true)

切换后重新 inflate ,布局里的所有 ?attr 会自动应用新 theme 对应的尺寸。

 

让 AI参与进来

到这里,想硬扯一句 AI ,因为在处理这个方案的时候就在想,这个方案需要大量的预设,这是“笨办法”,那现在我们有了 AI ,其实可以通过 AI 代替我们做这些繁琐复杂的事情,比如说直接通过 Trae 让他帮我们生成 100 套预设,而我们也就有更多的精力去用在更值得我们去思考的地方。

 

想想

技术成长的过程,其实就是不断折腾,不断试错。很多时候我们追求 “优雅”和“通用”,但过度设计往往带来新的复杂性。

由繁至简的过程,其实是一种不一样的体验, “笨办法”或许有时候才是真正聪明的做法,真正的经验往往不是“多高明的技巧”,而是什么时候该停下折腾,选择最合适的平衡点。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917874/viewspace-3094344/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle OCA(Java),IBM高级工程师认证,中国软件行业人才(高级c语言),高级Android工程师,对数据库并发与性能调优也有一定了解

注册时间:2019-04-25

  • 博文量
    147
  • 访问量
    390751