Commit a3c8062e by hoangtc Committed by Andrew Lewis

Add support for listening to AspectRatioFrameLayout's aspect ratio update

Currently, AspectRatioFrameLayout may need to resize itself if it could not
satisfy a target aspect ratio. User may want to know when this happen, or
whether this can happen, so they can update their UI accordingly. For
example: show/hide a button to toggle different resize mode only when the
aspect ratio of the view and the content is very different.

GitHub: #3736

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=187484241
parent fdfaa029
......@@ -2,6 +2,9 @@
### dev-v2 (not yet released) ###
* UI components:
* Add support for listening to `AspectRatioFrameLayout`'s aspect ratio update
([#3736](https://github.com/google/ExoPlayer/issues/3736)).
* Gradle: Replace 'compile' configuration (deprecated) with 'implementation' and
'api'. Note: This may lead to build breakage for applications upgrading from
previous version that rely on indirect dependency for certain modules. In such
......
......@@ -28,6 +28,22 @@ import java.lang.annotation.RetentionPolicy;
*/
public final class AspectRatioFrameLayout extends FrameLayout {
/** Listener to be notified about changes of the aspect ratios of this view. */
public interface AspectRatioListener {
/**
* Called when either the target aspect ratio or the view aspect ratio is updated.
*
* @param targetAspectRatio The aspect ratio that has been set in {@link #setAspectRatio(float)}
* @param naturalAspectRatio The natural aspect ratio of this view (before its width and height
* are modified to satisfy the target aspect ratio).
* @param aspectRatioMismatch Whether the target and natural aspect ratios differ enough for
* changing the resize mode to have an effect.
*/
void onAspectRatioUpdated(
float targetAspectRatio, float naturalAspectRatio, boolean aspectRatioMismatch);
}
// LINT.IfChange
/** Resize modes for {@link AspectRatioFrameLayout}. */
@Retention(RetentionPolicy.SOURCE)
......@@ -73,8 +89,12 @@ public final class AspectRatioFrameLayout extends FrameLayout {
*/
private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;
private final AspectRatioUpdateDispatcher aspectRatioUpdateDispatcher;
private AspectRatioListener aspectRatioListener;
private float videoAspectRatio;
private int resizeMode;
private @ResizeMode int resizeMode;
public AspectRatioFrameLayout(Context context) {
this(context, null);
......@@ -92,6 +112,7 @@ public final class AspectRatioFrameLayout extends FrameLayout {
a.recycle();
}
}
aspectRatioUpdateDispatcher = new AspectRatioUpdateDispatcher();
}
/**
......@@ -107,6 +128,15 @@ public final class AspectRatioFrameLayout extends FrameLayout {
}
/**
* Sets the {@link AspectRatioListener}.
*
* @param listener The listener to be notified about aspect ratios changes.
*/
public void setAspectRatioListener(AspectRatioListener listener) {
this.aspectRatioListener = listener;
}
/**
* Returns the resize mode.
*/
public @ResizeMode int getResizeMode() {
......@@ -128,7 +158,7 @@ public final class AspectRatioFrameLayout extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (resizeMode == RESIZE_MODE_FILL || videoAspectRatio <= 0) {
if (videoAspectRatio <= 0) {
// Aspect ratio not set.
return;
}
......@@ -139,6 +169,7 @@ public final class AspectRatioFrameLayout extends FrameLayout {
float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
// We're within the allowed tolerance.
aspectRatioUpdateDispatcher.scheduleUpdate(videoAspectRatio, viewAspectRatio, false);
return;
}
......@@ -156,16 +187,51 @@ public final class AspectRatioFrameLayout extends FrameLayout {
height = (int) (width / videoAspectRatio);
}
break;
default:
case RESIZE_MODE_FIT:
if (aspectDeformation > 0) {
height = (int) (width / videoAspectRatio);
} else {
width = (int) (height * videoAspectRatio);
}
break;
case RESIZE_MODE_FILL:
default:
// Ignore target aspect ratio
break;
}
aspectRatioUpdateDispatcher.scheduleUpdate(videoAspectRatio, viewAspectRatio, true);
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
/** Dispatches updates to {@link AspectRatioListener}. */
private final class AspectRatioUpdateDispatcher implements Runnable {
private float targetAspectRatio;
private float naturalAspectRatio;
private boolean aspectRatioMismatch;
private boolean isScheduled;
public void scheduleUpdate(
float targetAspectRatio, float naturalAspectRatio, boolean aspectRatioMismatch) {
this.targetAspectRatio = targetAspectRatio;
this.naturalAspectRatio = naturalAspectRatio;
this.aspectRatioMismatch = aspectRatioMismatch;
if (!isScheduled) {
isScheduled = true;
post(this);
}
}
@Override
public void run() {
isScheduled = false;
if (aspectRatioListener == null) {
return;
}
aspectRatioListener.onAspectRatioUpdated(
targetAspectRatio, naturalAspectRatio, aspectRatioMismatch);
}
}
}
......@@ -478,6 +478,12 @@ public class PlayerView extends FrameLayout {
contentFrame.setResizeMode(resizeMode);
}
/** Returns the resize mode. */
public @ResizeMode int getResizeMode() {
Assertions.checkState(contentFrame != null);
return contentFrame.getResizeMode();
}
/** Returns whether artwork is displayed if present in the media. */
public boolean getUseArtwork() {
return useArtwork;
......@@ -751,6 +757,17 @@ public class PlayerView extends FrameLayout {
}
/**
* Set the {@link AspectRatioFrameLayout.AspectRatioListener}.
*
* @param listener The listener to be notified about aspect ratios changes of the video content or
* the content frame.
*/
public void setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener listener) {
Assertions.checkState(contentFrame != null);
contentFrame.setAspectRatioListener(listener);
}
/**
* Gets the view onto which video is rendered. This is a:
*
* <ul>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment