ImageView - мають ширину відповідності по висоті?


166

У мене є перегляд зображення. Я хочу, щоб його ширина була наповнювальною. Я хочу, щоб його висота була незалежною від ширини. Наприклад:

<ImageView
  android:layout_width="fill_parent"
  android:layout_height="whatever the width ends up being" />

Чи можливо щось подібне у файлі компонування без створення власного класу перегляду?

Дякую


Ви придумали, як це зробити? Я припускаю, що ви хочете, щоб співвідношення сторін залишалося колишнім. Більшість із цих відповідей припускають, що ви хочете, щоб зображення було квадратним.
Адам

@Joe Blow, що це ДУЖЕ поганий спосіб зробити це
Агресор

Відповіді:


170

Оновлення: 14 вересня 2017 року

Згідно з коментарем, наведеним нижче, бібліотека відсотків підтримки застаріла, ніж у бібліотеці підтримки Android 26.0.0. Це новий спосіб зробити це:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1" />

</android.support.constraint.ConstraintLayout>

Дивіться тут

Застаріле:

Відповідно до цього допису розробників Android, все, що вам потрібно зробити зараз, - це обернути все, що завгодно, в межах PercentRelativeLayout або PercentFrameLayout, а потім вказати його співвідношення, як-от так

<android.support.percent.PercentRelativeLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        app:layout_widthPercent="100%"
        app:layout_aspectRatio="100%"/>

</android.support.percent.PercentRelativeLayout>

8
Посилання на цю відповідь має найелегантніше рішення, надане Google. У моєму випадку я хотів, щоб зображення відображалося у співвідношенні 16: 9 незалежно від того, яке оригінальне співвідношення сторін зображення. Чудово працює. Дякую!
LETs

У моєму випадку такі рішення, як цей , не спрацювали, це зробили!
Gooey

5
не забудьте додати "компілювати com.android.support:percent:23.3.0" у ваших залежностях
Мілад Фарідня

Схоже, у цього підходу виникають проблеми з WrappedViewPager, який обчислює висоту на основі вмісту своїх дітей. Джерело для WrappedViewPager схоже на gist.github.com/egslava/589b82a6add9c816a007
sha

1
Модуль Percent Support був застарілий, він застарів з моменту підтримки бібліотеки Android 26.0.0. Джерело: developer.android.com/topic/libraries/support-library/…
MHogge

97

Можливо, це відповість на ваше запитання:

<ImageView
    android:id="@+id/cover_image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true" />

Ви можете ігнорувати scaleTypeатрибут для цієї конкретної ситуації.


12
Так, це марно
Фетті

4
Це не обов'язково марно. Це добре працює для мого використання, у мене на піктограмі на піктограмі є значок, який я хочу масштабувати, щоб заповнити висоту, залишаючи квадрат.
Anubian Noob

3
Вирішив і мою проблему.
Продаж Дільсона

Найпростіший спосіб! Це має бути позначено як найкращий відповідь.
Х. Фарид

30

Це можна зробити за допомогою LayoutParams для динамічного встановлення висоти переглядів, коли ви знаєте ширину перегляду під час виконання. Щоб отримати ширину представлень під час виконання, вам потрібно скористатися потоком Runnable, інакше ви намагатиметеся встановити висоту, перш ніж дізнатися ширину перегляду, оскільки макет ще не намальований.

Приклад того, як я вирішив свою проблему:

final FrameLayout mFrame = (FrameLayout) findViewById(R.id.frame_id);

    mFrame.post(new Runnable() {

        @Override
        public void run() {
            RelativeLayout.LayoutParams mParams;
            mParams = (RelativeLayout.LayoutParams) mFrame.getLayoutParams();
            mParams.height = mFrame.getWidth();
            mFrame.setLayoutParams(mParams);
            mFrame.postInvalidate();
        }
    });

Параметри LayoutParams повинні мати тип батьківського перегляду, в якому знаходиться ваш погляд. Мій FrameLayout знаходиться у відносному макеті у файлі xml.

    mFrame.postInvalidate();

викликається, щоб змусити погляд перемальовуватися, перебуваючи в окремому потоці, ніж потік інтерфейсу користувача


4
дивовижна відповідь, особливо з Runnable, спасибі!
jesses.co.tt

1
Хоча це працює, це не ідеально. Біг на посаді означає, що перегляд відображається один раз до зміни макета. Можна дозволити спалах вмісту на неправильній висоті, перш ніж правильно малювати. Краще вирішити раніше. Перший можливий момент вирішити - це звичай onMeasure, як показано у відповіді Регіса . Альтернативним, але тільки для видів послуг через адаптер, наприклад , всередині GridView, це відповідь Метта .
ToolmakerSteve

1
добре це працювало для мене лише після виклику requestLayout()після встановлення параметрів. чому це було б?
Divins Mathew

mFrame.postInvalidate (); це те, що це робилося, без цього я виводив погляд з позиції.
Яколак

17

Я не зміг отримати відповідь Девіда Чу для роботи над елементом RecyclerView і зрозумів, що мені потрібно обмежити ImageView батьків. Встановіть ширину ImageView на 0dpта обмежте його початок та кінець батьківським. Я не впевнений, чи встановлення ширини wrap_contentчи match_parentпрацює в деяких випадках, але я думаю, що це кращий спосіб змусити дитину ConstraintLayout заповнити її батьків.

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintDimensionRatio="1:1"/>

</android.support.constraint.ConstraintLayout>

13

