带圆角的 AppWidget 图像

Posted

技术标签:

【中文标题】带圆角的 AppWidget 图像【英文标题】:AppWidget image with rounded corners 【发布时间】:2014-11-10 17:15:34 【问题描述】:

因此,我在应用程序的主布局中通过动画显示给用户的各种视图来动态地在应用程序中创建图像。

目前我正在一个 RelativeLayout 中生成我的场景,将布局的图像作为位图,然后将位图保存到 SD 以供 appwidget 通过 uri 访问。

这一切都很好,但是...在为 appwidget 图像创建圆角的尝试中,我尝试使用我发现的这两个 sn-ps here.

我的问题:

这个方法会生成一个drawable(如果显示为drawable,它的圆角看起来很完美)但是我需要将这些透明角导出为图像文件。下面 CustomView 中的 drawToBitmap 方法,确实生成了位图图像,但是边角是完整的和方形的。

/**
 * shows a bitmap as if it had rounded corners. based on :
 * http://rahulswackyworld.blogspot.co.il/2013/04/android-drawables-with-rounded_7.html
 */
public class RoundedCornersDrawable extends BitmapDrawable 

    private final BitmapShader bitmapShader;
    private final Paint p;
    private final RectF rect;
    private final float borderRadius;

    public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float     borderRadius) 
        super(resources, bitmap);
        bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP,     Shader.TileMode.CLAMP);
        final Bitmap b = getBitmap();
        p = getPaint();
        p.setAntiAlias(true);
        p.setShader(bitmapShader);
        final int w = b.getWidth(), h = b.getHeight();
        rect = new RectF(0, 0, w, h);
        this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
    

    @Override
    public void draw(final Canvas canvas) 
        canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
    

public class CustomView extends ImageView 
    private FrameLayout mMainContainer;
    private boolean mIsDirty=false;

    // TODO for each change of views/content, set mIsDirty to true and call invalidate

    @Override
    protected void onDraw(final Canvas canvas) 
        if (mIsDirty) 
            mIsDirty = false;
            drawContent();
            return;
        
        super.onDraw(canvas);
    

    /**
     * draws the view's content to a bitmap. code based on :
     * http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
     */
    public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) 
        // Create a new bitmap and a new canvas using that bitmap
        final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bmp);
        viewToDrawFrom.setDrawingCacheEnabled(true);
        // Supply measurements
        viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(),     MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
        // Apply the measures so the layout would resize before drawing.
        viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(),    viewToDrawFrom.getMeasuredHeight());
        // and now the bmp object will actually contain the requested layout
        canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
        return bmp;
     

    private void drawContent() 
        if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
            return;
        final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
        final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(),     bitmap, 15);
        setImageDrawable(drawable);
    

我了解位图不包含在图像中具有透明圆角所需的 alpha 信息, 所以我尝试像这样将文件保存为PNG;

RCD_test 是一个 RoundedCornersDrawable

Bitmap bitmap = RCD_test.getBitmap();
bitmap.setHasAlpha(true);
OutputStream stream = new          
FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/test/screenshottest.png");
bitmap.compress(CompressFormat.PNG, 100, stream);
stream.close();

但无济于事。整个方法可能看起来很复杂,但这是我想出的解决 AppWidget 的 RemoteViews 限制的方法。

我的问题:

如何获取此 RoundedCornersDrawable,并将其导出为正确描绘美丽透明角的 PNG 文件?

在此先感谢您的帮助,我愿意接受有关解决整个问题的不同方法的任何和所有建议!

【问题讨论】:

关于drawToBitmap,最好用这个final Bitmap bmp= ThumbnailUtils.extractThumbnail(viewToDrawFrom.getDrawingCache(),width,height); 【参考方案1】:

遗憾的是,AppWidgets 在视图方面非常有限。您只能使用 Android 支持的视图。

原因是视图的代码需要在 AppWidget 的容器上运行,这是一个安全风险,因为您可以瞥见显示它的应用程序的私有数据。因此,Google 所做的就是您需要准备要显示的内容,并在完成后告诉受限制的 API 如何显示 AppWidget。

因此,解决方案是将应显示的图像刷新到 imageView 或类似的东西。 如果有很多准备工作,我建议在后台进行。

这一切都取决于您的需求。

【讨论】:

从我的编辑中可以看出,我解决了我的问题。不过,感谢您抽出宝贵时间查看此内容。是你对另一个问题的回答让我开始走上这条道路,我对结果很满意。谢谢! 我不明白你是如何解决这个问题的。你能发表一个答案吗? 只是一个简单的疏忽。这些方法一直有效,我的小部件太小而无法显示结果。 @WillThomson 哦。好的。顺便说一句,如果位图构建需要一些时间(但少于 10 秒),您可以使用以下命令在后台线程上安全地运行代码:***.com/questions/22741202/…【参考方案2】:

除了这个问题:

'原来我的 AppWidget 的大小正在裁剪图像 全程。剪掉它刚好可以去掉圆角,然后 只是小到没有明显被剪掉。所以对于任何人 遇到了这个问题......所有这些方法都为此工作 目的(只是不要忘记让你的 AppWidget 大到可以看到 结果)。'

答案:

我发现在将 RoundedCornersDrawable 导出到 PNG 文件之前,通过 CustomView.drawToBitMap() 方法传递它也很重要。

我希望有一天这一切都对某人有所帮助!

【讨论】:

如果你还需要弄清楚如何通过你的 appWidget 显示这个 PNG 图像,我在这里也发现了一个方法:***.com/questions/25944639/…

以上是关于带圆角的 AppWidget 图像的主要内容,如果未能解决你的问题,请参考以下文章

带圆角的画布 clearRect

在android中创建带圆角的按钮[重复]

如何在 ios 中的 imageview 上进行六边形图像遮罩?

圆角进度条,带数字居中显示的圆角进度条

Xamarin Forms:带圆角的 StackLayout

如何制作带圆角的窗户