获取ImageView的尺寸以创建Bitmap

17

我是一名有Windows背景的程序员,新接触Java和Android开发。

我想创建一个小部件(不是应用程序),用来显示图表。经过长时间的研究,我知道可以使用Canvas、ImageView和Bitmap来实现这个功能。我需要在画布上绘制的Canvas大小应该与小部件大小相同。

如何获取小部件大小(或者ImageView大小),以便我可以将其传递给函数中呢?

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

代码片段:

在计时器运行的方法中:

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

*扶额*,一个应用小部件。这两个词汇在一起,需要回答一个与任何一个词汇的答案都没有关系的问题。 - Julian Fondren
7个回答

2

看一下这个方法:

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

每次启动/调整小部件时,它都将被调用。
可以按以下方式获取小部件的宽度/高度:
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)

2

据我所知,只有在Android 4.1及以上版本才能计算小部件的尺寸。在低版本上,您必须使用静态尺寸。关于小部件尺寸:应用程序小部件设计指南

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

完美运作。感谢指出需要考虑方向的必要性。但是,当数值被命名为“MIN”和“MAX”时,为什么方向会有影响呢? - GaryAmundson

0

我一直没在Widgets上工作过,但是我有一些获取ImageView尺寸的经验。

这是我使用的一些代码:

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

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

那只是一个包含大小参数的虚拟类。
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;
    }

该方法计算宽度,如果尚未发生测量周期,则强制进行测量。

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

这个可能对你没什么用,我只是举个例子 - 我有一个ImageView和一个图片URL,需要将其参数化为图片和高度。

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

这只是一个布局监听器 - 我想在布局阶段完成后处理图像加载。

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

这是我实际调用的方法。我给它视图和URL。如果该方法能够确定视图的大小,它会立即开始加载。否则,它只分配一个布局监听器,并在布局完成后启动加载过程。
你可以剥离一些参数 - forceLoading / aspectRatio 对你来说应该是无关紧要的。在更改PhotoUtils.loadPhoto方法之后,它将根据计算出的宽度/高度创建位图。

2
小部件在远程视图中运行,因此这种方法不起作用。 - Robin Davies

0

我目前正在使用这个:

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

需要解释一下。例如,什么是想法/要点?请通过编辑(更改)您的答案进行回复,而不是在此处进行评论(不带“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的)。 - Peter Mortensen

0

你可以使用这个

Bitmap image1, image2;

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

0

您可以创建一个自定义小部件,并在其onMeasure()方法中设置宽度大小。同时,在那个时候保存大小,以便您可以进一步用于图像创建...


-2

2
看看他的示例代码。他想要创建位图,并创建将使用它的画布。我建议他等到.onDraw()提供画布。 - Julian Fondren
是的,Julian 是正确的,位图需要根据 Widget/imageview 的大小创建,我期望像这样的东西,int width = widget.getWidth(); 或 int width = imageview.getWidth(); - Augustus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接