Augustus
Augustus

Reputation: 385

Getting imageview size for Bitmap creation

I am a programmer with a Windows background and I am new to Java and Android stuff.

I want to create a widget (not an app) which displays a chart. After a long research I know I can do this with Canvas, imageviews and Bitmaps. The canvas which I paint on should be the same as the Widget Size.

How do I know the widget size (or imageview size) so that I can supply it to the function?

Bitmap.createBitmap(width_xx, height_yy, Config.ARGB_8888);

Code Snippet:

In the timer run method:

@Override
public void run() {
    Bitmap bitmap = Bitmap.createBitmap(??, ??, Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);

    // Create a new paint
    Paint p = new Paint();
    p.setAntiAlias(true);
    p.setStrokeWidth(1);

    // Draw circle
    // Here I can use the width and height to scale the circle
    canvas.drawCircle(50, 50, 7, p);
    remoteViews.setImageViewBitmap(R.id.imageView, bitmap);

Upvotes: 17

Views: 3720

Answers (7)

Samuil Yanovski
Samuil Yanovski

Reputation: 2867

I've not worked on Widgets, but I have some experience getting ImageView's size.

Here is some code I use:

public class ViewSizes {
    public int width;
    public int height;

    public boolean isEmpty() {
        boolean result = false;
        if (0 >= width || 0 >= height) {
            result = true;
        }
        return result;
    }
}

That's just a dummy class containing the size parameters.

public static ViewSizes getSizes(View view) {
        ViewSizes sizes = new ViewSizes();
        sizes.width = view.getWidth();
        sizes.height = view.getHeight();

        if (sizes.isEmpty()) {
            LayoutParams params = view.getLayoutParams();
            if (null != params) {
                int widthSpec = View.MeasureSpec.makeMeasureSpec(params.width, View.MeasureSpec.AT_MOST);
                int heightSpec = View.MeasureSpec.makeMeasureSpec(params.height, View.MeasureSpec.AT_MOST);
                view.measure(widthSpec, heightSpec);
            }

            sizes.width = view.getMeasuredWidth();
            sizes.height = view.getMeasuredHeight();
        }

        return sizes;
    }

This method calculates the width forcing a measure cycle if such has not already happened.

public static boolean loadPhoto(ImageView view, String url, float aspectRatio) {
    boolean processed = false;
    ViewSizes sizes = ViewsUtils.getSizes(view);

    if (!sizes.isEmpty()) {
        int width = sizes.width - 2;
        int height = sizes.height - 2;
        if (ASPECT_RATIO_UNDEFINED != aspectRatio) {
            if (height * aspectRatio > width) {
                height = (int) (width / aspectRatio);
            } else if (height * aspectRatio < width) {
                width = (int) (height * aspectRatio);
            }
        }

        // Do you bitmap processing here

        processed = true;
    }

    return processed;
}

This one is probably useless for you. I give just as an example - I have an ImageView and image URL, which should be parametrized with image and height.

public class PhotoLayoutListener implements OnGlobalLayoutListener {
    private ImageView view;
    private String url;
    private float aspectRatio;


    public PhotoLayoutListener(ImageView view, String url, float aspectRatio) {
        this.view = view;
        this.url = url;
        this.aspectRatio = aspectRatio;
    }

    boolean handled = false;
    @Override
    public void onGlobalLayout() {
        if (!handled) {
            PhotoUtils.loadPhoto(view, url, aspectRatio);
            handled = true;
        }

        ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                removeLayoutListenerPre16(viewTreeObserver, this);
            } else {
                removeLayoutListenerPost16(viewTreeObserver, this);
            }
        }
    }

    @SuppressWarnings("deprecation")
    private void removeLayoutListenerPre16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
        observer.removeGlobalOnLayoutListener(listener);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void removeLayoutListenerPost16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
        observer.removeOnGlobalLayoutListener(listener);
    }
}

This is just a layout listener - I want to process the image loading once the layout phase has finished.

public static void setImage(ImageView view, String url, boolean forceLayoutLoading, float aspectRatio) {
    if (null != view && null != url) {
        final ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();

        if (forceLayoutLoading || !PhotoUtils.loadPhoto(view, url, aspectRatio)) {
            if (viewTreeObserver.isAlive()) {
                viewTreeObserver.addOnGlobalLayoutListener(new PhotoLayoutListener(view, url, aspectRatio));
            }
        }
    }
}

This is the method I actually call. I give it the view and URL. The methods takes care of loading - if it can determine the view's size it starts loading immediately. Otherwise it just assigns a layout listener and start the loading process once the layout is finished.

You could strip away some parameters - forceLoading / aspectRatio should be irrelevant for you. After that change the PhotoUtils.loadPhoto method in order to create the bitmap with the width / height it has calculated.

Upvotes: 0

Jignesh Shah
Jignesh Shah

Reputation: 649

Have a look at the method:

public void onAppWidgetOptionsChanged (Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)

It will be called each time you start/resize the widget.

Getting the widget width/height can be done as follows:

newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)

Upvotes: 2

Wasim Ahmed
Wasim Ahmed

Reputation: 356

You can create a custom widget and set the size of wight on its onMeasure() method. And also save the size at that time so that you can use it further for image creation...

Upvotes: 0

user3317993
user3317993

Reputation: 111

You can use this

Bitmap image1, image2;

Bitmap bitmap = Bitmap.createBitmap(image1.getWidth(), image1.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);

Upvotes: 0

XXX
XXX

Reputation: 333

I am currently using this:

private void run() {

    int width = 400, height = 400;

    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bitmap);

    Paint p = new Paint();
    p.setColor(Color.WHITE);
    p.setStyle(Paint.Style.STROKE);
    p.setStrokeWidth(1);
    p.setAntiAlias(true);

    c.drawCircle(width/2, height/2, radius, p);

    remoteViews.setImageViewBitmap(R.id.imageView, bitmap);

    ComponentName clockWidget = new ComponentName(context,
    Clock_22_analog.class);
    AppWidgetManager appWidgetManager = AppWidgetManager
    .getInstance(context);
    appWidgetManager.updateAppWidget(clockWidget, remoteViews);
}

Upvotes: 0

youssoua
youssoua

Reputation: 802

Like Julian told us, you can get them like that with a bitmap of your image:

int width = bitmap.getWidth();
int height = bitmap.getHeight();

Upvotes: -2

Christian G&#246;llner
Christian G&#246;llner

Reputation: 5818

From what I've learnt, you can only calculate widget dimensions on Android 4.1+. When on a lower API, you'll have to use static dimensions. About widget dimensions: App Widget Design Guidelines

int w = DEFAULT_WIDTH, h = DEFAULT_HEIGHT;

if ( Build.VERSION.SDK_INT >= 16 ) {
    Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);

    int maxW = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
    int maxH = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);

    int minW = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
    int minH = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);

    if ( context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ) {
        w = maxW;
        h = minH;
    } else {
        w = minW;
        h = maxH;
    }
}

Upvotes: 2

Related Questions