2016-11-08 8 views
3

Мне нужно установить Bitmap в ImageView, чтобы сохранить соотношение 16: 9. У тебя есть какой-нибудь совет? Главное решение, вероятно, в методе переопределения onMeasure пользовательского ImageView, но как?Android ImageView - 16: 9

+0

Возможный дубликат [Как установить изображение в процентах Относительная компоновка к следующему коэффициенту на основе размера экрана устройства, 16: 9,1: 1,3: 2,2: 1,4: 3] (https: //stackoverflow.com/questions/36305054/how-to-set-imageview-in-percent-relative-layout-to-following-ratios-based-on-de) –

ответ

2
public class CustomImageView extends ImageView { 

    // some other necessary things 

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

     int width = getMeasuredWidth(); 

     //force a 16:9 aspect ratio    
     int height = Math.round(width * .5625f); 
     setMeasuredDimension(width, height); 
    } 
} 

Затем в XML

<path.to.package.CustomImageView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:src="@drawable/img"/> 
2

EDIT: Google официально осуждается библиотеку Процент поддержки начиная API 26, и вы должны отойти от него как можно скорее.

Установить размер как отношение Вы можете установить размер представления в таком соотношении, как 16: 9, если по крайней мере, один из размеров просмотра установлен в положение «соответствует ограничениям» (0dp). Чтобы включить коэффициент, нажмите «Переключить соотношение сторон изображения» (выноска 1 на рисунке 10), а затем введите соотношение ширины и высоты на появившемся входе.

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

Например, если вы установили обе стороны на «ограничения соответствия», дважды нажмите «Переключить соотношение сторон изображения», чтобы установить ширину как отношение высоты. Теперь весь размер определяется высотой представления (который может быть определен в любом случае), как показано на рисунке ниже:

The view is set to a 16:9 aspect with the width based on a ratio of the height.

Более подробная информация здесь: https://developer.android.com/training/constraint-layout/index.html#adjust-the-view-size


В библиотеке поддержки есть что-то под названием PercentFrameLayout и PercentRelativeLayout.

<android.support.percent.PercentFrameLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 
    <ImageView 
    app:layout_widthPercent="100%" 
    app:layout_aspectRatio="178%" 
    android:scaleType="centerCrop" 
    android:src="@drawable/header_background"/> 
    <!-- The rest of your layout --> 
</android.support.percent.PercentRelativeLayout> 

Если вы внимательно посмотрите на выше макет, вы увидите, что ImageView в вопросе (который должен быть установлен на 16: 9) обернута вокруг PercentFrameLayout и есть два атрибута, установленные на ImageView, что вы, возможно, не видели раньше:

app:layout_widthPercent="100%" 
app:layout_aspectRatio="178%" 

So (1), необходимо определить один из размеров (ширины или высоты), чтобы быть ведущим размер для рассматриваемого нашего ImageView. В этом случае ImageView будет расширяться вертикально, до максимальной ширины (например, android:layout_width="match_parent") И (2) вам нужно установить соотношение сторон в процентах (отсюда и название библиотеки), которое в этом случае составляет 178% (16/9 = 1,77777777778 или более просто положить 1,78: 1 или 178%).

Подробнее о библиотеке поддержки процентов here.

1

Выше ответы не работает для меня, я нашел это и работал:

public class AspectRatioImageView extends ImageView { 
    // NOTE: These must be kept in sync with the AspectRatioImageView attributes in attrs.xml. 
    public static final int MEASUREMENT_WIDTH = 0; 
    public static final int MEASUREMENT_HEIGHT = 1; 

    private static final float DEFAULT_ASPECT_RATIO = 1f; 
    private static final boolean DEFAULT_ASPECT_RATIO_ENABLED = false; 
    private static final int DEFAULT_DOMINANT_MEASUREMENT = MEASUREMENT_WIDTH; 

    private float aspectRatio; 
    private boolean aspectRatioEnabled; 
    private int dominantMeasurement; 

    public AspectRatioImageView(Context context) { 
    this(context, null); 
    } 

