252 lines
8.0 KiB
Java
252 lines
8.0 KiB
Java
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.view;
|
|
|
|
import static android.view.InsetsAnimationControlImplProto.CURRENT_ALPHA;
|
|
import static android.view.InsetsAnimationControlImplProto.IS_CANCELLED;
|
|
import static android.view.InsetsAnimationControlImplProto.IS_FINISHED;
|
|
import static android.view.InsetsAnimationControlImplProto.PENDING_ALPHA;
|
|
import static android.view.InsetsAnimationControlImplProto.PENDING_FRACTION;
|
|
import static android.view.InsetsAnimationControlImplProto.PENDING_INSETS;
|
|
import static android.view.InsetsAnimationControlImplProto.SHOWN_ON_FINISH;
|
|
import static android.view.InsetsAnimationControlImplProto.TMP_MATRIX;
|
|
import static android.view.InsetsController.ANIMATION_TYPE_RESIZE;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.animation.ValueAnimator;
|
|
import android.annotation.Nullable;
|
|
import android.graphics.Insets;
|
|
import android.graphics.Rect;
|
|
import android.util.SparseArray;
|
|
import android.util.proto.ProtoOutputStream;
|
|
import android.view.InsetsController.LayoutInsetsDuringAnimation;
|
|
import android.view.WindowInsets.Type.InsetsType;
|
|
import android.view.WindowInsetsAnimation.Bounds;
|
|
import android.view.animation.Interpolator;
|
|
import android.view.inputmethod.ImeTracker;
|
|
|
|
/**
|
|
* Runs a fake animation of resizing insets to produce insets animation callbacks.
|
|
* @hide
|
|
*/
|
|
public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner,
|
|
InternalInsetsAnimationController, WindowInsetsAnimationControlListener {
|
|
|
|
private final InsetsState mFromState;
|
|
private final InsetsState mToState;
|
|
private final @InsetsType int mTypes;
|
|
private final WindowInsetsAnimation mAnimation;
|
|
private final InsetsAnimationControlCallbacks mController;
|
|
private ValueAnimator mAnimator;
|
|
private boolean mCancelled;
|
|
private boolean mFinished;
|
|
|
|
public InsetsResizeAnimationRunner(Rect frame, InsetsState fromState, InsetsState toState,
|
|
Interpolator interpolator, long duration, @InsetsType int types,
|
|
InsetsAnimationControlCallbacks controller) {
|
|
mFromState = fromState;
|
|
mToState = toState;
|
|
mTypes = types;
|
|
mController = controller;
|
|
mAnimation = new WindowInsetsAnimation(types, interpolator, duration);
|
|
mAnimation.setAlpha(1f);
|
|
final Insets fromInsets = fromState.calculateInsets(
|
|
frame, types, false /* ignoreVisibility */);
|
|
final Insets toInsets = toState.calculateInsets(
|
|
frame, types, false /* ignoreVisibility */);
|
|
controller.startAnimation(this, this, types, mAnimation,
|
|
new Bounds(Insets.min(fromInsets, toInsets), Insets.max(fromInsets, toInsets)));
|
|
}
|
|
|
|
@Override
|
|
public int getTypes() {
|
|
return mTypes;
|
|
}
|
|
|
|
@Override
|
|
public int getControllingTypes() {
|
|
return mTypes;
|
|
}
|
|
|
|
@Override
|
|
public WindowInsetsAnimation getAnimation() {
|
|
return mAnimation;
|
|
}
|
|
|
|
@Override
|
|
public int getAnimationType() {
|
|
return ANIMATION_TYPE_RESIZE;
|
|
}
|
|
|
|
@Override
|
|
@Nullable
|
|
public ImeTracker.Token getStatsToken() {
|
|
// Return null as resizing the IME view is not explicitly tracked.
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void cancel() {
|
|
if (mCancelled || mFinished) {
|
|
return;
|
|
}
|
|
mCancelled = true;
|
|
if (mAnimator != null) {
|
|
mAnimator.cancel();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isCancelled() {
|
|
return mCancelled;
|
|
}
|
|
|
|
@Override
|
|
public void onReady(WindowInsetsAnimationController controller, int types) {
|
|
if (mCancelled) {
|
|
return;
|
|
}
|
|
mAnimator = ValueAnimator.ofFloat(0f, 1f);
|
|
mAnimator.setDuration(mAnimation.getDurationMillis());
|
|
mAnimator.addUpdateListener(animation -> {
|
|
mAnimation.setFraction(animation.getAnimatedFraction());
|
|
mController.scheduleApplyChangeInsets(InsetsResizeAnimationRunner.this);
|
|
});
|
|
mAnimator.addListener(new AnimatorListenerAdapter() {
|
|
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
mFinished = true;
|
|
mController.scheduleApplyChangeInsets(InsetsResizeAnimationRunner.this);
|
|
}
|
|
});
|
|
mAnimator.start();
|
|
}
|
|
|
|
@Override
|
|
public boolean applyChangeInsets(InsetsState outState) {
|
|
if (mCancelled) {
|
|
return false;
|
|
}
|
|
final float fraction = mAnimation.getInterpolatedFraction();
|
|
InsetsState.traverse(mFromState, mToState, new InsetsState.OnTraverseCallbacks() {
|
|
@Override
|
|
public void onIdMatch(InsetsSource fromSource, InsetsSource toSource) {
|
|
final Rect fromFrame = fromSource.getFrame();
|
|
final Rect toFrame = toSource.getFrame();
|
|
final Rect frame = new Rect(
|
|
(int) (fromFrame.left + fraction * (toFrame.left - fromFrame.left)),
|
|
(int) (fromFrame.top + fraction * (toFrame.top - fromFrame.top)),
|
|
(int) (fromFrame.right + fraction * (toFrame.right - fromFrame.right)),
|
|
(int) (fromFrame.bottom + fraction * (toFrame.bottom - fromFrame.bottom)));
|
|
final InsetsSource source =
|
|
new InsetsSource(fromSource.getId(), fromSource.getType());
|
|
source.setFrame(frame);
|
|
source.setVisible(toSource.isVisible());
|
|
outState.addSource(source);
|
|
}
|
|
});
|
|
if (mFinished) {
|
|
mController.notifyFinished(this, true /* shown */);
|
|
}
|
|
return mFinished;
|
|
}
|
|
|
|
@Override
|
|
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
|
|
final long token = proto.start(fieldId);
|
|
proto.write(IS_CANCELLED, mCancelled);
|
|
proto.write(IS_FINISHED, mFinished);
|
|
proto.write(TMP_MATRIX, "null");
|
|
proto.write(PENDING_INSETS, "null");
|
|
proto.write(PENDING_FRACTION, mAnimation.getInterpolatedFraction());
|
|
proto.write(SHOWN_ON_FINISH, true);
|
|
proto.write(CURRENT_ALPHA, 1f);
|
|
proto.write(PENDING_ALPHA, 1f);
|
|
proto.end(token);
|
|
}
|
|
|
|
@Override
|
|
public Insets getHiddenStateInsets() {
|
|
return Insets.NONE;
|
|
}
|
|
|
|
@Override
|
|
public Insets getShownStateInsets() {
|
|
return Insets.NONE;
|
|
}
|
|
|
|
@Override
|
|
public Insets getCurrentInsets() {
|
|
return Insets.NONE;
|
|
}
|
|
|
|
@Override
|
|
public float getCurrentFraction() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public float getCurrentAlpha() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void setInsetsAndAlpha(Insets insets, float alpha, float fraction) {
|
|
}
|
|
|
|
@Override
|
|
public void finish(boolean shown) {
|
|
}
|
|
|
|
@Override
|
|
public boolean isFinished() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void notifyControlRevoked(int types) {
|
|
}
|
|
|
|
@Override
|
|
public void updateSurfacePosition(SparseArray<InsetsSourceControl> controls) {
|
|
}
|
|
|
|
@Override
|
|
public boolean hasZeroInsetsIme() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void setReadyDispatched(boolean dispatched) {
|
|
}
|
|
|
|
@Override
|
|
public void onFinished(WindowInsetsAnimationController controller) {
|
|
}
|
|
|
|
@Override
|
|
public void onCancelled(WindowInsetsAnimationController controller) {
|
|
}
|
|
|
|
@Override
|
|
public void updateLayoutInsetsDuringAnimation(
|
|
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
|
|
}
|
|
}
|