しばしば尋ねられ、決して答えられなかった(少なくとも再現可能な方法ではない)。
私はより小さいである画像を持つ画像ビューを持っています。画像を画面の幅に合わせて拡大縮小し、ImageViewの高さを調整して、比例して正しい画像の高さを反映させます。
<ImageView
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
/>
これにより、画像は元のサイズ(画面幅よりも小さい)の中央に配置され、余白が横になります。ダメ。
だから私は追加しました
Android:adjustViewBounds="true"
同じ効果、ダメ。追加した
Android:scaleType="centerInside"
同じ効果、ダメ。 centerInside
をfitCenter
に変更しました。同じ効果、ダメ。 centerInside
をcenterCrop
に変更しました。
Android:scaleType="centerCrop"
さて、最後に、画像はscaled画面の幅に対応していますが、上下はcroppedです!そこで、centerCrop
をfitXY
に変更しました。
Android:scaleType="fitXY"
これで、画像は画面の幅に合わせて拡大縮小されますが、y軸でnotに拡大縮小され、distorted imageになります。
Android:adjustViewBounds="true"
を削除しても効果はありません。 Android:layout_gravity
を追加しても、他の場所で提案されているように、効果はありません。
私は他の組み合わせを試しました-無駄に。だから、誰もが知っていますか:
画面の幅に合わせてImageViewのXMLを設定し、ビュー全体に合わせて小さい画像を拡大縮小し、歪みやトリミングなしに画像をアスペクト比で表示するにはどうすればよいですか?
編集:私はまた、任意の数値の高さを設定しようとしました。これは、centerCrop
設定でのみ効果があります。ビューの高さに応じて画像を垂直に歪ませます。
XMLレイアウト標準内に実行可能なソリューションはありません。
動的な画像サイズに対応する唯一の信頼できる方法は、コードでLayoutParams
を使用することです。
がっかり。
レイアウトファイルに含めるJavaクラスを作成することでこれを解決しました。
public class DynamicImageView extends ImageView {
public DynamicImageView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final Drawable d = this.getDrawable();
if (d != null) {
// ceil not round - avoid thin vertical gaps along the left/right edges
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
this.setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
次に、クラスをレイアウトファイルに追加して、これを使用します。
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent" >
<my.package.name.DynamicImageView
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:scaleType="centerCrop"
Android:src="@drawable/about_image" />
</RelativeLayout>
あなたと同じ問題がありました。異なるバリエーションを30分間試した後、この方法で問題を解決しました。 柔軟な高さ、および親の幅に合わせた幅
<ImageView
Android:id="@+id/imageview_company_logo"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:adjustViewBounds="true"
Android:scaleType="fitCenter"
Android:src="@drawable/appicon" />
Android:scaleType="fitCenter"
元のsrcアスペクト比を維持するが、srcがdst内に完全に収まるようにするスケールを計算します。少なくとも1つの軸(XまたはY)が正確に適合します。結果はdstの中央に配置されます。
編集:
ここでの問題は、layout_height="wrap_content"
が画像の拡大を「許可」していないことです。その変更のために、サイズを設定する必要があります
Android:layout_height="wrap_content"
に
Android:layout_height="100dp" // or whatever size you want it to be
edit2:
正常に動作します:
<ImageView
Android:id="@+id/imageView1"
Android:layout_width="match_parent"
Android:layout_height="300dp"
Android:scaleType="fitCenter"
Android:src="@drawable/img715945m" />
これは、Mark Martinssonの優れたソリューションへの小さな追加です。
画像の幅が高さよりも大きい場合、Markのソリューションは画面の上下にスペースを残します。
以下は、最初に幅と高さを比較することでこれを修正します。画像の幅が高さ以上の場合、画面の高さと一致するように高さをスケーリングし、次にアスペクト比を維持するために幅をスケーリングします。同様に、画像の高さが幅よりも大きい場合、画面の幅に合わせて幅が拡大縮小され、アスペクト比が維持されるように高さが拡大縮小されます。
つまり、scaleType="centerCrop"
の定義を適切に満たしています。
http://developer.Android.com/reference/Android/widget/ImageView.ScaleType.html
の両方の寸法(幅と高さ)がまたはビューの対応する寸法よりも大きい(マイナスパディング)。
package com.mypackage;
import Android.content.Context;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.widget.ImageView;
public class FixedCenterCrop extends ImageView
{
public FixedCenterCrop(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
final Drawable d = this.getDrawable();
if(d != null) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
if(width >= height)
height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
else
width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight());
this.setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
このソリューションは、ポートレートモードまたはランドスケープモードで自動的に機能します。 Markのソリューションで行うように、レイアウトで参照します。例えば。:
<com.mypackage.FixedCenterCrop
Android:id="@+id/imgLoginBackground"
Android:src="@drawable/mybackground"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_centerInParent="true"
Android:scaleType="centerCrop" />
私は同じ問題に遭遇しましたが、高さを固定し、幅をスケーリングして、画像の元のアスペクト比を維持しました。重み付き線形レイアウトで解決しました。必要に応じて変更できます。
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:orientation="horizontal">
<ImageView
Android:id="@+id/image"
Android:layout_width="0px"
Android:layout_height="180dip"
Android:layout_weight="1.0"
Android:adjustViewBounds="true"
Android:scaleType="fitStart" />
</LinearLayout>
マーク・マーティンソンのコトリン版 answer :
class DynamicImageView(context: Context, attrs: AttributeSet) : AppCompatImageView(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val drawable = this.drawable
if (drawable != null) {
//Ceil not round - avoid thin vertical gaps along the left/right edges
val width = View.MeasureSpec.getSize(widthMeasureSpec)
val height = Math.ceil((width * drawable.intrinsicHeight.toFloat() / drawable.intrinsicWidth).toDouble()).toInt()
this.setMeasuredDimension(width, height)
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
Mark Matinssonのソリューションへのもう1つの追加。自分の画像の中には、他の画像よりも過度に拡大されたものがあることがわかりました。そこで、画像を最大係数でスケーリングするようにクラスを変更しました。画像が小さすぎてぼやけずに最大幅で拡大縮小できない場合、最大制限を超えて拡大縮小を停止します。
public class DynamicImageView extends ImageView {
final int MAX_SCALE_FACTOR = 2;
public DynamicImageView(final Context context) {
super(context);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final Drawable d = this.getDrawable();
if (d != null) {
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = View.MeasureSpec.getSize(widthMeasureSpec);
if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR;
final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
this.setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}