Подтвердить что ты не робот

Android: масштабировать графическое или фоновое изображение?

На макете я хочу масштабировать фоновое изображение (сохраняя его соотношение сторон) до места, выделенного при создании страницы. Кто-нибудь знает, как это сделать?

Я использую layout.setBackgroundDrawable() и использую BitmapDrawable для setGravity для отсечения и заполнения, но не вижу возможности для масштабирования.

4b9b3361

Ответ 1

Чтобы настроить масштабирование фонового изображения, создайте ресурс, подобный этому:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:src="@drawable/list_bkgnd" />

Затем он будет центрирован в представлении, если используется в качестве фона. Существуют и другие флаги: http://developer.android.com/guide/topics/resources/drawable-resource.html

Ответ 2

Не пытались сделать именно то, что вы хотите, но вы можете масштабировать ImageView с помощью android:scaleType="fitXY"
и размер будет соответствовать размеру, который вы даете ImageView.

Итак, вы можете создать FrameLayout для своего макета, поместить в него ImageView, а затем любой другой контент, который вам нужен в FrameLayout, а также прозрачный фон.

<FrameLayout  
android:layout_width="fill_parent" android:layout_height="fill_parent">

  <ImageView 
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:src="@drawable/back" android:scaleType="fitXY" />

  <LinearLayout>your views</LinearLayout>
</FrameLayout>

Ответ 3

Существует простой способ сделать это из 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>

Единственным недостатком является то, что если места недостаточно, ваше изображение не будет отображаться полностью, но оно будет обрезано, я не смог бы найти способ сделать это прямо из drawable. Но из тестов я сделал это очень хорошо, и это не зациклирует большую часть изображения. Вы можете играть больше с параметрами гравитации.

Другой способ - просто создать макет, где вы будете использовать ImageView и установите scaleType на fitCenter.

Ответ 4

Чтобы сохранить соотношение сторон, вы должны использовать android:scaleType=fitCenter или fitStart и т.д. Использование fitXY не сохранит исходное соотношение сторон изображения!

Обратите внимание, что это работает только для изображений с атрибутом src, а не для фонового изображения.

Ответ 5

Использовать изображение в качестве фона по размеру:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/imgPlaylistItemBg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:maxHeight="0dp"
        android:scaleType="fitXY"
        android:src="@drawable/img_dsh" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >


    </LinearLayout>

</FrameLayout>

Ответ 6

Когда вы устанавливаете Drawable из ImageView с помощью метода setBackgroundDrawable, изображение всегда будет масштабироваться. Параметры как adjustViewBounds или разные ScaleTypes будут просто проигнорированы. Единственное решение для сохранения соотношения сторон, которое я нашел, - это изменить размер ImageView после загрузки вашего рисунка. Вот фрагмент кода, который я использовал:

// bmp is your Bitmap object
int imgHeight = bmp.getHeight();
int imgWidth = bmp.getWidth();
int containerHeight = imageView.getHeight();
int containerWidth = imageView.getWidth();
boolean ch2cw = containerHeight > containerWidth;
float h2w = (float) imgHeight / (float) imgWidth;
float newContainerHeight, newContainerWidth;

if (h2w > 1) {
    // height is greater than width
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth * h2w;
    } else {
        newContainerHeight = (float) containerHeight;
        newContainerWidth = newContainerHeight / h2w;
    }
} else {
    // width is greater than height
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth / h2w; 
    } else {
        newContainerWidth = (float) containerHeight;
        newContainerHeight = newContainerWidth * h2w;       
    }
}
Bitmap copy = Bitmap.createScaledBitmap(bmp, (int) newContainerWidth, (int) newContainerHeight, false);
imageView.setBackgroundDrawable(new BitmapDrawable(copy));
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imageView.setLayoutParams(params);
imageView.setMaxHeight((int) newContainerHeight);
imageView.setMaxWidth((int) newContainerWidth);

В приведенном выше фрагменте кода bmp показан объект Bitmap, который должен быть показан, и imageView - это объект ImageView

Важно отметить изменение параметров макета. Это необходимо, потому что setMaxHeight и setMaxWidth будут иметь значение только в том случае, если ширина и высота определены для обертывания содержимого, а не для заполнения родителя. Заполнение родителя с другой стороны - это желаемая настройка в начале, потому что в противном случае containerWidth и containerHeight будут иметь значения, равные 0. Итак, в вашем файле макета у вас будет что-то вроде этого для вашего ImageView:

...
<ImageView android:id="@+id/my_image_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
...

Ответ 7

