web-dev-qa-db-ja.com

背景のドロアブルでアスペクト比を維持したまま画像を拡大縮小する

<bitmap />を背景の描画可能なXMLとして使用する場合、背景画像をビューに合わせながらアスペクト比を維持するにはどうすればよいですか? <bitmap>Android:gravity値はどれも、望ましい効果をもたらしません。

58
tilex

Xml-files内でのみ背景属性を操作することはできません。次の2つのオプションがあります。

  1. Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) を使用してプログラムでビットマップをカット/スケールし、Viewの背景として設定します。

  2. 背景の代わりにImageViewを使用して最初のレイアウトの要素として配置し、 Android:scaleType その属性:

    <RelativeLayout
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent" >
    
        <ImageView
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
    
            Android:src="@drawable/backgrnd"
            Android:scaleType="centerCrop" />
    
        ...
    
        rest layout components here
    
        ...
    
    </RelativeLayout>
    
58
a.ch.

ドロアブルからこれを行う簡単な方法があります:

your_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android" >

    <item Android:drawable="@color/bg_color"/>
    <item>
        <bitmap
            Android:gravity="center|bottom|clip_vertical"
            Android:src="@drawable/your_image" />
    </item>

</layer-list>

唯一の欠点は、十分なスペースがない場合、画像が完全に表示されないが、クリップされるため、ドローアブルから直接これを行う方法が見つからないことです。しかし、私が行ったテストからはかなりうまく機能し、画像の大部分は切り取られません。あなたは重力オプションでもっと遊ぶことができます。

別の方法は、ImageViewを使用してを設定するレイアウトを作成することですscaleTypetofitCenter.

この情報があなたが望むものを達成するのに役立つことを願っています。

33
Ionut Negru

カスタムDrawableクラスで同様のことをしたかったのです。重要な部分は次のとおりです。

public class CustomBackgroundDrawable extends Drawable
{
    private Rect mTempRect = new Rect();
    private Paint mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    ...

public void draw(@NonNull Canvas canvas)
{
    Rect bounds = getBounds();
    if (mBitmap != null ) {
        if (mScaleType == ScaleType.SCALE_FILL) {
            //bitmap scales to fill the whole bounds area (bitmap can be cropped)
            if (bounds.height() > 0 && bounds.height() > 0) {
                float scale = Math.min(mBitmap.getWidth()/(float)bounds.width(), mBitmap.getHeight()/(float)bounds.height());

                float bitmapVisibleWidth = scale * bounds.width();
                float bitmapVisibleHeight = scale * bounds.height();

                mTempRect.set((int)(mBitmap.getWidth()-bitmapVisibleWidth)/2, 0, (int)(bitmapVisibleWidth+mBitmap.getWidth())/2, (int)bitmapVisibleHeight);
                canvas.drawBitmap(mBitmap, mTempRect, bounds, mBitmapPaint);
            }
        } else if (mScaleType == ScaleType.SCALE_FIT) {
            //bitmap scales to fit in bounds area
            if (bounds.height() > 0 && bounds.height() > 0) {
                float scale = Math.min((float)bounds.width()/mBitmap.getWidth(), (float)bounds.height()/mBitmap.getHeight());

                float bitmapScaledWidth = scale * mBitmap.getWidth();
                float bitmapScaledHeight = scale * mBitmap.getHeight();
                int centerPadding = (int)(bounds.width()-bitmapScaledWidth)/2;
                mTempRect.set(bounds.left + centerPadding, bounds.top, bounds.right - centerPadding, bounds.top+(int)bitmapScaledHeight);
                canvas.drawBitmap(mBitmap, null, mTempRect, mBitmapPaint);
            }
        }
    }
}

このアプローチを使用すると、必要なスケールロジックを柔軟に適用できます。

3
Kamen Dobrev

別の方法は、通常の画像の patch 9 images を作成し、希望する方法で拡大縮小することです。

角に9パッチドットを配置してコンテンツを中央に配置し、比率を明らかに維持することができます(画像の最も外側のエッジが繰り返し可能/透明であると仮定)。

うまくいけば、あなたはアイデアを得ます。

3
xbakesx

A.chで説明されている方法を使用すると、私にとってはうまくいきました。ただし、このスケールタイプを使用したのは、必要なものにはるかに適していました。

Android:scaleType="centerCrop"

使用可能な縮尺タイプの完全なリストを次に示します。 http://developer.Android.com/reference/Android/widget/ImageView.ScaleType.html

2
Benjamin Stark

InsetDrawableを使用してみてください(私にとってはうまくいきました)。

これにドローアブルと、4辺のいずれかから必要なインセット(またはパディング)を与えるだけです。

InsetDrawable insetDrawable = new InsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom);

これは、ビューよりも小さいまたはサイズの背景ドロウアブルを設定するために特に使用されます。

こちらをご覧ください: https://developer.Android.com/reference/Android/graphics/drawable/InsetDrawable.html

2

古い質問ですが、他の答えはどれもうまくいきませんでした。ただし、このxmlコードは次のことを行いました。

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <ImageView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_alignParentTop="true"
        Android:scaleType="centerCrop"
        Android:src="@drawable/background_image"/> 

</RelativeLayout>
1
Incinerator

ビットマップが高さよりも広い場合は、Android:gravity="fill_vertical"を使用します。それ以外の場合は、Android:gravity="fill_horizontal"を使用します。これは、ImageViewAndroid:scaleType="centerCrop"を使用するのと同様の効果があります。

<bitmap xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:gravity="fill_vertical"
    Android:src="@drawable/image" />

複数の方向をサポートする場合、1つのビットマップXMLファイルをdrawable-portフォルダーに作成し、もう1つをdrawable-landフォルダーに作成できます。

1
Jason Robinson

fitを利用可能なスペースにイメージするため(またはwidthおよびheightをdpに設定した場合)、次のアプローチを試みました、画像が広すぎない場合も同様です。

ここでは、同じ高さ正方形の画像に設定しています[またはwrap_content 両方に]。

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <ImageView
        Android:layout_width="80dp"
        Android:layout_height="80dp"
        Android:layout_alignParentTop="true"
        Android:adjustViewBounds="true"
        Android:scaleType="fitCenter"
        Android:src="@drawable/background_image"/> 

</RelativeLayout>

adjust view boundsおよびscale type center fitトリックを行います。

0
Abhinav Saxena