48

Come faccio a fare in modo che un'immagine di sfondo si adatti alla vista ma mantenga le proporzioni quando si utilizza <bitmap /> come xml di sfondo disegnabile? Nessuno dei valori <bitmap> di android:gravity dà l'effetto desiderato.Ridimensiona l'immagine mantenendo le proporzioni sullo sfondo disegnabile

+1

Avete già provato [ScaleType] (http://developer.android.com/reference /android/widget/ImageView.ScaleType.html)? –

+1

Prova android: scaleType = "matrix" – Pavandroid

+1

ScaleType è per ImageView. Le bitmap non lo supportano. – OldSchool4664

risposta

48

È impossibile ottenere la manipolazione dell'attributo in background solo nei file xml. Ci sono due opzioni:

  1. si taglia/scala del bitmap a livello di codice con Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) e impostarla come sfondo alcuni View s'.

  2. È utilizzare ImageView invece di sfondo ponendolo come elemento del primo layout e specificare android:scaleType attributo per esso:

    <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> 
    
+6

L'opzione 'centerCrop' di ScaleType è molto buona per questo. –

+2

Tutti i possibili valori di 'android: scaleType' non danno l'effetto necessario. Un'immagine si adatta alla vista mantenendo il suo rapporto solo se non specifica affatto 'scaleType'. – tilex

+0

Grazie, centerInside funziona per me. – pengguang001

3

altro approccio sarebbe quello di creare patch 9 images della vostra immagine regolare e lo hanno tratto scala nel modo desiderato.

Puoi centrare il contenuto inserendo 9 punti di patch negli angoli che conserveranno ovviamente il tuo rapporto (presupponendo che il bordo esterno dell'immagine sia ripetibile/trasparente).

Speriamo che tu abbia l'idea.

2

Utilizzando il metodo descritto da a.ch ha lavorato molto per me, tranne che ho usato questo tipo di scala che ha funzionato molto meglio per quello che mi serviva:

android:scaleType="centerCrop" 

Ecco un elenco completo dei tipi di scala disponibili: http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

+1

e qui puoi vedere alcuni esempi per ogni tipo: http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html –

29

C'è un modo semplice per fare questo dal drawable:

your_drawable.xml

L'unico svantaggio è che se non c'è abbastanza spazio, l'immagine non verrà mostrata completamente, ma verrà ritagliata, non ho trovato un modo per farlo direttamente da un drawable. Ma dai test che ho fatto funziona abbastanza bene, e non ritagliamo gran parte dell'immagine. Puoi giocare di più con le opzioni di gravità.

Un altro modo sarà quello di creare solo un layout, dove si utilizzerà un ImageView e impostare il scaleType a fitCenter.

Spero che questa informazione ti aiuti a ottenere ciò che desideri.

1

vecchia questione, ma nessuna delle altre risposte ha lavorato per me. Questo codice XML ha fatto comunque:

<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

Se la bitmap è più largo che alto, utilizzare android:gravity="fill_vertical". Altrimenti, utilizzare android:gravity="fill_horitzonal". Questo ha un effetto simile all'utilizzo di android:scaleType="centerCrop" su un ImageView.

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

Se supporti più orientamenti, è possibile creare un file bitmap XML nella cartella drawable-port e l'altro nella cartella drawable-land.

1

Volevo fare qualcosa di simile nella mia classe Drawable personalizzata. Qui ci sono i pezzi importanti:

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

Con questo approccio si sono flessibili di applicare qualsiasi logica di scala che è necessario