Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - scaling a viewgroup (layout) at runtime

Tags:

android

I've got a bunch of tiles that make up a single image, that are rendered on request (by what's portion of the total image is visible on screen). The composite image is significantly larger than the screen. Each tile is positioned tightly next to its neighbors to create the illusion of a single image (the single image, if not tiled, would be too large and have OOM errors).

These are ImageViews inside a FrameLayout, positioned with top/leftMargin.

Targetting API 2.2 / SDK 8

I'm trying to scale the total image in response to user events (button presses, pinch, etc).

Apparently setScale isn't available until API 11. I tried using canvas.scale in onDraw of the FrameLayout with setWillNotDraw(false), and onDraw is being called, but no scaling is being applied (I assume because the layout itself doesn't have any graphic information? I had assumed it'd render it's children as well, but I guess not unless I'm doing something wrong here also).

I guess I could iterate through each tile and scale it independently, but would need to reposition each one as well, each time.

I have to think there's a way to scale a parent View (ViewGroup?) so that all of its children are also scaled (like every other language responsible for managing a GUI). What am I missing?

Thanks

like image 977
momo Avatar asked Jan 22 '12 11:01

momo


1 Answers

For reference, the approach mentioned above (using onDraw of a parent ViewGroup) does in fact work. I had been using canvas.save() before the transformation and canvas.restore() after (based on some examples), which was incorrect.

The following is a generic subclass of FrameLayout that will scale it's children

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);
    }

}
like image 111
momo Avatar answered Nov 12 '22 11:11

momo