ImageView - есть высота соответствует ширине? - PullRequest
146 голосов
/ 21 марта 2012

У меня есть изображение.Я хочу, чтобы его ширина была fill_parent.Я хочу, чтобы его высота равнялась ширине.Например:

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

Возможно ли что-то подобное в файле макета без необходимости создания собственного класса представления?

Спасибо

Ответы [ 13 ]

143 голосов
/ 07 ноября 2015

Обновление: 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>
93 голосов
/ 23 апреля 2013

Возможно, это ответит на ваш вопрос:

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

Вы можете игнорировать атрибут scaleType для этой конкретной ситуации.

30 голосов
/ 20 июля 2013

Это можно сделать с помощью 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 находится внутри RelativeLayout в xml-файле.

    mFrame.postInvalidate();

вызывается для принудительного перерисовки представления в отдельном потоке, отличном от потока пользовательского интерфейса

13 голосов
/ 30 мая 2013

Здесь я сделал то, что я сделал, чтобы 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"
           />

Работает как шарм!

10 голосов
/ 12 октября 2017

Я не смог получить ответ Дэвида Чу , чтобы работать для элемента 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>
5 голосов
/ 21 марта 2012

Вы не можете сделать это с одним макетом, я пробовал. В итоге я написал очень простой класс для обработки, вы можете проверить это на github. SquareImage.java Это часть более крупного проекта, но ничего, что можно скопировать и вставить, не может быть исправлено (лицензировано в Apache 2.0)

По сути, вам просто нужно установить высоту / ширину, равную другому измерению (в зависимости от того, как вы хотите его масштабировать)

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

4 голосов
/ 22 августа 2017

В 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 в ваш проект.

3 голосов
/ 21 сентября 2013

Чтобы установить 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();
2 голосов
/ 12 июня 2017

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

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

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

Создание отзывчивого пользовательского интерфейса с ConstraintLayout

Более того, к настоящему времени PercentRelativeLayout устарел (см. Документация по Android ).

1 голос
/ 23 августа 2014

Вот как я решил эту проблему:

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

Предварительный просмотр - imageView с шириной, установленной в «match_parent» и scaleType в «cropCenter»

picture - Растровый объект, который нужно установить в imageView src.

Это хорошо работает для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...