Это не самое эффективное решение, но, как кто-то предложил вместо фона, вы можете создать FrameLayout или RelativeLayout и использовать ImageView в качестве псевдо-фона - другие элементы будут расположены просто над ним:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:scaleType="fitStart"
        android:src="@drawable/menu_icon_exit" />

    <Button
        android:id="@+id/bSomeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="61dp"
        android:layout_marginTop="122dp"
        android:text="Button" />

</RelativeLayout>

Проблема с ImageView заключается в том, что доступны только доступные типы scaleTypes: CENTER, CENTER_CROP, CENTER_INSIDE, FIT_CENTER, FIT_END, FIT_START, FIT_XY, MATRIX (http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html)

и "масштабировать фоновое изображение (сохраняя его соотношение сторон)" в некоторых случаях, когда вы хотите, чтобы изображение заполняло весь экран (например, фоновое изображение), а соотношение сторон экрана отличается от изображения, необходимо scaleType - вид TOP_CROP, потому что:

CENTER_CROP центрирует масштабированное изображение вместо выравнивания верхнего края к верхнему краю изображения, а FIT_START соответствует высоте экрана и не заполняет ширину. И, как заметил Анке, FIT_XY не поддерживает соотношение сторон.

С радостью кто-то расширил ImageView для поддержки TOP_CROP

public class ImageViewScaleTypeTopCrop extends ImageView {
    public ImageViewScaleTypeTopCrop(Context context) {
        super(context);
        setup();
    }

    public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup();
    }

    public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setup();
    }

    private void setup() {
        setScaleType(ScaleType.MATRIX);
    }

    @Override
    protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) {

        float frameWidth = frameRight - frameLeft;
        float frameHeight = frameBottom - frameTop;

        if (getDrawable() != null) {

            Matrix matrix = getImageMatrix();
            float scaleFactor, scaleFactorWidth, scaleFactorHeight;

            scaleFactorWidth = (float) frameWidth / (float) getDrawable().getIntrinsicWidth();
            scaleFactorHeight = (float) frameHeight / (float) getDrawable().getIntrinsicHeight();

            if (scaleFactorHeight > scaleFactorWidth) {
                scaleFactor = scaleFactorHeight;
            } else {
                scaleFactor = scaleFactorWidth;
            }

            matrix.setScale(scaleFactor, scaleFactor, 0, 0);
            setImageMatrix(matrix);
        }

        return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
    }

}

fooobar.com/questions/52661/...

Теперь IMHO был бы идеальным, если бы кто-нибудь написал пользовательский Drawable, который масштабирует изображение таким образом. Затем он может использоваться как фоновый параметр.


Reflog предлагает предварительно масштабировать перед использованием. Вот инструкция, как это сделать: Java (Android): Как масштабировать графику без растрового изображения? Хотя у него есть недостаток, что масштабируемая масштабируемая/растровая карта будет использовать больше ОЗУ, а масштабирование "на лету", используемое ImageView, не требует больше памяти. Преимущество может быть меньше нагрузки процессора.

Ответ 8

Что предлагает Dweebo. Но по моему скромному мнению это не нужно. Одиночный вес фонаря сам по себе. Представление должно иметь фиксированную ширину и высоту, как в следующем примере:

 < RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/black">

    <LinearLayout
        android:layout_width="500dip"
        android:layout_height="450dip"
        android:layout_centerInParent="true"
        android:background="@drawable/my_drawable"
        android:orientation="vertical"
        android:padding="30dip"
        >
        ...
     </LinearLayout>
 < / RelativeLayout>

Ответ 9

Код "Ниже" делает растровое изображение совершенно одинаковым размером изображения. Получите высоту и ширину растрового изображения, а затем вычислите новую высоту и ширину с помощью параметров изображения. Это даст вам требуемое изображение с наилучшим соотношением сторон.

int bwidth=bitMap1.getWidth();
int bheight=bitMap1.getHeight();
int swidth=imageView_location.getWidth();
int sheight=imageView_location.getHeight();
new_width=swidth;
new_height = (int) Math.floor((double) bheight *( (double) new_width / (double) bwidth));
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap1,new_width,new_height, true);
imageView_location.setImageBitmap(newbitMap)

Ответ 10

Один из вариантов - разместить изображение в папке drawable-nodpi и установить фон макета для идентификатора ресурса.

Это определенно работает с уменьшением масштаба, но я не тестировал его масштабирование.

Ответ 11

вам нужно предварительно масштабировать эту возможность, прежде чем использовать ее в качестве фона

Ответ 12

Вы можете использовать один из следующих вариантов:

андроида: гравитация = "fill_horizontal | clip_vertical"

или

андроида: гравитация = "fill_vertical | clip_horizontal"