Ось, що я зробив, щоб мати ImageButton, який завжди має ширину, рівну його висоті (і уникати дурних порожніх полів в одному напрямку ... що я вважаю помилкою SDK ...):

Я визначив клас SquareImageButton, який поширюється на ImageButton:

package com.myproject;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageButton;

    public class SquareImageButton extends ImageButton {

        public SquareImageButton(Context context) {
        super(context);


        // TODO Auto-generated constructor stub
    }

    public SquareImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub

    }

    public SquareImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

    }

    int squareDim = 1000000000;

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


        int h = this.getMeasuredHeight();
        int w = this.getMeasuredWidth();
        int curSquareDim = Math.min(w, h);
        // Inside a viewholder or other grid element,
        // with dynamically added content that is not in the XML,
        // height may be 0.
        // In that case, use the other dimension.
        if (curSquareDim == 0)
            curSquareDim = Math.max(w, h);

        if(curSquareDim < squareDim)
        {
            squareDim = curSquareDim;
        }

        Log.d("MyApp", "h "+h+"w "+w+"squareDim "+squareDim);


        setMeasuredDimension(squareDim, squareDim);

    }

}

Ось мій xml:

<com.myproject.SquareImageButton
            android:id="@+id/speakButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:scaleType="centerInside"
            android:src="@drawable/icon_rounded_no_shadow_144px"
            android:background="#00ff00"
            android:layout_alignTop="@+id/searchEditText"
            android:layout_alignBottom="@+id/searchEditText"
            android:layout_alignParentLeft="true"
           />

Працює як шарм!


Так, це найкраща відповідь. (і єдиний, який дійсно відповідає питанню ОП)
Twometer

6

В Android 26.0.0 PercentRelativeLayout застаріло .

Найкращий спосіб вирішити це зараз ConstraintLayoutтаким чином:

<android.support.constraint.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

    <ImageView android:layout_width="match_parent"
               android:layout_height="0dp"
               android:scaleType="centerCrop"
               android:src="@drawable/you_image"                       
               app:layout_constraintDimensionRatio="1:1"/>


</android.support.constraint.ConstraintLayout>


Ось підручник про те, як додати ConstraintLayoutдо свого проекту.


6

Якщо ваше зображення перебуває всередині макета обмеження, ви можете використовувати наступні обмеження для створення подання квадратного зображення

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:id="@+id/ivImageView"
    app:layout_constraintDimensionRatio="W,1:1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"/>

5

Ви не можете зробити це з макетом самостійно, я намагався. Я закінчив написати дуже простий клас, щоб обробити його, ви можете перевірити це на github. SquareImage.java Його частина більшого проекту, але нічого копію та вставлення неможливо виправити (ліцензується під Apache 2.0)

По суті, вам просто потрібно встановити висоту / ширину, рівну іншим розмірам (залежно від того, яким способом ви хочете її масштабувати)

Примітка. Ви можете зробити його квадратним без спеціального класу за допомогою scaleTypeатрибута, але межі перегляду виходять за рамки видимого зображення, що робить його проблемою, якщо ви розміщуєте поруч інші види.


3

Щоб встановити ImageView рівним половині екрана, вам потрібно додати наступне зображення до свого XML для ImageView:

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:scaleType="fitXY"
    android:adjustViewBounds="true"/>

Щоб потім встановити висоту, рівну цій ширині, потрібно зробити це в коді. У getViewспособі GridViewадаптера встановіть ImageViewвисоту, рівну його виміряній ширині:

mImageView.getLayoutParams().height = mImageView.getMeasuredWidth();

3

Для людей, які зараз проходять, у 2017 році новий найкращий спосіб досягти того, що ви хочете, - використовуючи ConstraintLayout таким чином:

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="1:1" />

І не забудьте додати обмеження для всіх чотирьох напрямків, залежно від вашого макета.

Створіть чуйний інтерфейс користувача з ConstraintLayout

Крім того, до цього часу PercentRelativeLayout застарілий (див. Документацію на Android ).


1

Ось як я вирішив цю проблему:

int pHeight =  picture.getHeight();
int pWidth = picture.getWidth();
int vWidth = preview.getWidth();
preview.getLayoutParams().height = (int)(vWidth*((double)pHeight/pWidth));

попередній перегляд - imageView із шириною, встановленою на "match_parent", а масштабType - "cropCenter"

picture - Бітмап-об'єкт для встановлення у imageView src.

Це дуже добре працює для мене.


Ви не пояснили, куди потрібно поставити цей код. Ви також не пояснили, чому ви робите = vw*ph/pwзамість простішого = vw. (Я думаю, ви робите це, щоб зберегти співвідношення сторін вихідного зображення, а не примушувати квадратний попередній перегляд.)
ToolmakerSteve

0

Я не думаю, що ви можете зробити це у файлі макета XML, і я не думаю, що android:scaleTypeатрибут працюватиме так, як ви хочете.
Єдиний спосіб - це зробити це програмно. Ви можете встановити ширину для fill_parent і можете взяти ширину екрана як висоту Viewабо використовувати View.getWidth()метод.


0

Тут може допомогти вам функція ImageView "scaleType".

Цей код збереже співвідношення сторін і розмістить зображення у верхній частині:

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitStart"

Ось чудовий пост, який показує можливості та виступи від використання scaleType.

Зразки ImageView scaleType


Тут не допомагає "scaleType". Мета полягає в тому, щоб сам ImageView завжди був квадратним, а не лише зображенням всередині нього. За допомогою шкали шкали типу ImageView може бути більше, ніж зображення.
ToolmakerSteve

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.