Merge "Revert "Revert "Defer updating InsetsSource.mFrame while animating""" into rvc-dev am: a775f45d85 am: 911ce402a4 am: 67658867a1
Change-Id: Icf249688c2c6008dc4b776e03e961dad7a832fb2
This commit is contained in:
@@ -18,6 +18,7 @@ package android.view;
|
||||
|
||||
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_IME;
|
||||
import static android.view.InsetsState.toInternalType;
|
||||
import static android.view.InsetsState.toPublicType;
|
||||
import static android.view.WindowInsets.Type.all;
|
||||
import static android.view.WindowInsets.Type.ime;
|
||||
@@ -471,7 +472,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
if (!localStateChanged && mLastDispachedState.equals(state)) {
|
||||
return false;
|
||||
}
|
||||
mState.set(state);
|
||||
updateState(state);
|
||||
mLastDispachedState.set(state, true /* copySources */);
|
||||
applyLocalVisibilityOverride();
|
||||
if (localStateChanged) {
|
||||
@@ -480,11 +481,25 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
|
||||
sendStateToWindowManager();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateState(InsetsState newState) {
|
||||
mState.setDisplayFrame(newState.getDisplayFrame());
|
||||
for (int i = newState.getSourcesCount() - 1; i >= 0; i--) {
|
||||
InsetsSource source = newState.sourceAt(i);
|
||||
getSourceConsumer(source.getType()).updateSource(source);
|
||||
}
|
||||
for (int i = mState.getSourcesCount() - 1; i >= 0; i--) {
|
||||
InsetsSource source = mState.sourceAt(i);
|
||||
if (newState.peekSource(source.getType()) == null) {
|
||||
mState.removeSource(source.getType());
|
||||
}
|
||||
}
|
||||
if (mCaptionInsetsHeight != 0) {
|
||||
mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
|
||||
mFrame.right, mFrame.top + mCaptionInsetsHeight));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean captionInsetsUnchanged() {
|
||||
@@ -879,8 +894,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
control.cancel();
|
||||
}
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
if (mRunningAnimations.get(i).runner == control) {
|
||||
RunningAnimation runningAnimation = mRunningAnimations.get(i);
|
||||
if (runningAnimation.runner == control) {
|
||||
mRunningAnimations.remove(i);
|
||||
ArraySet<Integer> types = toInternalType(control.getTypes());
|
||||
for (int j = types.size() - 1; j >= 0; j--) {
|
||||
if (getSourceConsumer(types.valueAt(j)).notifyAnimationFinished()) {
|
||||
mViewRoot.notifyInsetsChanged();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
|
||||
import static android.view.InsetsController.AnimationType;
|
||||
import static android.view.InsetsState.toPublicType;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
@@ -64,6 +66,8 @@ public class InsetsSourceConsumer {
|
||||
private final Supplier<Transaction> mTransactionSupplier;
|
||||
private @Nullable InsetsSourceControl mSourceControl;
|
||||
private boolean mHasWindowFocus;
|
||||
private Rect mPendingFrame;
|
||||
private Rect mPendingVisibleFrame;
|
||||
|
||||
public InsetsSourceConsumer(@InternalInsetsType int type, InsetsState state,
|
||||
Supplier<Transaction> transactionSupplier, InsetsController controller) {
|
||||
@@ -215,6 +219,38 @@ public class InsetsSourceConsumer {
|
||||
// no-op for types that always return ShowResult#SHOW_IMMEDIATELY.
|
||||
}
|
||||
|
||||
void updateSource(InsetsSource newSource) {
|
||||
InsetsSource source = mState.peekSource(mType);
|
||||
if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE
|
||||
|| source.getFrame().equals(newSource.getFrame())) {
|
||||
mState.addSource(newSource);
|
||||
return;
|
||||
}
|
||||
|
||||
// Frame is changing while animating. Keep note of the new frame but keep existing frame
|
||||
// until animaition is finished.
|
||||
newSource = new InsetsSource(newSource);
|
||||
mPendingFrame = new Rect(newSource.getFrame());
|
||||
mPendingVisibleFrame = newSource.getVisibleFrame() != null
|
||||
? new Rect(newSource.getVisibleFrame())
|
||||
: null;
|
||||
newSource.setFrame(source.getFrame());
|
||||
newSource.setVisibleFrame(source.getVisibleFrame());
|
||||
mState.addSource(newSource);
|
||||
}
|
||||
|
||||
boolean notifyAnimationFinished() {
|
||||
if (mPendingFrame != null) {
|
||||
InsetsSource source = mState.getSource(mType);
|
||||
source.setFrame(mPendingFrame);
|
||||
source.setVisibleFrame(mPendingVisibleFrame);
|
||||
mPendingFrame = null;
|
||||
mPendingVisibleFrame = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets requested visibility from the client, regardless of whether we are able to control it at
|
||||
* the moment.
|
||||
|
||||
@@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -638,7 +639,31 @@ public class InsetsControllerTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFrameUpdateDuringAnimation() {
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_IME));
|
||||
|
||||
// Pretend IME is calling
|
||||
mController.show(ime(), true /* fromIme */);
|
||||
|
||||
InsetsState copy = new InsetsState(mController.getState(), true /* copySources */);
|
||||
copy.getSource(ITYPE_IME).setFrame(0, 1, 2, 3);
|
||||
copy.getSource(ITYPE_IME).setVisibleFrame(new Rect(4, 5, 6, 7));
|
||||
mController.onStateChanged(copy);
|
||||
assertNotEquals(new Rect(0, 1, 2, 3),
|
||||
mController.getState().getSource(ITYPE_IME).getFrame());
|
||||
assertNotEquals(new Rect(4, 5, 6, 7),
|
||||
mController.getState().getSource(ITYPE_IME).getVisibleFrame());
|
||||
mController.cancelExistingAnimation();
|
||||
assertEquals(new Rect(0, 1, 2, 3),
|
||||
mController.getState().getSource(ITYPE_IME).getFrame());
|
||||
assertEquals(new Rect(4, 5, 6, 7),
|
||||
mController.getState().getSource(ITYPE_IME).getVisibleFrame());
|
||||
});
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptionInsetsStateAssemble() {
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.google.android.test.windowinsetstests;
|
||||
|
||||
import static android.view.WindowInsets.Type.ime;
|
||||
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
@@ -31,6 +30,7 @@ import android.content.Context;
|
||||
import android.graphics.Insets;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
@@ -44,11 +44,11 @@ import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class WindowInsetsActivity extends AppCompatActivity {
|
||||
|
||||
private View mRoot;
|
||||
@@ -191,6 +191,40 @@ public class WindowInsetsActivity extends AppCompatActivity {
|
||||
mTransitions.forEach(it -> it.onFinish(animation));
|
||||
}
|
||||
});
|
||||
|
||||
findViewById(R.id.floating_action_button).setOnClickListener(
|
||||
v -> v.getWindowInsetsController().controlWindowInsetsAnimation(ime(), -1,
|
||||
new LinearInterpolator(), null /* cancellationSignal */,
|
||||
new WindowInsetsAnimationControlListener() {
|
||||
@Override
|
||||
public void onReady(
|
||||
WindowInsetsAnimationController controller,
|
||||
int types) {
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
|
||||
anim.setDuration(1500);
|
||||
anim.addUpdateListener(animation
|
||||
-> controller.setInsetsAndAlpha(
|
||||
controller.getShownStateInsets(),
|
||||
(float) animation.getAnimatedValue(),
|
||||
anim.getAnimatedFraction()));
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
controller.finish(true);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(WindowInsetsAnimationController controller) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinished(WindowInsetsAnimationController controller) {
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,57 +234,6 @@ public class WindowInsetsActivity extends AppCompatActivity {
|
||||
getWindow().getDecorView().post(() -> getWindow().setDecorFitsSystemWindows(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
getWindow().getInsetsController().addOnControllableInsetsChangedListener(
|
||||
new OnControllableInsetsChangedListener() {
|
||||
|
||||
boolean hasControl = false;
|
||||
@Override
|
||||
public void onControllableInsetsChanged(WindowInsetsController controller,
|
||||
int types) {
|
||||
if ((types & ime()) != 0 && !hasControl) {
|
||||
hasControl = true;
|
||||
controller.controlWindowInsetsAnimation(ime(), -1,
|
||||
new LinearInterpolator(), null /* cancellationSignal */,
|
||||
new WindowInsetsAnimationControlListener() {
|
||||
@Override
|
||||
public void onReady(
|
||||
WindowInsetsAnimationController controller,
|
||||
int types) {
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
|
||||
anim.setDuration(1500);
|
||||
anim.addUpdateListener(animation
|
||||
-> controller.setInsetsAndAlpha(
|
||||
controller.getShownStateInsets(),
|
||||
(float) animation.getAnimatedValue(),
|
||||
anim.getAnimatedFraction()));
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
controller.finish(true);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinished(
|
||||
WindowInsetsAnimationController controller) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(
|
||||
WindowInsetsAnimationController controller) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static class Transition {
|
||||
private int mEndBottom;
|
||||
private int mStartBottom;
|
||||
|
||||
Reference in New Issue
Block a user