Merge "Fix QS expansion animations"

This commit is contained in:
TreeHugger Robot
2022-01-05 17:11:33 +00:00
committed by Android (Google) Code Review
8 changed files with 284 additions and 86 deletions

View File

@@ -34,7 +34,7 @@ public interface QS extends FragmentBase {
String ACTION = "com.android.systemui.action.PLUGIN_QS";
int VERSION = 12;
int VERSION = 13;
String TAG = "QS";
@@ -70,6 +70,11 @@ public interface QS extends FragmentBase {
void setContainerController(QSContainerController controller);
void setExpandClickListener(OnClickListener onClickListener);
/**
* Returns the height difference between the QSPanel container and the QuickQSPanel container
*/
int getHeightDiff();
View getHeader();
default void setHasNotifications(boolean hasNotifications) {

View File

@@ -20,4 +20,6 @@
android:id="@+id/qs_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
android:layout_weight="1"
android:clipChildren="false"
android:clipToPadding="false" />

View File

@@ -30,6 +30,7 @@ import com.android.systemui.qs.QSPanel.QSTileLayout;
import com.android.systemui.qs.QSPanelControllerBase.TileRecord;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class PagedTileLayout extends ViewPager implements QSTileLayout {
@@ -332,6 +333,18 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
mPageListener = listener;
}
public List<String> getSpecsForPage(int page) {
ArrayList<String> out = new ArrayList<>();
if (page < 0) return out;
int perPage = mPages.get(0).maxTiles();
int startOfPage = page * perPage;
int endOfPage = (page + 1) * perPage;
for (int i = startOfPage; i < endOfPage && i < mTiles.size(); i++) {
out.add(mTiles.get(i).tile.getTileSpec());
}
return out;
}
private void distributeTiles() {
emptyAndInflateOrRemovePages();
@@ -491,6 +504,11 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
return currentPage.mRecords.size();
}
public int getNumTilesFirstPage() {
if (mPages.size() == 0) return 0;
return mPages.get(0).mRecords.size();
}
public void startTileReveal(Set<String> tileSpecs, final Runnable postAnimation) {
if (tileSpecs.isEmpty() || mPages.size() < 2 || getScrollX() != 0 || !beginFakeDrag()) {
// Do not start the reveal animation unless there are tiles to animate, multiple
@@ -556,8 +574,9 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
updateSelected();
if (mPageIndicator == null) return;
if (mPageListener != null) {
int pageNumber = isLayoutRtl() ? mPages.size() - 1 - position : position;
mPageListener.onPageChanged(isLayoutRtl() ? position == mPages.size() - 1
: position == 0);
: position == 0, pageNumber);
}
}
@@ -575,8 +594,12 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
mPageIndicatorPosition = position + positionOffset;
mPageIndicator.setLocation(mPageIndicatorPosition);
if (mPageListener != null) {
int pageNumber = isLayoutRtl() ? mPages.size() - 1 - position : position;
mPageListener.onPageChanged(positionOffsetPixels == 0 &&
(isLayoutRtl() ? position == mPages.size() - 1 : position == 0));
(isLayoutRtl() ? position == mPages.size() - 1 : position == 0),
// Send only valid page number on integer pages
positionOffsetPixels == 0 ? pageNumber : PageListener.INVALID_PAGE
);
}
}
@@ -626,6 +649,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
};
public interface PageListener {
void onPageChanged(boolean isFirst);
int INVALID_PAGE = -1;
void onPageChanged(boolean isFirst, int pageNumber);
}
}

View File

