【问题标题】:Android - scaling a viewgroup (layout) at runtimeAndroid - 在运行时缩放视图组(布局)
【发布时间】:2026-01-30 02:50:01
【问题描述】:

我有一堆组成一个图像的图块,这些图块是根据请求渲染的(总图像的一部分在屏幕上可见)。合成图像明显大于屏幕。每个图块都紧挨着它的邻居放置,以创建单个图像的错觉(单个图像,如果不分块,将太大并出现 OOM 错误)。

这些是 FrameLayout 内的 ImageView,使用 top/leftMargin 定位。

定位 API 2.2 / SDK 8

我正在尝试缩放整个图像以响应用户事件(按钮按下、捏合等)。

显然 setScale 在 API 11 之前不可用。我尝试在带有 setWillNotDraw(false) 的 FrameLayout 的 onDraw 中使用 canvas.scale,并且正在调用 onDraw,但没有应用缩放(我假设是因为布局本身没有'没有任何图形信息?我以为它也会渲染它的孩子,但我想除非我在这里也做错了什么)。

我想我可以遍历每个图块并独立缩放它,但每次都需要重新定位每个图块。

我不得不认为有一种方法可以缩放父视图(ViewGroup?),以便它的所有子视图也可以缩放(就像负责管理 GUI 的所有其他语言一样)。我错过了什么?

谢谢

【问题讨论】:

    标签: android


    【解决方案1】:

    作为参考,上面提到的方法(使用父 ViewGroup 的 onDraw)确实有效。我在转换之前一直使用 canvas.save(),之后使用 canvas.restore()(基于一些示例),这是不正确的。

    以下是 FrameLayout 的通用子类,将缩放其子类

    package com.whatever.layouts;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.widget.FrameLayout;
    
    public class ScalingFrameLayout extends FrameLayout {
    
        private float scale = 1;
    
        public ScalingFrameLayout(Context context) {
            super(context);
            setWillNotDraw(false);
        }
    
        public void setScale(float factor){
            scale = factor;
            invalidate();
        }
        public float getScale(){
            return scale;
        }
    
        @Override
        public void onDraw(Canvas canvas){
            canvas.scale(scale, scale);
            super.onDraw(canvas);
        }
    
    }
    

    【讨论】:

    • 哇,真是大开眼界,谢谢!但我想这是有道理的(知道答案更容易得出结论;))。我们不想保存画布并将其恢复到以前的状态,因为这是我们想要的更改,直接在同一层上进行。再一次,干杯:)
    • 关于 canvas.save() 和 canvas.restore(),我一直在做同样的事情。事实上,没有他们,它是有效的。那么你能告诉我为什么他们在android development page 中放置这些行吗?
    • @AsafK 我不知道。
    • 太棒了!这是自动缩放View Group类型的最佳解决方案
    • @AsafK 只是为了澄清一下:目的是你先做canvas.save(); 然后canvas.scale(scale, scale);,然后做任何你需要的绘图操作,最后是canvas.restore();。这样,只有您打算影响的那些绘制操作会受到变换的影响。如果例如超类或父类打算在画布上做一些进一步的绘图,您不会无意中将缩放操作泄露给那些人。您在保存和恢复之间所做的绘图会受到比例的影响,调用 restore 不会追溯适用于该比例,仅适用于之后的绘图