Skaluj obraz, zachowując jego proporcje w tle

Jak sprawić, aby obraz tła pasował do widoku, ale zachowywał proporcje, gdy używasz <bitmap /> jako rysowalnego tła XML? Żadna z wartości <bitmap> android:gravity nie daje pożądanego efektu.

Author: wonea, 2012-03-27

9 answers

Nie jest możliwe uzyskanie atrybutu tła tylko w plikach xml. Istnieją dwie opcje:

  1. Programowo wycinasz / skalujesz bitmapę za pomocą Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) i ustawić go jako tło View.

  2. Używasz ImageView zamiast tła umieszczając go jako element pierwszego układu i określasz android:scaleType atrybut dla niego:

    <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>
    
 50
Author: a.ch.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-05 08:34:28

Jest łatwy sposób, aby to zrobić z drawable:

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>

Jedynym minusem jest to, że jeśli nie ma wystarczającej ilości miejsca, Twój obraz nie będzie w pełni pokazany, ale zostanie przycięty, nie mogłem znaleźć sposobu, aby to zrobić bezpośrednio z drawable. Ale z testów, które zrobiłem, działa całkiem dobrze i nie klipsuje zbyt wiele obrazu. Możesz grać więcej z opcjami grawitacji.

Innym sposobem będzie po prostu stworzenie layoutu, w którym użyj ImageView i ustawić scaleType na fitCenter.

Mam nadzieję, że te informacje pomogą Ci osiągnąć to, czego chcesz.

 31
Author: Ionut Negru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 09:05:47

Innym podejściem byłoby stworzenie łatki 9 obrazów Twojego zwykłego obrazu i rozciągnięcie skali tak, jak chcesz.

Możesz wyśrodkować zawartość, umieszczając 9-łatkowe kropki w rogach, które oczywiście zachowają twój stosunek (zakładając, że zewnętrzna krawędź obrazu jest powtarzalna / przezroczysta).

Mam nadzieję, że masz pomysł.

 3
Author: xbakesx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-12 20:49:52

Chciałem zrobić coś podobnego w mojej klasie niestandardowego rysowania. Oto najważniejsze elementy:

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

Dzięki temu podejściu jesteś elastyczny, aby zastosować dowolną logikę skali, której potrzebujesz

 3
Author: Kamen Dobrev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 12:54:33

Stosując metodę opisaną przez a.ch działało świetnie dla mnie, z wyjątkiem tego typu skali, który działał znacznie lepiej dla tego, czego potrzebowałem: {]}

android:scaleType="centerCrop"

Oto pełna lista dostępnych typów skali: http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

 2
Author: Benjamin Stark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-12 17:02:30

Spróbuj użyć InsetDrawable(zadziałało dobrze dla mnie).

Po prostu daj to swoje rysowalne i wstawki (lub wyściółki), które chcesz z jednej z czterech stron.

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

Jest specjalnie używany do ustawiania tła drawable, o rozmiarze mniejszym lub niż Widok.

Zobacz Tutaj : https://developer.android.com/reference/android/graphics/drawable/InsetDrawable.html

 1
Author: Ashutosh Chamoli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-13 08:51:29

Stare pytanie, ale żadna z pozostałych odpowiedzi nie zadziałała. Ten kod xml zrobił jednak:

<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
Author: Incinerator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 15:24:41

Jeśli bitmapa jest szersza niż wysoka, użyj android:gravity="fill_vertical". W przeciwnym razie użyj android:gravity="fill_horizontal". Ma to podobny efekt jak użycie {[3] } na ImageView.

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

Jeśli obsługujesz wiele orientacji, możesz utworzyć jeden plik bitmapowy XML w folderze drawable-port, a drugi w folderze drawable-land.

 1
Author: Jason Robinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-15 02:28:58

Aby dopasować obraz do dostępnej przestrzeni (lub jeśli Ustawiłeś szerokość i wysokość w dp), próbowałem tego podejścia, jeśli obraz nie jest zbyt szeroki.

Tutaj ustawiłem tę samą szerokość i wysokość dla obrazów kwadratowych [lub możesz wrap_content na obu].

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

Dostosuj granice widoku i dopasuj Typ skali do środka.

 0
Author: Abhinav Saxena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-30 04:56:52