@@ -20,6 +20,8 @@ import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FOOTER;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnLayoutChangeListener;
@@ -57,11 +59,14 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
private static final String ALLOW_FANCY_ANIMATION = "sysui_qs_fancy_anim";
private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
public static final float EXPANDED_TILE_DELAY = .86f;
private static final float EXPANDED_TILE_DELAY = .86f;
//Non first page delays
private static final float QS_TILE_LABEL_FADE_OUT_START = 0.15f;
private static final float QS_TILE_LABEL_FADE_OUT_END = 0.7f;
private static final float QQS_FADE_IN_INTERVAL = 0.1f;
public static final float SHORT_PARALLAX_AMOUNT = 0.1f;
private static final long QQS_FADE_IN_DURATION = 200L;
// Fade out faster than fade in to finish before QQS hides.
private static final long QQS_FADE_OUT_DURATION = 50L;
/**
* List of all views that will be reset when clearing animation state
@@ -86,33 +91,54 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
private PagedTileLayout mPagedLayout;
private boolean mOnFirstPage = true;
private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
private int mCurrentPage = 0;
private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
// Animator for elements in the first page, including secondary labels and qqs brightness
// slider, as well as animating the alpha of the QS tile layout (as we are tracking QQS tiles)
private TouchAnimator mFirstPageAnimator;
private TouchAnimator mFirstPageDelayedAnimator;
// TranslationX animator for QQS/QS tiles
private TouchAnimator mTranslationXAnimator;
// TranslationY animator for QS tiles (and their components) in the first page
private TouchAnimator mTranslationYAnimator;
private TouchAnimator mNonfirstPageAnimator;
private TouchAnimator mNonfirstPageDelayedAnimator;
// TranslationY animator for QQS tiles (and their components)
private TouchAnimator mQQSTranslationYAnimator;
// Animates alpha of permanent views (QS tile layout, QQS tiles) when not in first page
private TouchAnimator mNonfirstPageAlphaAnimator;
// TranslatesY the QS Tile layout using QS.getHeightDiff()
private TouchAnimator mQSTileLayoutTranslatorAnimator;
// This animates fading of SecurityFooter and media divider
private TouchAnimator mAllPagesDelayedAnimator;
// Animator for brightness slider(s)
private TouchAnimator mBrightnessAnimator;
// Animator for Footer actions in QQS
private TouchAnimator mQQSFooterActionsAnimator;
// Height animator for QQS tiles (height changing from QQS size to QS size)
private HeightExpansionAnimator mQQSTileHeightAnimator;
private HeightExpansionAnimator mOtherTilesExpandAnimator;
// Height animator for QS tile in first page but not in QQS, to present the illusion that they
// are expanding alongside the QQS tiles
private HeightExpansionAnimator mOtherFirstPageTilesHeightAnimator;
// Pair of animators for each non first page. The creation is delayed until the user first
// scrolls to that page, in order to get the proper measures and layout.
private final SparseArray<Pair<HeightExpansionAnimator, TouchAnimator>>
mNonFirstPageQSAnimators = new SparseArray<>();
private boolean mNeedsAnimatorUpdate = false;
private boolean mToShowing;
private boolean mOnKeyguard;
private boolean mAllowFancy;
private boolean mFullRows;
private int mNumQuickTiles;
private int mLastQQSTileHeight;
private float mLastPosition;
private final QSTileHost mHost;
private final Executor mExecutor;
private final TunerService mTunerService;
private boolean mShowCollapsedOnKeyguard;
private boolean mTranslateWhileExpanding;
private int mQQSTop;
private int[] mTmpLoc1 = new int[2];
private int[] mTmpLoc2 = new int[2];
@Inject
public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
@@ -213,8 +239,19 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
updateAnimators();
}
private void addNonFirstPageAnimators(int page) {
Pair<HeightExpansionAnimator, TouchAnimator> pair = createSecondaryPageAnimators(page);
mNonFirstPageQSAnimators.put(page, pair);
}
@Override
public void onPageChanged(boolean isFirst) {
public void onPageChanged(boolean isFirst, int currentPage) {
if (currentPage != INVALID_PAGE && mCurrentPage != currentPage) {
mCurrentPage = currentPage;
if (!isFirst && !mNonFirstPageQSAnimators.contains(currentPage)) {
addNonFirstPageAnimators(currentPage);
}
}
if (mOnFirstPage == isFirst) return;
if (!isFirst) {
clearAnimationState();
@@ -230,7 +267,8 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
int yOffset,
int[] temp,
TouchAnimator.Builder animatorBuilderX,
TouchAnimator.Builder animatorBuilderY
TouchAnimator.Builder animatorBuilderY,
TouchAnimator.Builder qqsAnimatorBuilderY
) {
getRelativePosition(temp, qqsView, commonParent);
int qqsPosX = temp[0];
@@ -243,7 +281,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
animatorBuilderX.addFloat(qqsView, "translationX", 0, xDiff);
animatorBuilderX.addFloat(qsView, "translationX", -xDiff, 0);
int yDiff = qsPosY - qqsPosY - yOffset;
animatorBuilderY.addFloat(qqsView, "translationY", 0, yDiff);
qqsAnimatorBuilderY.addFloat(qqsView, "translationY", 0, yDiff);
animatorBuilderY.addFloat(qsView, "translationY", -yDiff, 0);
mAllViews.add(qqsView);
mAllViews.add(qsView);
@@ -253,40 +291,47 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
mNeedsAnimatorUpdate = false;
TouchAnimator.Builder firstPageBuilder = new Builder();
TouchAnimator.Builder translationYBuilder = new Builder();
TouchAnimator.Builder qqsTranslationYBuilder = new Builder();
TouchAnimator.Builder translationXBuilder = new Builder();
TouchAnimator.Builder nonFirstPageAlphaBuilder = new Builder();
Collection<QSTile> tiles = mHost.getTiles();
int count = 0;
int[] loc1 = new int[2];
int[] loc2 = new int[2];
clearAnimationState();
mNonFirstPageQSAnimators.clear();
mAllViews.clear();
mAnimatedQsViews.clear();
mQQSTileHeightAnimator = null;
mOtherTilesExpandAnimator = null;
mOtherFirstPageTilesHeightAnimator = null;
mNumQuickTiles = mQuickQsPanel.getNumQuickTiles();
QSTileLayout tileLayout = mQsPanelController.getTileLayout();
mAllViews.add((View) tileLayout);
int height = mQs.getView() != null ? mQs.getView().getMeasuredHeight() : 0;
int heightDiff = height - mQs.getHeader().getBottom()
+ mQs.getHeader().getPaddingBottom();
int heightDiff = mQs.getHeightDiff();
if (!mTranslateWhileExpanding) {
heightDiff *= SHORT_PARALLAX_AMOUNT;
}
firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
mQSTileLayoutTranslatorAnimator = new Builder()
.addFloat(tileLayout, "translationY", heightDiff, 0)
.build();
int qqsTileHeight = 0;
mLastQQSTileHeight = 0;
if (mQsPanelController.areThereTiles()) {
for (QSTile tile : tiles) {
QSTileView tileView = mQsPanelController.getTileView(tile);
if (tileView == null) {
Log.e(TAG, "tileView is null " + tile.getTileSpec());
continue;
}
// Only animate tiles in the first page
if (mPagedLayout != null && count >= mPagedLayout.getNumTilesFirstPage()) {
break;
}
final View tileIcon = tileView.getIcon().getIconView();
View view = mQs.getView();
@@ -297,16 +342,16 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
if (quickTileView == null) continue;
getRelativePosition(loc1, quickTileView, view);
getRelativePosition(loc2, tileView, view);
int yOffset = loc2[1] - loc1[1];
int xOffset = loc2[0] - loc1[0];
getRelativePosition(mTmpLoc1, quickTileView, view);
getRelativePosition(mTmpLoc2, tileView, view);
int yOffset = mTmpLoc2[1] - mTmpLoc1[1];
int xOffset = mTmpLoc2[0] - mTmpLoc1[0];
// Offset the translation animation on the views
// (that goes from 0 to getOffsetTranslation)
int offsetWithQSBHTranslation =
yOffset - mQuickStatusBarHeader.getOffsetTranslation();
translationYBuilder.addFloat(quickTileView, "translationY", 0,
qqsTranslationYBuilder.addFloat(quickTileView, "translationY", 0,
offsetWithQSBHTranslation);
translationYBuilder.addFloat(tileView, "translationY",
-offsetWithQSBHTranslation, 0);
@@ -317,7 +362,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mQQSTileHeightAnimator == null) {
mQQSTileHeightAnimator = new HeightExpansionAnimator(this,
quickTileView.getMeasuredHeight(), tileView.getMeasuredHeight());
qqsTileHeight = quickTileView.getMeasuredHeight();
mLastQQSTileHeight = quickTileView.getMeasuredHeight();
}
mQQSTileHeightAnimator.addView(quickTileView);
@@ -329,9 +374,10 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
view,
xOffset,
yOffset,
loc1,
mTmpLoc1,
translationXBuilder,
translationYBuilder
translationYBuilder,
qqsTranslationYBuilder
);
// Label containers
@@ -341,9 +387,10 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
view,
xOffset,
yOffset,
loc1,
mTmpLoc1,
translationXBuilder,
translationYBuilder
translationYBuilder,
qqsTranslationYBuilder
);
// Secondary icon
@@ -353,12 +400,15 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
view,
xOffset,
yOffset,
loc1,
mTmpLoc1,
translationXBuilder,
translationYBuilder
translationYBuilder,
qqsTranslationYBuilder
);
firstPageBuilder.addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 1);
nonFirstPageAlphaBuilder
.addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 0);
mAnimatedQsViews.add(tileView);
mAllViews.add(quickTileView);
@@ -373,16 +423,17 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
// expanding from.
SideLabelTileLayout qqsLayout =
(SideLabelTileLayout) mQuickQsPanel.getTileLayout();
getRelativePosition(loc1, qqsLayout, view);
getRelativePosition(loc2, tileView, view);
int diff = loc2[1] - (loc1[1] + qqsLayout.getPhantomTopPosition(count));
getRelativePosition(mTmpLoc1, qqsLayout, view);
mQQSTop = mTmpLoc1[1];
getRelativePosition(mTmpLoc2, tileView, view);
int diff = mTmpLoc2[1] - (mTmpLoc1[1] + qqsLayout.getPhantomTopPosition(count));
translationYBuilder.addFloat(tileView, "translationY", -diff, 0);
if (mOtherTilesExpandAnimator == null) {
mOtherTilesExpandAnimator =
if (mOtherFirstPageTilesHeightAnimator == null) {
mOtherFirstPageTilesHeightAnimator =
new HeightExpansionAnimator(
this, qqsTileHeight, tileView.getMeasuredHeight());
this, mLastQQSTileHeight, tileView.getMeasuredHeight());
}
mOtherTilesExpandAnimator.addView(tileView);
mOtherFirstPageTilesHeightAnimator.addView(tileView);
tileView.setClipChildren(true);
tileView.setClipToPadding(true);
firstPageBuilder.addFloat(tileView.getSecondaryLabel(), "alpha", 0, 1);
@@ -392,18 +443,19 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
mAllViews.add(tileView);
count++;
}
if (mCurrentPage != 0) {
addNonFirstPageAnimators(mCurrentPage);
}
}
if (mAllowFancy) {
animateBrightnessSlider(firstPageBuilder);
mFirstPageAnimator = firstPageBuilder
// Fade in the tiles/labels as we reach the final position.
.addFloat(tileLayout, "alpha", 0, 1)
.setListener(this)
.build();
// Fade in the tiles/labels as we reach the final position.
Builder builder = new Builder()
.addFloat(tileLayout, "alpha", 0, 1);
mFirstPageDelayedAnimator = builder.build();
if (mQQSFooterActions.getVisibility() != View.GONE) {
// only when qqs footer is present (which means split shade mode) it needs to
@@ -411,9 +463,8 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
updateQQSFooterAnimation();
}
// Fade in the security footer and the divider as we reach the final position
builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
Builder builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1);
if (mQsPanelController.shouldUseHorizontalLayout()
&& mQsPanelController.mMediaHost.hostView != null) {
@@ -425,26 +476,100 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
mAllPagesDelayedAnimator = builder.build();
mAllViews.add(mSecurityFooter.getView());
translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
qqsTranslationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
translationXBuilder.setInterpolator(mQSExpansionPathInterpolator.getXInterpolator());
if (mOnFirstPage) {
// Only recreate this animator if we're in the first page. That way we know that
// the first page is attached and has the proper positions/measures.
mQQSTranslationYAnimator = qqsTranslationYBuilder.build();
}
mTranslationYAnimator = translationYBuilder.build();
mTranslationXAnimator = translationXBuilder.build();
if (mQQSTileHeightAnimator != null) {
mQQSTileHeightAnimator.setInterpolator(
mQSExpansionPathInterpolator.getYInterpolator());
}
if (mOtherTilesExpandAnimator != null) {
mOtherTilesExpandAnimator.setInterpolator(
if (mOtherFirstPageTilesHeightAnimator != null) {
mOtherFirstPageTilesHeightAnimator.setInterpolator(
mQSExpansionPathInterpolator.getYInterpolator());
}
}
mNonfirstPageAnimator = new TouchAnimator.Builder()
mNonfirstPageAlphaAnimator = nonFirstPageAlphaBuilder
.addFloat(mQuickQsPanel, "alpha", 1, 0)
.addFloat(tileLayout, "alpha", 0, 1)
.setListener(mNonFirstPageListener)
.setEndDelay(.5f)
.setEndDelay(1 - QQS_FADE_IN_INTERVAL)
.build();
mNonfirstPageDelayedAnimator = new TouchAnimator.Builder()
.setStartDelay(.14f)
.addFloat(tileLayout, "alpha", 0, 1).build();
}
private Pair<HeightExpansionAnimator, TouchAnimator> createSecondaryPageAnimators(int page) {
if (mPagedLayout == null) return null;
HeightExpansionAnimator animator = null;
TouchAnimator.Builder builder = new Builder()
.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
TouchAnimator.Builder alphaDelayedBuilder = new Builder()
.setStartDelay(QS_TILE_LABEL_FADE_OUT_START)
.setEndDelay(QS_TILE_LABEL_FADE_OUT_END);
SideLabelTileLayout qqsLayout = (SideLabelTileLayout) mQuickQsPanel.getTileLayout();
View view = mQs.getView();
List<String> specs = mPagedLayout.getSpecsForPage(page);
int row = -1;
int lastTileTop = -1;
for (int i = 0; i < specs.size(); i++) {
QSTileView tileView = mQsPanelController.getTileView(specs.get(i));
getRelativePosition(mTmpLoc2, tileView, view);
int diff = mTmpLoc2[1] - (mQQSTop + qqsLayout.getPhantomTopPosition(i));
builder.addFloat(tileView, "translationY", -diff, 0);
// The different elements in the tile should be centered, so maintain them centered
int centerDiff = (tileView.getMeasuredHeight() - mLastQQSTileHeight) / 2;
builder.addFloat(tileView.getIcon(), "translationY", -centerDiff, 0);
builder.addFloat(tileView.getSecondaryIcon(), "translationY", -centerDiff, 0);
// The labels have different apparent size in QQS vs QS (no secondary label), so the
// translation needs to account for that.
int labelDiff = centerDiff - tileView.getSecondaryLabel().getMeasuredHeight() / 2;
builder.addFloat(tileView.getLabelContainer(), "translationY", -labelDiff, 0);
builder.addFloat(tileView.getSecondaryLabel(), "alpha", 0, 0.3f, 1);
alphaDelayedBuilder.addFloat(tileView.getLabelContainer(), "alpha", 0, 1);
alphaDelayedBuilder.addFloat(tileView.getIcon(), "alpha", 0, 1);
alphaDelayedBuilder.addFloat(tileView.getSecondaryIcon(), "alpha", 0, 1);
final int tileTop = tileView.getTop();
if (tileTop != lastTileTop) {
row++;
lastTileTop = tileTop;
}
if (i >= mQuickQsPanel.getTileLayout().getNumVisibleTiles() && row >= 2) {
// Fade completely the tiles in rows below the ones that will merge into QQS.
// args is an array of 0s where the length is the current row index (at least third
// row)
final float[] args = new float[row];
args[args.length - 1] = 1f;
builder.addFloat(tileView, "alpha", args);
} else {
// For all the other rows, fade them a bit
builder.addFloat(tileView, "alpha", 0.6f, 1);
}
if (animator == null) {
animator = new HeightExpansionAnimator(
this, mLastQQSTileHeight, tileView.getMeasuredHeight());
animator.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
}
animator.addView(tileView);
tileView.setClipChildren(true);
tileView.setClipToPadding(true);
mAllViews.add(tileView);
mAllViews.add(tileView.getSecondaryLabel());
mAllViews.add(tileView.getIcon());
mAllViews.add(tileView.getSecondaryIcon());
mAllViews.add(tileView.getLabelContainer());
}
builder.addFloat(alphaDelayedBuilder.build(), "position", 0, 1);
return new Pair<>(animator, builder.build());
}
private void animateBrightnessSlider(Builder firstPageBuilder) {
@@ -542,31 +667,37 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
}
}
mLastPosition = position;
if (mOnFirstPage && mAllowFancy) {
if (!mAllowFancy) return;
if (mOnFirstPage) {
mQuickQsPanel.setAlpha(1);
mFirstPageAnimator.setPosition(position);
mFirstPageDelayedAnimator.setPosition(position);
mTranslationYAnimator.setPosition(position);
mTranslationXAnimator.setPosition(position);
if (mQQSTileHeightAnimator != null) {
mQQSTileHeightAnimator.setPosition(position);
}
if (mOtherTilesExpandAnimator != null) {
mOtherTilesExpandAnimator.setPosition(position);
if (mOtherFirstPageTilesHeightAnimator != null) {
mOtherFirstPageTilesHeightAnimator.setPosition(position);
}
} else {
mNonfirstPageAnimator.setPosition(position);
mNonfirstPageDelayedAnimator.setPosition(position);
mNonfirstPageAlphaAnimator.setPosition(position);
}
if (mAllowFancy) {
mAllPagesDelayedAnimator.setPosition(position);
if (mBrightnessAnimator != null) {
mBrightnessAnimator.setPosition(position);
}
if (mQQSFooterActionsAnimator != null) {
mQQSFooterActionsAnimator.setPosition(position);
for (int i = 0; i < mNonFirstPageQSAnimators.size(); i++) {
Pair<HeightExpansionAnimator, TouchAnimator> pair = mNonFirstPageQSAnimators.valueAt(i);
if (pair != null) {
pair.first.setPosition(position);
pair.second.setPosition(position);
}
}
if (mQQSTileHeightAnimator != null) {
mQQSTileHeightAnimator.setPosition(position);
}
mQSTileLayoutTranslatorAnimator.setPosition(position);
mQQSTranslationYAnimator.setPosition(position);
mAllPagesDelayedAnimator.setPosition(position);
if (mBrightnessAnimator != null) {
mBrightnessAnimator.setPosition(position);
}
if (mQQSFooterActionsAnimator != null) {
mQQSFooterActionsAnimator.setPosition(position);
}
}
@Override
@@ -611,8 +742,11 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mQQSTileHeightAnimator != null) {
mQQSTileHeightAnimator.resetViewsHeights();
}
if (mOtherTilesExpandAnimator != null) {
mOtherTilesExpandAnimator.resetViewsHeights();
if (mOtherFirstPageTilesHeightAnimator != null) {
mOtherFirstPageTilesHeightAnimator.resetViewsHeights();
}
for (int i = 0; i < mNonFirstPageQSAnimators.size(); i++) {
mNonFirstPageQSAnimators.valueAt(i).first.resetViewsHeights();
}
final int N2 = mAnimatedQsViews.size();
for (int i = 0; i < N2; i++) {
@@ -623,7 +757,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
mExecutor.execute(mUpdateAnimators);
boolean actualChange =
left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom;
if (actualChange) mExecutor.execute(mUpdateAnimators);
}
@Override

View File

@@ -503,6 +503,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
isTransitioningToFullShade ? progress : mSquishinessFraction);
}
@Override
public int getHeightDiff() {
return mQSPanelScrollView.getBottom() - mHeader.getBottom()
+ mHeader.getPaddingBottom();
}
@Override
public void setQsExpansion(float expansion, float panelExpansionFraction,
float proposedTranslation, float squishinessFraction) {
@@ -537,8 +543,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
boolean fullyExpanded = expansion == 1;
boolean fullyCollapsed = expansion == 0.0f;
int heightDiff = mQSPanelScrollView.getBottom() - mHeader.getBottom()
+ mHeader.getPaddingBottom();
int heightDiff = getHeightDiff();
float panelTranslationY = translationScaleY * heightDiff;
// Let the views animate their contents correctly by giving them the necessary context.

View File

@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -106,6 +107,7 @@ public class QSPanel extends LinearLayout implements Tunable {
protected QSTileLayout mTileLayout;
private float mSquishinessFraction = 1f;
private final ArrayMap<View, Integer> mChildrenLayoutTop = new ArrayMap<>();
private final Rect mClippingRect = new Rect();
public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -133,8 +135,7 @@ public class QSPanel extends LinearLayout implements Tunable {
mHorizontalContentContainer = new RemeasuringLinearLayout(mContext);
mHorizontalContentContainer.setOrientation(LinearLayout.VERTICAL);
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
setHorizontalContentContainerClipping();
LayoutParams lp = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1);
int marginSize = (int) mContext.getResources().getDimension(R.dimen.qs_media_padding);
@@ -148,6 +149,23 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
protected void setHorizontalContentContainerClipping() {
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
// Don't clip on the top, that way, secondary pages tiles can animate up
mHorizontalContentContainer.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
if (left != oldLeft || right != oldRight || bottom != oldBottom) {
mClippingRect.left = left;
mClippingRect.right = right;
mClippingRect.bottom = bottom;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
});
mClippingRect.top = -1000;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
/**
* Add brightness view above the tile layout.
*

View File

@@ -45,6 +45,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -258,6 +259,15 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
return null;
}
QSTileView getTileView(String spec) {
for (QSPanelControllerBase.TileRecord r : mRecords) {
if (Objects.equals(r.tile.getTileSpec(), spec)) {
return r.tileView;
}
}
return null;
}
private String getTilesSpecs() {
return mRecords.stream()
.map(tileRecord -> tileRecord.tile.getTileSpec())

View File

@@ -46,11 +46,9 @@ public class QuickQSPanel extends QSPanel {
}
@Override
void initialize() {
super.initialize();
if (mHorizontalContentContainer != null) {
mHorizontalContentContainer.setClipChildren(false);
}
protected void setHorizontalContentContainerClipping() {
mHorizontalContentContainer.setClipToPadding(false);
mHorizontalContentContainer.setClipChildren(false);
}
@Override