    public AspectRatioImageView(Context context, AttributeSet attrs) { 
    super(context, attrs); 

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AspectRatioImageView); 
    aspectRatio = a.getFloat(R.styleable.AspectRatioImageView_aspectRatio, DEFAULT_ASPECT_RATIO); 
    aspectRatioEnabled = a.getBoolean(R.styleable.AspectRatioImageView_aspectRatioEnabled, 
     DEFAULT_ASPECT_RATIO_ENABLED); 
    dominantMeasurement = a.getInt(R.styleable.AspectRatioImageView_dominantMeasurement, 
     DEFAULT_DOMINANT_MEASUREMENT); 
    a.recycle(); 
    } 

    @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    if (!aspectRatioEnabled) return; 

    int newWidth; 
    int newHeight; 
    switch (dominantMeasurement) { 
     case MEASUREMENT_WIDTH: 
     newWidth = getMeasuredWidth(); 
     newHeight = (int) (newWidth/aspectRatio); 
     break; 

     case MEASUREMENT_HEIGHT: 
     newHeight = getMeasuredHeight(); 
     newWidth = (int) (newHeight * aspectRatio); 
     break; 

     default: 
     throw new IllegalStateException("Unknown measurement with ID " + dominantMeasurement); 
    } 

    setMeasuredDimension(newWidth, newHeight); 
    } 

    /** Get the aspect ratio for this image view. */ 
    public float getAspectRatio() { 
    return aspectRatio; 
    } 

    /** Set the aspect ratio for this image view. This will update the view instantly. */ 
    public void setAspectRatio(float aspectRatio) { 
    this.aspectRatio = aspectRatio; 
    if (aspectRatioEnabled) { 
     requestLayout(); 
    } 
    } 

    /** Get whether or not forcing the aspect ratio is enabled. */ 
    public boolean getAspectRatioEnabled() { 
    return aspectRatioEnabled; 
    } 

    /** set whether or not forcing the aspect ratio is enabled. This will re-layout the view. */ 
    public void setAspectRatioEnabled(boolean aspectRatioEnabled) { 
    this.aspectRatioEnabled = aspectRatioEnabled; 
    requestLayout(); 
    } 

    /** Get the dominant measurement for the aspect ratio. */ 
    public int getDominantMeasurement() { 
    return dominantMeasurement; 
    } 

    /** 
    * Set the dominant measurement for the aspect ratio. 
    * 
    * @see #MEASUREMENT_WIDTH 
    * @see #MEASUREMENT_HEIGHT 
    */ 
    public void setDominantMeasurement(int dominantMeasurement) { 
    if (dominantMeasurement != MEASUREMENT_HEIGHT && dominantMeasurement != MEASUREMENT_WIDTH) { 
     throw new IllegalArgumentException("Invalid measurement type."); 
    } 
    this.dominantMeasurement = dominantMeasurement; 
    requestLayout(); 
    } 
} 

Примечание: Один Simbol * изменяется на / (читать комментарии в источнике) И это в /values/attrs.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="AspectRatioImageView"> 
     <attr name="aspectRatio" format="float" /> 
     <attr name="aspectRatioEnabled" format="boolean" /> 
     <attr name="dominantMeasurement"> 
      <enum name="width" value="0" /> 
      <enum name="height" value="1" /> 
     </attr> 
    </declare-styleable> 
</resources> 

Затем вы можете использовать этот способ в макете (AspectRatio = ширина/высота):

<com.yourpackage.ui.classes.AspectRatioImageView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:scaleType="centerCrop" 
     app:aspectRatio="1.78" 
     app:aspectRatioEnabled="true" 
     app:dominantMeasurement="width" /> 

Source

9

С PercentFrameLayout и PercentRelativeLayout были устаревшими в уровне API 26.0.0, я предлагаю вам рассмотреть использование ConstraintLayout сохранить соотношение 16: 9 для ImageView. ConstraintLayout - действительно мощный инструмент для создания адаптивного интерфейса для платформы Android, вы можете найти более подробную информацию здесь Build a Responsive UI with ConstraintLayout.

Вот пример того, как построить свой ImageView в ConstraintLayout держать 16: 9 соотношение:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <ImageView 
     android:id="@+id/imageView" 
     android:layout_width="0dp" 
     android:layout_height="0dp" 
     android:layout_marginEnd="0dp" 
     android:layout_marginStart="0dp" 
     android:layout_marginTop="0dp" 
     app:srcCompat="@mipmap/ic_launcher" 
     app:layout_constraintDimensionRatio="H,16:9" 
     app:layout_constraintStart_toStartOf="parent" 
     app:layout_constraintEnd_toEndOf="parent" 
     app:layout_constraintTop_toTopOf="parent" /> 

</android.support.constraint.ConstraintLayout> 

Не забудьте добавить constraint-layout зависимость к build.gradle файла вашего модуля

implementation "com.android.support.constraint:constraint-layout:1.0.2" 

Или вместо редактирования файла XML отредактируйте свой макет непосредственно в редакторе макета:

Layout Editor