wake-up-neo.com

Skaliere das Bild so, dass sein Seitenverhältnis im Hintergrund zeichnbar bleibt

Wie kann ich ein Hintergrundbild an die Ansicht anpassen, aber das Seitenverhältnis beibehalten, wenn <bitmap /> Als im Hintergrund darstellbares XML verwendet wird? Keiner der <bitmap> - Werte von Android:gravity Ergibt den gewünschten Effekt.

58
tilex

Es ist unmöglich, das Hintergrundattribut nur in XML-Dateien zu manipulieren. Es gibt zwei Möglichkeiten:

  1. Sie schneiden/skalieren die Bitmap programmgesteuert mit Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) und legen sie als Hintergrund für View fest.

  2. Sie verwenden ImageView anstelle des Hintergrunds, indem Sie ihn als erstes Layoutelement platzieren, und geben Android:scaleType Attribut dafür:

    <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.

Es gibt eine einfache Möglichkeit, dies aus dem Drawable heraus zu tun:

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>

Der einzige Nachteil ist, dass wenn nicht genügend Speicherplatz vorhanden ist, Ihr Bild nicht vollständig angezeigt wird, es jedoch abgeschnitten wird. Ich konnte keinen Weg finden, dies direkt von einer Zeichenfläche aus zu tun. Aber von den Tests, die ich gemacht habe, funktioniert es ziemlich gut und es schneidet nicht so viel vom Bild ab. Sie könnten mehr mit den Schwerkraftoptionen spielen.

Eine andere Möglichkeit besteht darin, einfach ein Layout zu erstellen, in dem Sie ein ImageView verwenden und das scaleType auf fitCenter.

Ich hoffe, diese Informationen helfen Ihnen dabei, das zu erreichen, was Sie wollen.

33
Ionut Negru

Ich wollte in meiner benutzerdefinierten Drawable-Klasse etwas Ähnliches tun. Hier sind die wichtigen Stücke:

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);
            }
        }
    }
}

Mit diesem Ansatz können Sie flexibel jede Skalierungslogik anwenden, die Sie benötigen

3
Kamen Dobrev

Ein anderer Ansatz wäre, Patch 9-Bilder von Ihrem regulären Bild zu erstellen und es so strecken zu lassen, wie Sie es möchten.

Sie können den Inhalt zentrieren, indem Sie 9-Patch-Punkte in die Ecken setzen, wodurch Ihr Verhältnis offensichtlich erhalten bleibt (vorausgesetzt, der äußerste Rand Ihres Bildes ist wiederholbar/transparent).

Hoffentlich kommst du auf die Idee.

3
xbakesx

Die von a.ch beschriebene Methode hat sich für mich hervorragend bewährt, außer dass ich diesen Skalentyp verwendet habe, der für das, was ich brauchte, viel besser funktioniert hat:

Android:scaleType="centerCrop"

Hier ist eine vollständige Liste der verfügbaren Skalentypen: http://developer.Android.com/reference/Android/widget/ImageView.ScaleType.html

2
Benjamin Stark

Versuchen Sie es mit InsetDrawable (hat bei mir gut funktioniert).

Geben Sie diesem einfach Ihr Zeichen und die gewünschten Einsätze (oder Polsterungen) von einer der vier Seiten.

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

Es wird speziell verwendet, um Hintergrundbilder zu zeichnen, die kleiner oder kleiner als die Ansicht sind.

Siehe hier: https://developer.Android.com/reference/Android/graphics/drawable/InsetDrawable.html

2

Alte Frage, aber keine der anderen Antworten hat für mich funktioniert. Dieser XML-Code hat jedoch Folgendes bewirkt:

<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

Wenn Ihre Bitmap breiter als hoch ist, verwenden Sie Android:gravity="fill_vertical". Verwenden Sie andernfalls Android:gravity="fill_horizontal". Dies hat einen ähnlichen Effekt wie die Verwendung von Android:scaleType="centerCrop" Für ein ImageView.

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

Wenn Sie mehrere Ausrichtungen unterstützen, können Sie eine Bitmap-XML-Datei im Ordner drawable-port Und die andere im Ordner drawable-land Erstellen.

1
Jason Robinson

Um fit das Bild an den verfügbaren Platz anzupassen (oder wenn Sie width und height in dp eingestellt haben), habe ich den folgenden Ansatz versucht , auch wenn das Bild nicht zu breit ist.

Hier habe ich gleich width und height für square images gesetzt [oder du kannst wrap_content auf beiden].

<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 und scale type center fit macht den Trick.

0
Abhinav Saxena