저는 ImageView
, 전체 너비 및 너비 : 높이 = 3 : 1을 가지고 있습니다. 1200 x 400이라고합시다. ImageView
에 두 개의 Drawable
두 개를 표시하려고합니다. 두 개는 모두 런타임에만 알려져 있습니다. 드로어 블 중 하나는 "center-crop"에 따라 ImageView
에 배치해야합니다. 드로어 블이 width : height> 3 인 경우, 너비가 정확히 맞고 위쪽과 아래쪽이 잘리는 것을 의미합니다. 다른 쪽은 가운데 맞추기 및 크기 조절해야합니다. 맞춤 요인으로LayerDrawable :이 작업을보다 효율적으로 수행 할 수 있습니까?
이 작업을 수행하는 코드가 있지만 불필요하게 복잡합니다. 나는 LayerDrawable
에서 새 Bitmap
을 만들고 그 다음에 BitmapDrawable
을 만들었을 때 LayerDrawable
에 이미 경계를 설정했지만 BitmapDrawable
에 원하는 경계를 다시 설정할 때만 원하는대로 작동하도록 할 수있었습니다. 그러나 그 경계는 다음과 같습니다. 여분의 단계를 수행하지 않으면 무시됩니다. 나는 .setImageDrawable()
에 그대로 사용할 수있는 그런 방식으로 LayerDrawable
을 생성하는 것을 선호하지만, 어떻게해야할지 모르겠다. 시도해도 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;
}
(I는 비트 맵 BM1 2400 x 1200 픽셀 비트 맵 BM2 800 x 300 픽셀로 테스트했습니다.)
지금, 난 그냥 LayerDrawable
것을 사용하는 경우 , 그래서
myImageView.setImageDrawable(layd);
처럼 ImageView
은 (높이 변경.) 원하는 크기가되지 않습니다 내가다시 레이아웃을 설정하는 경우, 그걸 막을 수는 있지만 드로어 블이 올바르게 표시되지 않습니다. 대신, 나는 이것을한다
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);
그것은 작동한다.
Here는 github에
난 그 하드가 보인다 아닌 자신의Drawable
클래스를 작성 고려할 것이라고
ImageView는 레이아웃의 일부로 이미지 드로어 블에 setBounds()를 호출합니다. 경계를 설정하려고 수동으로 호출하면 효과가 없습니다. BitmapDrawable 레이어에 [gravity] (http://developer.android.com/reference/android/graphics/drawable/BitmapDrawable.html#attr_android:gravity)를 설정하는 것을 고려해야합니다. – alanv
@alanv. 1) 중력이 내 목적에 충분히 융통성이 없다고 생각합니다. 드로어 블 중 하나는 가운데도 구석에도 없습니다. 2) (screenWidth x screenWidth/3) 뷰의 픽셀 크기를 원하는 것을 알고있다 - 나보다 똑똑해 지려고 시도하고있는 ImageView 알려주고 setBounds() 호출하지 않는 방법은 무엇입니까? – mathheadinclouds
ImageView의 기본 측정 및 레이아웃을 재정의해야합니다. 아래의 대답은 자신 만의 Drawable을 작성하는 것이 가장 좋은 방법이라고 제안하지만 LayerDrawable을 하위 클래스로 분류하는 것이 더 좋을 수도 있고 onBoundsChange() 메서드를 재정 의하여 개별 레이어에서 고유 한 setBounds()를 호출하는 것이 좋습니다. – alanv