web-dev-qa-db-fra.com

Échelle d'image gardant son format d'image en arrière-plan dessinable

Comment adapter une image d'arrière-plan à la vue tout en conservant ses proportions lorsque vous utilisez <bitmap /> Comme fichier XML pouvant être dessiné en arrière-plan? Aucune des valeurs <bitmap> De Android:gravity Ne donne l'effet désiré.

58
tilex

Il est impossible de manipuler l'attribut d'arrière-plan dans les fichiers xml uniquement. Il y a deux options:

  1. Vous coupez/redimensionnez le bitmap par programme avec Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) et vous le définissez comme arrière-plan de View.

  2. Vous utilisez ImageView au lieu de l’arrière-plan, vous le placez comme élément de la première mise en page et vous spécifiez Android:scaleType attribut pour cela:

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

Il existe un moyen facile de faire cela depuis le dessinable:

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>

Le seul inconvénient est que s'il n'y a pas assez d'espace, votre image ne sera pas entièrement affichée, mais elle sera coupée, je ne pouvais pas trouver un moyen de le faire directement à partir d'un dessinable. Mais d'après les tests que j'ai effectués, cela fonctionne assez bien et ne coupe pas beaucoup l'image. Vous pourriez jouer plus avec les options de gravité.

Une autre façon de créer une mise en page consiste à utiliser un ImageView et à définir le scaleType à fitCenter.

J'espère que cette information vous aidera à réaliser ce que vous voulez.

33
Ionut Negru

Je voulais faire quelque chose de similaire dans ma classe Drawable personnalisée. Voici les pièces importantes:

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

Avec cette approche, vous êtes flexible pour appliquer toute logique de balance dont vous avez besoin.

3
Kamen Dobrev

Une autre approche serait de créer images du patch 9 de votre image normale et de l’étendre à l’échelle que vous le souhaitez.

Vous pouvez le faire centrer le contenu en plaçant 9 points de raccordement dans les coins, ce qui préservera votre rapport de manière évidente (en supposant que le bord extérieur de votre image soit répétable/transparent).

J'espère que vous avez l'idée.

3
xbakesx

L'utilisation de la méthode décrite par a.ch a très bien fonctionné pour moi, sauf que j'ai utilisé ce type de balance qui fonctionnait beaucoup mieux pour ce dont j'avais besoin:

Android:scaleType="centerCrop"

Voici une liste complète des types de balance disponibles: http://developer.Android.com/reference/Android/widget/ImageView.ScaleType.html

2
Benjamin Stark

Essayez d'utiliser InsetDrawable (a bien fonctionné pour moi).

Donnez simplement ceci à votre dessin et inserts (ou rembourrages) que vous voulez de l'un des quatre côtés.

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

Il est spécifiquement utilisé pour la configuration d’arrière-plan dessinable, de taille inférieure ou égale à la vue.

Voir ici: https://developer.Android.com/reference/Android/graphics/drawable/InsetDrawable.html

2
Ashutosh Chamoli

Vieille question, mais aucune des autres réponses n'a fonctionné pour moi. Ce code xml a cependant:

<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

Si votre image bitmap est plus large que haute, utilisez Android:gravity="fill_vertical". Sinon, utilisez Android:gravity="fill_horizontal". Cela a un effet similaire à celui d'utiliser Android:scaleType="centerCrop" Sur un ImageView.

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

Si vous prenez en charge plusieurs orientations, vous pouvez créer un fichier XML bitmap dans le dossier drawable-port Et l'autre dans le dossier drawable-land.

1
Jason Robinson

Afin de fit l'image à l'espace disponible (ou si vous avez défini largeur et hauteur en dp), J'ai essayé l'approche suivante, même si l'image n'est pas trop large.

Ici, j'ai défini le même largeur et hauteur pour images carrées [ou vous pouvez wrap_content à la fois].

<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 et scale type center fit fait le tour.

0
Abhinav Saxena