Android:layout_width=100dp
、Android:layout_height=wrap_content
、Android:adjustViewBounds=true
のImageViewがあります
ソースは50 x 50ピクセルの画像です。ただし、アスペクト比は保持されません-ImageViewの高さは100pxではなく50pxです(つまり、adjustViewBounds
は機能しません)。 200x200pxの画像がある場合は動作します-幅と高さは100pxです。このコードは、幅100ピクセル、高さ50ピクセルの画像になりますが、srcイメージは正方形です。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent">
<ImageView
Android:id="@+id/photo"
Android:src="@drawable/icon"
Android:layout_width="100dp"
Android:layout_height="wrap_content"
Android:scaleType="fitXY"
Android:adjustViewBounds="true" />
</LinearLayout>
問題は、adjustViewBounds
がImageView
のサイズをドロアブルの自然な寸法を超えて増加させないことです。アスペクト比を維持するためにビューを縮小するだけです。 50x50画像の代わりに500x500画像を提供する場合、これは機能するはずです。
この動作が実装されている場所に興味がある場合は、 ImageView.JavaのonMeasure実装 を参照してください。
回避策の1つは、ImageView
でこの動作を変更するカスタムonMeasure
を実装することです。
もっと簡単な方法があります。 ImageViewを次のようにします。
<ImageView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:scaleType="fitCenter"
Android:adjustViewBounds="true"/>
このようにdrawableはImageViewの中央に収まるように伸縮しますアスペクト比を維持します。空白を残さないように、適切な高さを計算して比例させる必要があります。
private void setImageBitmap(Bitmap bitmap, ImageView imageView){
float i = ((float)imageWidth)/((float)bitmap.getWidth());
float imageHeight = i * (bitmap.getHeight());
imageView.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth, (int) imageHeight));
imageView.setImageBitmap(bitmap);
}
同様の要件がありました。私の場合、画像を正方形にし、ImageViewをアスペクト比に合わせて、背景とパディングを使用して境界線を描画できるようにしました。
ここで答えを読みましたが、ImageViewをオーバーライドする代わりに、コンテンツ(1つのビューのみ)が正方形であることを保証するレイアウトを作成することにしました。そうすれば、その中に標準のImageViewを使用できます。 (そして、あなたは決して知らない、私は後で他の何かを正方形にしたいと思うかもしれない。おそらくそうではないが。)
他の人にとって便利な場合は、ここにコードがあります(気軽にコピーしてください)。おそらく、アプリで機能するようにした後停止したため、おそらくバグがあります。 :)
public class SquareLayout extends ViewGroup
{
public SquareLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public SquareLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SquareLayout(Context context)
{
super(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
// Work out width and height, and square size.
int width = r - l;
int height = b - t;
int size, xOffset, yOffset;
if(width < height)
{
size = width;
xOffset = 0;
yOffset = (height - size) / 2;
}
else
{
size = height;
xOffset = (width - size) / 2;
yOffset = 0;
}
for(int i = 0; i < getChildCount(); i++)
{
View child = getChildAt(i);
child.layout(xOffset, yOffset, size + xOffset, size + yOffset);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// Get width and height.
int w = -1, h = -1;
switch(MeasureSpec.getMode(widthMeasureSpec))
{
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
w = MeasureSpec.getSize(widthMeasureSpec);
break;
case MeasureSpec.UNSPECIFIED:
break;
}
switch(MeasureSpec.getMode(heightMeasureSpec))
{
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
h = MeasureSpec.getSize(heightMeasureSpec);
break;
case MeasureSpec.UNSPECIFIED:
break;
}
// If only one of width/height is unspecified, set them both the same.
if(w == -1 && h != -1)
{
w = h;
}
else if(h == -1 && w != -1)
{
h = w;
}
// Either they're both specified or both unspecified.
int childMeasureSpec;
if(w == -1)
{
childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
else
{
childMeasureSpec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
}
// Pass through to children.
int maxDimension = 1;
for(int i = 0; i < getChildCount(); i++)
{
View child = getChildAt(i);
child.measure(childMeasureSpec, childMeasureSpec);
maxDimension = Math.max(maxDimension, child.getMeasuredWidth());
maxDimension = Math.max(maxDimension, child.getMeasuredHeight());
}
if(w == -1)
{
w = maxDimension;
h = maxDimension;
}
setMeasuredDimension(w, h);
}
}