Introduce resize mode for AspectRatioFrameLayout.

https://github.com/google/ExoPlayer/issues/1827

Three different modes available: fit (default), fixed_width, fixed_height
Developers need to use wrap_content for the dimension which is not fixed:

app:resize_mode="fixed_width"
android:layout_width="320dp"
android:layout_height="wrap_content"

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=135264861
This commit is contained in:
[]inger 2016-10-05 12:31:32 -07:00 committed by Oliver Woodman
parent 2cf339e095
commit 053dc27a3e
3 changed files with 83 additions and 5 deletions

View file

@ -16,14 +16,30 @@
package com.google.android.exoplayer2.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import com.google.android.exoplayer2.R;
/**
* A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
*/
public final class AspectRatioFrameLayout extends FrameLayout {
/**
* Either the width or height is decreased to obtain the desired aspect ratio.
*/
public static final int RESIZE_MODE_FIT = 0;
/**
* The width is fixed and the height is increased or decreased to obtain the desired aspect ratio.
*/
public static final int RESIZE_MODE_FIXED_WIDTH = 1;
/**
* The height is fixed and the width is increased or decreased to obtain the desired aspect ratio.
*/
public static final int RESIZE_MODE_FIXED_HEIGHT = 2;
/**
* The {@link FrameLayout} will not resize itself if the fractional difference between its natural
* aspect ratio and the requested aspect ratio falls below this threshold.
@ -36,13 +52,24 @@ public final class AspectRatioFrameLayout extends FrameLayout {
private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;
private float videoAspectRatio;
private int resizeMode;
public AspectRatioFrameLayout(Context context) {
super(context);
this(context, null);
}
public AspectRatioFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
resizeMode = RESIZE_MODE_FIT;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.AspectRatioFrameLayout, 0, 0);
try {
resizeMode = a.getInt(R.styleable.AspectRatioFrameLayout_resize_mode, RESIZE_MODE_FIT);
} finally {
a.recycle();
}
}
}
/**
@ -57,6 +84,19 @@ public final class AspectRatioFrameLayout extends FrameLayout {
}
}
/**
* Sets the resize mode which can be of value {@link #RESIZE_MODE_FIT},
* {@link #RESIZE_MODE_FIXED_HEIGHT} or {@link #RESIZE_MODE_FIXED_WIDTH}.
*
* @param resizeMode The resize mode.
*/
public void setResizeMode(int resizeMode) {
if (this.resizeMode != resizeMode) {
this.resizeMode = resizeMode;
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@ -74,10 +114,20 @@ public final class AspectRatioFrameLayout extends FrameLayout {
return;
}
if (aspectDeformation > 0) {
height = (int) (width / videoAspectRatio);
} else {
width = (int) (height * videoAspectRatio);
switch (resizeMode) {
case RESIZE_MODE_FIXED_WIDTH:
height = (int) (width / videoAspectRatio);
break;
case RESIZE_MODE_FIXED_HEIGHT:
width = (int) (height * videoAspectRatio);
break;
default:
if (aspectDeformation > 0) {
height = (int) (width / videoAspectRatio);
} else {
width = (int) (height * videoAspectRatio);
}
break;
}
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));

View file

@ -63,6 +63,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
super(context, attrs, defStyleAttr);
boolean useTextureView = false;
int resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SimpleExoPlayerView, 0, 0);
@ -70,6 +71,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
useController = a.getBoolean(R.styleable.SimpleExoPlayerView_use_controller, useController);
useTextureView = a.getBoolean(R.styleable.SimpleExoPlayerView_use_texture_view,
useTextureView);
resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode,
AspectRatioFrameLayout.RESIZE_MODE_FIT);
} finally {
a.recycle();
}
@ -78,6 +81,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
LayoutInflater.from(context).inflate(R.layout.exo_simple_player_view, this);
componentListener = new ComponentListener();
layout = (AspectRatioFrameLayout) findViewById(R.id.video_frame);
layout.setResizeMode(resizeMode);
controller = (PlaybackControlView) findViewById(R.id.control);
shutterView = findViewById(R.id.shutter);
subtitleLayout = (SubtitleView) findViewById(R.id.subtitles);
@ -147,6 +151,17 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
}
/**
* Sets the resize mode which can be of value {@link AspectRatioFrameLayout#RESIZE_MODE_FIT},
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_HEIGHT} or
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_WIDTH}.
*
* @param resizeMode The resize mode.
*/
public void setResizeMode(int resizeMode) {
layout.setResizeMode(resizeMode);
}
/**
* Set the {@link PlaybackControlView.VisibilityListener}.
*

View file

@ -14,8 +14,21 @@
limitations under the License.
-->
<resources>
<attr name="resize_mode" format="enum">
<enum name="fit" value="0"/>
<enum name="fixed_width" value="1"/>
<enum name="fixed_height" value="2"/>
</attr>
<declare-styleable name="SimpleExoPlayerView">
<attr name="use_controller" format="boolean"/>
<attr name="use_texture_view" format="boolean"/>
<attr name="resize_mode"/>
</declare-styleable>
<declare-styleable name="AspectRatioFrameLayout">
<attr name="resize_mode"/>
</declare-styleable>
</resources>