Move pip above controls when expanded or not enough space in landscape.

This commit is contained in:
Alex Hart
2024-08-06 12:08:24 -03:00
committed by mtang-signal
parent cbd587f142
commit 8dc910e71d
3 changed files with 100 additions and 23 deletions

View File

@@ -36,11 +36,14 @@ final class PictureInPictureExpansionHelper {
private Point defaultDimensions;
private Point expandedDimensions;
public PictureInPictureExpansionHelper(@NonNull View selfPip) {
this.selfPip = selfPip;
this.parent = (ViewGroup) selfPip.getParent();
this.defaultDimensions = new Point(selfPip.getLayoutParams().width, selfPip.getLayoutParams().height);
this.expandedDimensions = new Point(ViewUtil.dpToPx(EXPANDED_PIP_WIDTH_DP), ViewUtil.dpToPx(EXPANDED_PIP_HEIGHT_DP));
private final OnStateChangedListener onStateChangedListener;
public PictureInPictureExpansionHelper(@NonNull View selfPip, @NonNull OnStateChangedListener onStateChangedListener) {
this.selfPip = selfPip;
this.parent = (ViewGroup) selfPip.getParent();
this.defaultDimensions = new Point(selfPip.getLayoutParams().width, selfPip.getLayoutParams().height);
this.expandedDimensions = new Point(ViewUtil.dpToPx(EXPANDED_PIP_WIDTH_DP), ViewUtil.dpToPx(EXPANDED_PIP_HEIGHT_DP));
this.onStateChangedListener = onStateChangedListener;
}
public boolean isExpandedOrExpanding() {
@@ -82,12 +85,12 @@ final class PictureInPictureExpansionHelper {
beginResizeSelfPipTransition(expandedDimensions, new Callback() {
@Override
public void onAnimationWillStart() {
state = State.IS_EXPANDING;
setState(State.IS_EXPANDING);
}
@Override
public void onAnimationHasFinished() {
state = State.IS_EXPANDED;
setState(State.IS_EXPANDED);
}
});
}
@@ -100,12 +103,12 @@ final class PictureInPictureExpansionHelper {
beginResizeSelfPipTransition(defaultDimensions, new Callback() {
@Override
public void onAnimationWillStart() {
state = State.IS_SHRINKING;
setState(State.IS_SHRINKING);
}
@Override
public void onAnimationHasFinished() {
state = State.IS_SHRUNKEN;
setState(State.IS_SHRUNKEN);
}
});
}
@@ -136,6 +139,14 @@ final class PictureInPictureExpansionHelper {
selfPip.setLayoutParams(params);
}
private void setState(@NonNull State state) {
this.state = state;
if (onStateChangedListener != null) {
onStateChangedListener.onStateChanged(state);
}
}
enum State {
IS_EXPANDING,
IS_EXPANDED,
@@ -143,6 +154,10 @@ final class PictureInPictureExpansionHelper {
IS_SHRUNKEN
}
interface OnStateChangedListener {
void onStateChanged(@NonNull State state);
}
public interface Callback {
/**
* Called when an animation (shrink or expand) will begin. This happens before any animation

View File

@@ -45,9 +45,12 @@ public class PictureInPictureGestureHelper extends GestureDetector.SimpleOnGestu
private int maximumFlingVelocity;
private boolean isLockedToBottomEnd;
private Interpolator interpolator;
private Corner currentCornerPosition = Corner.BOTTOM_RIGHT;
private int previousTopBoundary = -1;
private int previousBottomBoundary = -1;
private Corner currentCornerPosition = Corner.BOTTOM_RIGHT;
private int previousTopBoundary = -1;
private int expandedVerticalBoundary = -1;
private int collapsedVerticalBoundary = -1;
private BoundaryState boundaryState = BoundaryState.EXPANDED;
private boolean isCollapsedStateAllowed = false;
@SuppressLint("ClickableViewAccessibility")
public static PictureInPictureGestureHelper applyTo(@NonNull View child) {
@@ -124,14 +127,47 @@ public class PictureInPictureGestureHelper extends GestureDetector.SimpleOnGestu
child.setLayoutParams(layoutParams);
}
public void setBottomVerticalBoundary(int bottomBoundary) {
if (bottomBoundary == previousBottomBoundary) {
public void setCollapsedVerticalBoundary(int bottomBoundary) {
final int oldBoundary = collapsedVerticalBoundary;
collapsedVerticalBoundary = bottomBoundary;
if (oldBoundary != bottomBoundary && boundaryState == BoundaryState.COLLAPSED) {
applyBottomVerticalBoundary(bottomBoundary);
}
}
public void setExpandedVerticalBoundary(int bottomBoundary) {
final int oldBoundary = expandedVerticalBoundary;
expandedVerticalBoundary = bottomBoundary;
if (oldBoundary != bottomBoundary && boundaryState == BoundaryState.EXPANDED) {
applyBottomVerticalBoundary(bottomBoundary);
}
}
public void setBoundaryState(@NonNull BoundaryState boundaryState) {
if (!isCollapsedStateAllowed && boundaryState == BoundaryState.COLLAPSED) {
return;
}
previousBottomBoundary = bottomBoundary;
final BoundaryState old = this.boundaryState;
this.boundaryState = boundaryState;
if (old != boundaryState) {
applyBottomVerticalBoundary(boundaryState == BoundaryState.EXPANDED ? expandedVerticalBoundary : collapsedVerticalBoundary);
}
}
public void allowCollapsedState() {
if (isCollapsedStateAllowed) {
return;
}
isCollapsedStateAllowed = true;
setBoundaryState(BoundaryState.COLLAPSED);
}
private void applyBottomVerticalBoundary(int bottomBoundary) {
extraPaddingBottom = parent.getMeasuredHeight() + parent.getTop() - bottomBoundary;
ViewUtil.setBottomMargin(child, extraPaddingBottom + framePadding);
}
@@ -405,4 +441,9 @@ public class PictureInPictureGestureHelper extends GestureDetector.SimpleOnGestu
return interpolated;
}
}
public enum BoundaryState {
EXPANDED,
COLLAPSED
}
}

View File

@@ -131,6 +131,7 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
private View missingPermissionContainer;
private MaterialButton allowAccessButton;
private Guideline callParticipantsOverflowGuideline;
private View callControlsSheet;
private WebRtcCallParticipantsPagerAdapter pagerAdapter;
private WebRtcCallParticipantsRecyclerAdapter recyclerAdapter;
@@ -210,6 +211,7 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
missingPermissionContainer = findViewById(R.id.missing_permissions_container);
allowAccessButton = findViewById(R.id.allow_access_button);
callParticipantsOverflowGuideline = findViewById(R.id.call_screen_participants_overflow_guideline);
callControlsSheet = findViewById(R.id.call_controls_info_parent);
View decline = findViewById(R.id.call_screen_decline_call);
View answerLabel = findViewById(R.id.call_screen_answer_call_label);
@@ -296,7 +298,13 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
answerWithoutVideo.setOnClickListener(v -> runIfNonNull(controlsListener, ControlsListener::onAcceptCallWithVoiceOnlyPressed));
pictureInPictureGestureHelper = PictureInPictureGestureHelper.applyTo(smallLocalRenderFrame);
pictureInPictureExpansionHelper = new PictureInPictureExpansionHelper(smallLocalRenderFrame);
pictureInPictureExpansionHelper = new PictureInPictureExpansionHelper(smallLocalRenderFrame, state -> {
if (state == PictureInPictureExpansionHelper.State.IS_SHRUNKEN) {
pictureInPictureGestureHelper.setBoundaryState(PictureInPictureGestureHelper.BoundaryState.COLLAPSED);
} else {
pictureInPictureGestureHelper.setBoundaryState(PictureInPictureGestureHelper.BoundaryState.EXPANDED);
}
});
smallLocalRenderFrame.setOnClickListener(v -> {
if (controlsListener != null) {
@@ -370,15 +378,15 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
if (getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
aboveControls.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
pictureInPictureGestureHelper.setBottomVerticalBoundary(bottom + ViewUtil.getStatusBarHeight(v));
});
} else {
SlideUpWithCallControlsBehavior behavior = (SlideUpWithCallControlsBehavior) ((CoordinatorLayout.LayoutParams) aboveControls.getLayoutParams()).getBehavior();
Objects.requireNonNull(behavior).setOnTopOfControlsChangedListener(topOfControls -> {
pictureInPictureGestureHelper.setBottomVerticalBoundary(topOfControls);
pictureInPictureGestureHelper.setCollapsedVerticalBoundary(bottom + ViewUtil.getStatusBarHeight(v));
});
}
SlideUpWithCallControlsBehavior behavior = (SlideUpWithCallControlsBehavior) ((CoordinatorLayout.LayoutParams) aboveControls.getLayoutParams()).getBehavior();
Objects.requireNonNull(behavior).setOnTopOfControlsChangedListener(topOfControls -> {
pictureInPictureGestureHelper.setExpandedVerticalBoundary(topOfControls);
});
if (callParticipantsOverflowGuideline != null) {
callParticipantsRecycler.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
callParticipantsOverflowGuideline.setGuidelineEnd(bottom - top);
@@ -386,6 +394,19 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
final int pipWidth = smallLocalRenderFrame.getMeasuredWidth();
final int controlsWidth = callControlsSheet.getMeasuredWidth();
final float protection = DimensionUnit.DP.toPixels(16 * 4);
final float requiredWidth = pipWidth + controlsWidth + protection;
if (w > h && w >= requiredWidth) {
pictureInPictureGestureHelper.allowCollapsedState();
}
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
navBarBottomInset = WindowInsetsCompat.toWindowInsetsCompat(insets).getInsets(WindowInsetsCompat.Type.navigationBars()).bottom;