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 @@ ...@@ -2,6 +2,9 @@
### dev-v2 (not yet released) ### ### 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 * Gradle: Replace 'compile' configuration (deprecated) with 'implementation' and
'api'. Note: This may lead to build breakage for applications upgrading from 'api'. Note: This may lead to build breakage for applications upgrading from
previous version that rely on indirect dependency for certain modules. In such previous version that rely on indirect dependency for certain modules. In such
......
...@@ -28,6 +28,22 @@ import java.lang.annotation.RetentionPolicy; ...@@ -28,6 +28,22 @@ import java.lang.annotation.RetentionPolicy;
*/ */
public final class AspectRatioFrameLayout extends FrameLayout { 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 // LINT.IfChange
/** Resize modes for {@link AspectRatioFrameLayout}. */ /** Resize modes for {@link AspectRatioFrameLayout}. */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
...@@ -73,8 +89,12 @@ public final class AspectRatioFrameLayout extends FrameLayout { ...@@ -73,8 +89,12 @@ public final class AspectRatioFrameLayout extends FrameLayout {
*/ */
private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f; private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;
private final AspectRatioUpdateDispatcher aspectRatioUpdateDispatcher;
private AspectRatioListener aspectRatioListener;
private float videoAspectRatio; private float videoAspectRatio;
private int resizeMode; private @ResizeMode int resizeMode;
public AspectRatioFrameLayout(Context context) { public AspectRatioFrameLayout(Context context) {
this(context, null); this(context, null);
...@@ -92,6 +112,7 @@ public final class AspectRatioFrameLayout extends FrameLayout { ...@@ -92,6 +112,7 @@ public final class AspectRatioFrameLayout extends FrameLayout {
a.recycle(); a.recycle();
} }
} }
aspectRatioUpdateDispatcher = new AspectRatioUpdateDispatcher();
} }
/** /**
...@@ -107,6 +128,15 @@ public final class AspectRatioFrameLayout extends FrameLayout { ...@@ -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. * Returns the resize mode.
*/ */
public @ResizeMode int getResizeMode() { public @ResizeMode int getResizeMode() {
...@@ -128,7 +158,7 @@ public final class AspectRatioFrameLayout extends FrameLayout { ...@@ -128,7 +158,7 @@ public final class AspectRatioFrameLayout extends FrameLayout {
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (resizeMode == RESIZE_MODE_FILL || videoAspectRatio <= 0) { if (videoAspectRatio <= 0) {
// Aspect ratio not set. // Aspect ratio not set.
return; return;
} }
...@@ -139,6 +169,7 @@ public final class AspectRatioFrameLayout extends FrameLayout { ...@@ -139,6 +169,7 @@ public final class AspectRatioFrameLayout extends FrameLayout {
float aspectDeformation = videoAspectRatio / viewAspectRatio - 1; float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) { if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
// We're within the allowed tolerance. // We're within the allowed tolerance.
aspectRatioUpdateDispatcher.scheduleUpdate(videoAspectRatio, viewAspectRatio, false);
return; return;
} }
...@@ -156,16 +187,51 @@ public final class AspectRatioFrameLayout extends FrameLayout { ...@@ -156,16 +187,51 @@ public final class AspectRatioFrameLayout extends FrameLayout {
height = (int) (width / videoAspectRatio); height = (int) (width / videoAspectRatio);
} }
break; break;
default: case RESIZE_MODE_FIT:
if (aspectDeformation > 0) { if (aspectDeformation > 0) {
height = (int) (width / videoAspectRatio); height = (int) (width / videoAspectRatio);
} else { } else {
width = (int) (height * videoAspectRatio); width = (int) (height * videoAspectRatio);
} }
break; break;
case RESIZE_MODE_FILL:
default:
// Ignore target aspect ratio
break;
} }
aspectRatioUpdateDispatcher.scheduleUpdate(videoAspectRatio, viewAspectRatio, true);
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, 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 { ...@@ -478,6 +478,12 @@ public class PlayerView extends FrameLayout {
contentFrame.setResizeMode(resizeMode); 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. */ /** Returns whether artwork is displayed if present in the media. */
public boolean getUseArtwork() { public boolean getUseArtwork() {
return useArtwork; return useArtwork;
...@@ -751,6 +757,17 @@ public class PlayerView extends FrameLayout { ...@@ -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: * Gets the view onto which video is rendered. This is a:
* *
* <ul> * <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