Масштабирование ImageView до ширины устройства - PullRequest
14 голосов
/ 02 февраля 2011

В моем приложении для Android есть Активность, в которой отображаются изображения следующего размера 244 x 330. Я хочу показать эти изображения в полную ширину устройства.

Мой файл макета выглядит так:

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

    <LinearLayout 
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical">

            <ImageView android:id="@+id/news_image" 
                android:layout_height="fill_parent" 
                android:layout_width="fill_parent"
                android:layout_marginLeft="18dip"
                android:layout_marginRight="18dip"
                android:background="#aaaaaa" />


    </LinearLayout>

</ScrollView>

Я попытался установить ScaleType для ImageView, но нет ScalingType, который масштабирует ImageView пропорционально. Как я могу пропорционально масштабировать изображение, чтобы оно помещалось на весь экран в ландшафтном режиме И в портретном режиме?

В основном я хочу что-то вроде ScaleType.CENTER_CORP, но которое также устанавливает пропорциональную высоту для изображения, чтобы я мог видеть все это, а не только часть изображения.

Изменить, потому что я знаю, что я путаю тебя с моим "странным" квестом.

Я хочу показать это вам с изображением. Это то, что я сейчас получаю с моим макетом. Я хочу заполнить всю серую область, масштабируя изображение по мере необходимости. Как мне это сделать?

image

Когда я устанавливаю ScaleType на CENTER_CROP, я получаю это

image

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

И вот что я хочу, чтобы это было:

image

Надеюсь, это поможет вам понять, чего я пытаюсь достичь. Кто-нибудь знает, как это сделать?

Редактировать 2:

Может показаться странным и немного сбивающим с толку, что я пытаюсь отобразить изображение, которое больше по высоте, чем размер экрана, но так как я использую ScrollView в моем примере макета, это должно быть в порядке, и пользователь может прокрутить, если он хочет видеть не отображаемую область.

Надеюсь, это поможет понять, что я пытаюсь сделать.

Ответы [ 9 ]

29 голосов
/ 03 февраля 2011

Я действительно пробовал каждый ScaleType в моих ImageView с fill_parent и wrap_content, но ни один из них не работал. Я также попробовал все, что нашел в Google, но у меня тоже ничего не получалось, поэтому придумал что-то самостоятельно.

Было ясно, что ImageView не масштабирует мое изображение, как я хотел, чтобы его масштабировали, поэтому мне пришлось масштабировать его самостоятельно. После масштабирования растрового изображения я бы установил новое растровое изображение в качестве источника изображения для ImageView. Это работает довольно хорошо и выглядит очень хорошо на G1 и на Motorola Milestone 2.

А вот и все части моего кода

Компоновка:

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

    <LinearLayout 
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:id="@+id/news_wrapper">

            <ImageView android:id="@+id/news_image" 
                android:layout_height="fill_parent"
                android:layout_width="fill_parent"
                android:layout_marginLeft="18dip"
                android:layout_marginRight="18dip"
                android:background="#aaaaaa" />

    </LinearLayout>

</ScrollView>

Активность

public class ScalingImages extends Activity {

    private ImageView imageView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_margin);

        this.imageView = (ImageView)findViewById(R.id.news_image);

        // The image is coming from resource folder but it could also 
        // load from the internet or whatever
        Drawable drawable = getResources().getDrawable(R.drawable.img);
        Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();

        // Get scaling factor to fit the max possible width of the ImageView
        float scalingFactor = this.getBitmapScalingFactor(bitmap);

        // Create a new bitmap with the scaling factor
        Bitmap newBitmap = Util.ScaleBitmap(bitmap, scalingFactor);

        // Set the bitmap as the ImageView source
        this.imageView.setImageBitmap(newBitmap);
    }

    private float getBitmapScalingFactor(Bitmap bm) {
        // Get display width from device
        int displayWidth = getWindowManager().getDefaultDisplay().getWidth();

        // Get margin to use it for calculating to max width of the ImageView
        LinearLayout.LayoutParams layoutParams = 
            (LinearLayout.LayoutParams)this.imageView.getLayoutParams();
        int leftMargin = layoutParams.leftMargin;
        int rightMargin = layoutParams.rightMargin;

        // Calculate the max width of the imageView
        int imageViewWidth = displayWidth - (leftMargin + rightMargin);

        // Calculate scaling factor and return it
        return ( (float) imageViewWidth / (float) bm.getWidth() );
    }
}

Util класс

public class Util {

    public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) {
        int scaleHeight = (int) (bm.getHeight() * scalingFactor);
        int scaleWidth = (int) (bm.getWidth() * scalingFactor);

        return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true);
    }

}

Если есть лучший или более точный способ выполнить такое же масштабирование , пожалуйста, дайте мне знать , потому что я не могу поверить, что такую ​​тривиальную вещь так трудно выполнить.

Я действительно надеюсь найти лучший способ сделать это.

Спасибо за чтение.

19 голосов
/ 08 мая 2014

самый простой способ - добавить Android: AdjustViewBounds = "true" в ImageView и установить тип масштаба "fitCenter"

3 голосов
/ 24 февраля 2014

Я гуглил везде и не мог найти решение.Вот что я сделал, это сработало для меня и с просмотром прокрутки.

XML-файл:

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

    <ImageView
        android:id="@+id/manga_page_image"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter" />
</ScrollView>
3 голосов
/ 02 февраля 2011

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

РЕДАКТИРОВАТЬ : Хорошо, я думаю, я понял вашу точку зрения сейчас. Во-первых, я бы установил для вашего LinearLayout значение wrap_content для высоты. Во-вторых, в коде, вот один из способов сделать это, о котором я могу подумать. Возможно, есть еще один способ сделать это: сначала получить размеры экрана, а затем выполнить createScaledBitmap с новыми размерами, а затем задать фоновый ресурс.

final ImageView newsImage = (ImageView)findViewById(R.id.news_image);

//get details on resolution from the display
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

//going to set what happens as the layout happens
newsImage.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {

        public void onGlobalLayout() {
            int oldHeight, oldWidth, newHeight, newWidth;

            //we want the new width to be as wide as the screen
            newWidth = metrics.widthPixels;

            oldHeight = newsImage.getDrawable().getIntrinsicHeight();
            oldWidth = newsImage.getDrawable().getIntrinsicWidth();

            //keeping the aspect ratio, the new height should be w1/h1 = w2/h2
            newHeight = Math.floor((oldHeight * newWidth) / oldWidth);
            LinearLayout.LayoutParams params = 
                (LinearLayout.LayoutParams)newsImage.getLayoutParams();
            params.height = newHeight;
            params.width = newWidth;
            newsImage.setLayoutParams(params);
            newsImage.setScaleType(ScaleType.CENTER);
            newsImage.invalidate();
            newsImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
    }
}
2 голосов
/ 02 февраля 2011

Я хочу показать эти изображения полностью Ширина устройства.

Это просто. У вас просто неправильные настройки полей. Удалите эти строки, и ваше изображение будет отображаться во всю ширину устройства:

android:layout_marginLeft="18dip"
android:layout_marginRight="18dip" 
2 голосов
/ 02 февраля 2011

Вы пытались установить его программно через ImageView.setScaleType()?

setAdjustViewBounds( false ) также может помочь.

Редактировать: извините, я неправильно прочитал вопрос. В любом случае, setAdjustViewBounds() все же может помочь. Никогда не использовал это все же.

1 голос
/ 28 января 2012

удалось достичь того, что я хотел, что, как мы надеемся, совпадает с вашей целью:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.pgviewer);

    ImageView PgContainer = (ImageView)findViewById(R.id.imageView1);

    String Page = String.valueOf(getIntent().getExtras().getInt("Page"));
    try {
        PgContainer.setImageBitmap(getBitmapFromAsset(Page));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    PgContainer.setScaleType(ScaleType.FIT_CENTER);
    PgContainer.scrollTo(0, 0);
    PgContainer.setScrollBarStyle(0);
}

затем масштабировать растровое изображение:

private Bitmap getBitmapFromAsset(String strName) throws IOException
{
    AssetManager assetManager = getAssets();
    InputStream istr = assetManager.open(strName+".png");
    Bitmap bitmap = BitmapFactory.decodeStream(istr);

    float screenWidth = getResources().getDisplayMetrics().widthPixels;
    int ih=bitmap.getHeight();
    int iw=bitmap.getWidth();
    float scalefactor = screenWidth/iw;
    //w = 480, h=~
    //int newh = bitmap.getHeight()/bitmap.getWidth();
    return android.graphics.Bitmap.createScaledBitmap(bitmap, (int)(iw*scalefactor), (int)(ih*scalefactor), true);
    //return bitmap;
}
1 голос
/ 11 января 2012

Я больше не вижу изображения, и вопрос старый, но на тот случай, если кто-то другой обнаружит это и столкнется с той же проблемой. Не лучше ли просто получить float screenWidth = getResources().getDisplayMetrics().widthPixels и программно установить параметры ImageView LayoutParamters, чтобы масштабировать изображение до screenWidth. Просто идея !!

0 голосов
/ 14 июля 2017

Один из способов сделать это, установив android: AdjustViewBounds = "true" для ImageView и установить тип масштаба "fitCenter" в файле XML.Это должно работать как ожидалось.Вы также можете сделать это программно, установив ImageView.adjustViewBounds (true) и ImageView.setScaleType (ScaleType.FIT_CENTER).

...