【问题标题】:Getting imageview size for Bitmap creation获取用于创建位图的图像视图大小
【发布时间】:2012-03-16 09:11:25
【问题描述】:

我是一名具有 Windows 背景的程序员,我是 Java 和 Android 方面的新手。

我想创建一个显示图表的小部件(不是应用程序)。经过长时间的研究,我知道我可以用画布、图像视图和位图来做到这一点。我画的画布应该和 Widget Size 一样。

我如何知道小部件大小(或 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);

【问题讨论】:

  • *facepalm*,App Widget。两个词合在一起,需要对这个问题的答案,而这与你对任何一个的答案都没有任何关系。
  • 我目前遇到了同样的问题。如果您找到了问题的解决方案,最好将其发布在这里。

标签: android android-widget android-imageview android-canvas


【解决方案1】:

据我所知,您只能在 Android 4.1+ 上计算小部件尺寸。 在较低的 API 上,您必须使用静态维度。 关于小部件尺寸: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;
    }
}

【讨论】:

  • 完美运行。感谢指出需要查看方向。但是,当值被命名为“MIN”和“MAX”时,为什么方向很重要?
【解决方案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)

【讨论】:

    【解决方案3】:

    我目前正在使用这个:

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

    【讨论】:

    • 解释一下。例如,想法/要点是什么?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
    【解决方案4】:

    你可以用这个

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

    【讨论】:

      【解决方案5】:

      您可以创建一个自定义小部件并在其 onMeasure() 方法上设置 wight 的大小。并且还保存当时的大小,以便您可以进一步使用它来创建图像...

      【讨论】:

        【解决方案6】:

        我没有在小部件上工作过,但我有一些获得 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 方法以创建具有计算出的宽度/高度的位图。

        【讨论】:

        • 小部件在远程视图中运行,所以这个方法不起作用
        【解决方案7】:

        这是一个你应该去的教程。一切都清楚地给出:Developing Android Home Screen Widgets

        【讨论】:

        • 感谢本教程,它提供了很好的信息,但遗憾的是没有回答我的问题,我希望我的图表始终填充小部件大小,无论它具有哪种尺寸或它具有哪个方向
        【解决方案8】:

        就像Julian told us,您可以通过图像的位图来获得它们:

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

        【讨论】:

        • 看他的示例代码。他想创建位图,并创建将使用它的 Canvas。我建议他等到 .onDraw() 提供 Canvas。
        • 是的,Julian 是对的,位图需要根据 Widget/imageview 的大小来创建,我希望类似,int width = widget.getWidth();或 int width = imageview.getWidth();
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-10
        • 2012-02-17
        • 1970-01-01
        • 2017-03-08
        • 1970-01-01
        相关资源
        最近更新 更多