1

我有一个ImageView全宽和宽度:高度 = 3:1,我们称之为 1200 x 400。我想在 中显示两个Drawables ImageView,这两个 s 都只在运行时才知道。应根据“中心裁剪”将其中一个可绘制对象放入其中ImageView(假设可绘制对象的宽度:高度> 3,这意味着使宽度完全适合并裁剪顶部和底部),另一个应居中并按比例缩放自定义因素。

我有一些代码可以做到这一点,但对我来说似乎不必要地复杂;Bitmap 当我从 中创建一个新的LayerDrawable,然后BitmapDrawable从那个创建一个新的,然后在 上再次设置所需的边界时,我只能让它按需要工作BitmapDrawable,尽管我已经在LayerDrawable- 上设置了边界,但如果我不这样做,这些边界将被忽略'不要执行额外的步骤。我更喜欢以LayerDrawable这样的方式生成,我可以使用它.setImageDrawable(),但我不知道如何。如果我尝试,Android 会做什么对我来说没有任何意义。我究竟做错了什么?

这就是我制作的方法LayerDrawable

double divide(int k, int n) {
    return ((double)k)/n;
}
int verticalPaddingForHorizontalFit(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight){
    // you want to draw a drawable into a view, with an exact match in the width. Then either [1] or [2]
    // [1] the view is taller than the drawable (i.e., height/width bigger for the view)
    //     --> method result is positive,
    //     and gives the amount of padding top and bottom
    // [2] the drawable is taller
    //     --> method result is negative,
    //         and gives (minus) the amount that needs to be clipped from top and bottom
    // such that the drawable is vertically centered
    double viewAspect     = divide(viewHeight,     viewWidth    );
    double drawableAspect = divide(drawableHeight, drawableWidth);
    return (int)Math.round(0.5 * viewWidth * (viewAspect - drawableAspect));
}
int[] paddingWhenCenteredAt(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight, double drawableScale, int centerX, int centerY){
    // scale the drawable with drawableScale, and put it into the view
    // such that the center of the drawable has coordinates (centerX, centerY)
    // return the padding needed as array of left, top, right, bottom, in that order
    // negative values indicating clipping instead of padding
    double w = drawableScale * drawableWidth;
    double h = drawableScale * drawableHeight;
    double left = centerX - 0.5*w;
    double right = viewWidth - (centerX + 0.5*w);
    double top = centerY - 0.5*h;
    double bottom = viewHeight - (centerY + 0.5*h);
    return new int[]{(int)Math.round(left), (int)Math.round(top), (int)Math.round(right), (int)Math.round(bottom)};
}
LayerDrawable makeLayerDrawable(Resources r, int outputWidth, int outputHeight, Bitmap bm1, Bitmap bm2){
    Drawable[] layers = new Drawable[2];
    BitmapDrawable bmd1 = new BitmapDrawable(r, bm1);
    int width1  = bmd1.getIntrinsicWidth();
    int height1 = bmd1.getIntrinsicHeight();
    layers[0]   = bmd1;
    BitmapDrawable bmd2 = new BitmapDrawable(r, bm2);
    int width2  = bmd2.getIntrinsicWidth();
    int height2 = bmd2.getIntrinsicHeight();
    layers[1]   = bmd2;
    LayerDrawable result = new LayerDrawable(layers);
    int vPad = verticalPaddingForHorizontalFit(outputWidth, outputHeight, width1, height1);
    result.setLayerInset(0, 0, vPad, 0, vPad);
    int[] ltrb = paddingWhenCenteredAt(outputWidth, outputHeight, width2, height2, 0.5, outputWidth/2, outputHeight/2);
    result.setLayerInset(1, ltrb[0], ltrb[1], ltrb[2], ltrb[3]);
    result.setBounds(0, 0, outputWidth, outputHeight);
    return result;
}

(我用 Bitmap bm1 2400 x 1200 像素和 Bitmap bm2 800 x 300 像素进行了测试。)

现在,如果我只是使用它LayerDrawable,就像这样

    myImageView.setImageDrawable(layd);

ImageView不会有所需的大小(高度变化。)如果我再次设置布局,LayoutParameters我可以防止这种情况发生,但是,drawables没有正确显示。相反,我这样做

    LayerDrawable layd = makeLayerDrawable(r, outputWidth, outputHeight, bm1, bm2);
    Bitmap b = Bitmap.createBitmap(outputWidth, outputHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(b);
    layd.draw(canvas);
    BitmapDrawable result = new BitmapDrawable(getResources(), b);
    result.setBounds(0, 0, outputWidth, outputHeight);
    myImageView.setImageDrawable(result);

有用。

是github上的完整代码

4

1 回答 1

0

我会考虑编写自己的Drawable课程,这并不像看起来那么难。只需扩展Drawable并覆盖draw()您在代码中所做的几乎相同的计算,只是为了绘制到具有所需纵横比的分层(堆叠)位图。Canvas.drawBitmap()似乎可以解决您的问题。

于 2015-01-28T00:37:41.403 回答