diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java index 7accfbb6a6..02aa3f208b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java @@ -23,6 +23,7 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; import com.android.launcher3.views.AbstractSlideInView; @@ -30,14 +31,14 @@ import com.android.launcher3.views.AbstractSlideInView; import java.util.Optional; /** Wrapper for taskbar all apps with slide-in behavior. */ -public class TaskbarAllAppsSlideInView extends - AbstractSlideInView implements Insettable { - +public class TaskbarAllAppsSlideInView extends AbstractSlideInView + implements Insettable, DeviceProfile.OnDeviceProfileChangeListener { static final int DEFAULT_OPEN_DURATION = 500; static final int DEFAULT_CLOSE_DURATION = 200; private TaskbarAllAppsContainerView mAppsView; private OnCloseListener mOnCloseBeginListener; + private float mShiftRange; public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -88,6 +89,11 @@ public class TaskbarAllAppsSlideInView extends super.onFinishInflate(); mAppsView = findViewById(R.id.apps_view); mContent = mAppsView; + + DeviceProfile dp = mActivityContext.getDeviceProfile(); + setShiftRange(dp.allAppsShiftRange); + + mActivityContext.addOnDeviceProfileChangeListener(this); } @Override @@ -113,4 +119,24 @@ public class TaskbarAllAppsSlideInView extends public void setInsets(Rect insets) { mAppsView.setInsets(insets); } + + @Override + public void onDeviceProfileChanged(DeviceProfile dp) { + setShiftRange(dp.allAppsShiftRange); + setTranslationShift(TRANSLATION_SHIFT_OPENED); + } + + private void setShiftRange(float shiftRange) { + mShiftRange = shiftRange; + } + + @Override + protected float getShiftRange() { + return mShiftRange; + } + + @Override + protected boolean isEventOverContent(MotionEvent ev) { + return getPopupContainer().isEventOverView(mAppsView.getVisibleContainerView(), ev); + } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java index 26d8f303e8..fec591b653 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -53,9 +53,16 @@ public class AllAppsState extends LauncherState { @Override public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) { - ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW - .getWorkspaceScaleAndTranslation(launcher); - scaleAndTranslation.scale = 1; + ScaleAndTranslation scaleAndTranslation = + new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET); + if (launcher.getDeviceProfile().isTablet) { + scaleAndTranslation.scale = 0.97f; + } else { + ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW + .getWorkspaceScaleAndTranslation(launcher); + scaleAndTranslation.translationX = overviewScaleAndTranslation.translationX; + scaleAndTranslation.translationY = overviewScaleAndTranslation.translationY; + } return scaleAndTranslation; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index 099915a281..f93917f1f5 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -23,8 +23,13 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; +import static com.android.launcher3.anim.Interpolators.INSTANT; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.anim.Interpolators.LINEAR_TELEPORT; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; import android.view.MotionEvent; @@ -126,23 +131,31 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr private StateAnimationConfig getNormalToAllAppsAnimation() { StateAnimationConfig builder = new StateAnimationConfig(); - builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL, - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD, - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD)); + boolean isTablet = mLauncher.getDeviceProfile().isTablet; + builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet + ? INSTANT + : Interpolators.clampToProgress(ACCEL, + ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD, + ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD)); builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL, ALL_APPS_SCRIM_VISIBLE_THRESHOLD, ALL_APPS_SCRIM_OPAQUE_THRESHOLD)); + builder.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR); return builder; } private StateAnimationConfig getAllAppsToNormalAnimation() { StateAnimationConfig builder = new StateAnimationConfig(); - builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL, - 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, - 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD)); + boolean isTablet = mLauncher.getDeviceProfile().isTablet; + builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet + ? FINAL_FRAME + : Interpolators.clampToProgress(DEACCEL, + 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, + 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD)); builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL, 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD, 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD)); + builder.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR); return builder; } diff --git a/res/drawable/bg_rounded_corner_bottom_sheet.xml b/res/drawable/bg_rounded_corner_bottom_sheet.xml index aa49bced7a..dfcd354ce7 100644 --- a/res/drawable/bg_rounded_corner_bottom_sheet.xml +++ b/res/drawable/bg_rounded_corner_bottom_sheet.xml @@ -16,7 +16,7 @@ - + diff --git a/res/drawable/bg_all_apps_bottom_sheet.xml b/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml similarity index 55% rename from res/drawable/bg_all_apps_bottom_sheet.xml rename to res/drawable/bg_rounded_corner_bottom_sheet_handle.xml index dba2fee7e9..c5021787c5 100644 --- a/res/drawable/bg_all_apps_bottom_sheet.xml +++ b/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml @@ -1,6 +1,5 @@ - - - - - - - - - \ No newline at end of file + + + + + diff --git a/res/layout/all_apps_bottom_sheet_background.xml b/res/layout/all_apps_bottom_sheet_background.xml index ad10d6801b..12b6b7bb55 100644 --- a/res/layout/all_apps_bottom_sheet_background.xml +++ b/res/layout/all_apps_bottom_sheet_background.xml @@ -17,19 +17,19 @@ android:id="@+id/bottom_sheet_background" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@drawable/bg_all_apps_bottom_sheet"> + android:background="@drawable/bg_rounded_corner_bottom_sheet"> + android:layout_height="36dp" /> + android:layout_marginTop="@dimen/bottom_sheet_handle_margin" + android:layout_marginBottom="@dimen/bottom_sheet_handle_margin" + android:background="@drawable/bg_rounded_corner_bottom_sheet_handle" /> diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml index 1a2cfc6f93..a5f72ef30a 100644 --- a/res/layout/widgets_bottom_sheet_content.xml +++ b/res/layout/widgets_bottom_sheet_content.xml @@ -19,16 +19,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_rounded_corner_bottom_sheet" - android:paddingTop="16dp" + android:paddingTop="@dimen/bottom_sheet_handle_margin" android:orientation="vertical"> + android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/> + android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/> 32dp - 32dp + 0dp + 46dp 75dp diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml new file mode 100644 index 0000000000..a9e0fb8a34 --- /dev/null +++ b/res/values-sw720dp-land/dimens.xml @@ -0,0 +1,20 @@ + + + + + + 0dp + diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml index 9d7941f5e3..5c314d598e 100644 --- a/res/values-sw720dp/dimens.xml +++ b/res/values-sw720dp/dimens.xml @@ -16,5 +16,6 @@ - 41dp + 300dp + 65dp diff --git a/res/values/dimens.xml b/res/values/dimens.xml index ddc7d10994..3e666fcf2e 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -93,8 +93,11 @@ -26dp - 320dp + 320dp + 0dp 48dp + + 24dp 30dp 40dp 144dp @@ -363,4 +366,9 @@ 32dp 8dp + + 32dp + 4dp + 16dp + 2dp diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 62703ad2e0..7189ef70ca 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -171,7 +171,8 @@ public class DeviceProfile { // All apps public Point allAppsBorderSpacePx; - public int allAppsOpenVerticalTranslate; + public int allAppsShiftRange; + public int allAppsTopPadding; public int allAppsCellHeightPx; public int allAppsCellWidthPx; public int allAppsIconSizePx; @@ -288,8 +289,11 @@ public class DeviceProfile { desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res); desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx; - allAppsOpenVerticalTranslate = res.getDimensionPixelSize( - R.dimen.all_apps_open_vertical_translate); + allAppsTopPadding = res.getDimensionPixelSize(R.dimen.all_apps_top_padding) + + (isTablet ? heightPx - availableHeightPx : 0); + allAppsShiftRange = isTablet + ? heightPx - allAppsTopPadding + : res.getDimensionPixelSize(R.dimen.all_apps_starting_vertical_translate); folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale); folderContentPaddingLeftRight = diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index b6a2459c2c..cdc313f351 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -89,15 +89,15 @@ public class AllAppsTransitionController private float mShiftRange; // changes depending on the orientation private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent - private float mScrollRangeDelta = 0; private ScrimView mScrimView; public AllAppsTransitionController(Launcher l) { mLauncher = l; - mShiftRange = mLauncher.getDeviceProfile().heightPx; + DeviceProfile dp = mLauncher.getDeviceProfile(); + setShiftRange(dp.allAppsShiftRange); mProgress = 1f; - mIsVerticalLayout = mLauncher.getDeviceProfile().isVerticalBarLayout(); + mIsVerticalLayout = dp.isVerticalBarLayout(); mLauncher.addOnDeviceProfileChangeListener(this); } @@ -108,7 +108,7 @@ public class AllAppsTransitionController @Override public void onDeviceProfileChanged(DeviceProfile dp) { mIsVerticalLayout = dp.isVerticalBarLayout(); - setScrollRangeDelta(mScrollRangeDelta); + setShiftRange(dp.allAppsShiftRange); if (mIsVerticalLayout) { mLauncher.getHotseat().setTranslationY(0); @@ -160,12 +160,14 @@ public class AllAppsTransitionController } // need to decide depending on the release velocity - Interpolator interpolator = (config.userControlled ? LINEAR : DEACCEL_1_7); - + Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS, + config.userControlled ? LINEAR : DEACCEL_1_7); Animator anim = createSpringAnimation(mProgress, targetProgress); - anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator)); + anim.setInterpolator(verticalProgressInterpolator); anim.addListener(getProgressAnimatorListener()); builder.add(anim); + // Use ANIM_VERTICAL_PROGRESS's interpolator to determine state transition threshold. + builder.setInterpolator(verticalProgressInterpolator); setAlphas(toState, config, builder); @@ -215,9 +217,8 @@ public class AllAppsTransitionController /** * Updates the total scroll range but does not update the UI. */ - public void setScrollRangeDelta(float delta) { - mScrollRangeDelta = delta; - mShiftRange = mLauncher.getDeviceProfile().heightPx - mScrollRangeDelta; + public void setShiftRange(float shiftRange) { + mShiftRange = shiftRange; } /** diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index 59e21c099c..bfc75153a5 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -408,7 +408,7 @@ public abstract class BaseAllAppsContainerView { + float startTeleport = 0.2f; + float endTeleport = 0.4f; + float teleportProgress = 0.5f; + float v; + if (t < startTeleport) { + v = LINEAR.getInterpolation(t); + } else if (t < endTeleport) { + v = Utilities.mapToRange(t, startTeleport, endTeleport, startTeleport, + endTeleport + teleportProgress, ACCEL_DEACCEL); + } else { + v = LINEAR.getInterpolation(t) + teleportProgress; + } + v = Utilities.boundToRange(v, 0f, 1f); + return v; + }; + private static final float FAST_FLING_PX_MS = 10; public static Interpolator scrollInterpolatorForVelocity(float velocity) { diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java index 3ab893b0a1..1300ce7f9c 100644 --- a/src/com/android/launcher3/anim/PendingAnimation.java +++ b/src/com/android/launcher3/anim/PendingAnimation.java @@ -77,6 +77,13 @@ public class PendingAnimation implements PropertySetter { addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders); } + /** + * Configures interpolator of the underlying AnimatorSet. + */ + public void setInterpolator(TimeInterpolator interpolator) { + mAnim.setInterpolator(interpolator); + } + @Override public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) { if (view == null || view.getAlpha() == alpha) { diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java index 989a9e4c24..f7d34921d3 100644 --- a/src/com/android/launcher3/touch/AllAppsSwipeController.java +++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java @@ -17,9 +17,13 @@ package com.android.launcher3.touch; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; +import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.anim.Interpolators.LINEAR_TELEPORT; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; import android.view.MotionEvent; import android.view.animation.Interpolator; @@ -94,9 +98,9 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { LauncherState toState) { StateAnimationConfig config = super.getConfigForStates(fromState, toState); if (fromState == NORMAL && toState == ALL_APPS) { - applyNormalToAllAppsAnimConfig(config); + applyNormalToAllAppsAnimConfig(mLauncher, config); } else if (fromState == ALL_APPS && toState == NORMAL) { - applyAllAppsToNormalConfig(config); + applyAllAppsToNormalConfig(mLauncher, config); } return config; } @@ -104,17 +108,24 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { /** * Applies Animation config values for transition from all apps to home */ - public static void applyAllAppsToNormalConfig(StateAnimationConfig config) { + public static void applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config) { + boolean isTablet = launcher.getDeviceProfile().isTablet; config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER); - config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER); + config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet + ? FINAL_FRAME : ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER); + config.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR); } /** * Applies Animation config values for transition from home to all apps */ - public static void applyNormalToAllAppsAnimConfig(StateAnimationConfig config) { + public static void applyNormalToAllAppsAnimConfig(Launcher launcher, + StateAnimationConfig config) { + boolean isTablet = launcher.getDeviceProfile().isTablet; config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER); - config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER); + config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet + ? INSTANT : ALLAPPS_STAGGERED_FADE_LATE_RESPONDER); + config.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR); } diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java index c22d60d0a9..5d888846a8 100644 --- a/src/com/android/launcher3/views/AbstractSlideInView.java +++ b/src/com/android/launcher3/views/AbstractSlideInView.java @@ -113,9 +113,16 @@ public abstract class AbstractSlideInView return -1; } + /** + * Returns the range in height that the slide in view can be dragged. + */ + protected float getShiftRange() { + return mContent.getHeight(); + } + protected void setTranslationShift(float translationShift) { mTranslationShift = translationShift; - mContent.setTranslationY(mTranslationShift * mContent.getHeight()); + mContent.setTranslationY(mTranslationShift * getShiftRange()); if (mColorScrim != null) { mColorScrim.setAlpha(1 - mTranslationShift); } @@ -132,8 +139,7 @@ public abstract class AbstractSlideInView mSwipeDetector.setDetectableScrollConditions( directionsToDetectScroll, false); mSwipeDetector.onTouchEvent(ev); - return mSwipeDetector.isDraggingOrSettling() - || !getPopupContainer().isEventOverView(mContent, ev); + return mSwipeDetector.isDraggingOrSettling() || !isEventOverContent(ev); } @Override @@ -142,13 +148,23 @@ public abstract class AbstractSlideInView if (ev.getAction() == MotionEvent.ACTION_UP && mSwipeDetector.isIdleState() && !isOpeningAnimationRunning()) { // If we got ACTION_UP without ever starting swipe, close the panel. - if (!getPopupContainer().isEventOverView(mContent, ev)) { + if (!isEventOverContent(ev)) { close(true); } } return true; } + /** + * Returns {@code true} if the touch event is over the visible area of the bottom sheet. + * + * By default will check if the touch event is over {@code mContent}, subclasses should override + * this method if the visible area of the bottom sheet is different from {@code mContent}. + */ + protected boolean isEventOverContent(MotionEvent ev) { + return getPopupContainer().isEventOverView(mContent, ev); + } + private boolean isOpeningAnimationRunning() { return mIsOpen && mOpenCloseAnimator.isRunning(); } @@ -160,7 +176,7 @@ public abstract class AbstractSlideInView @Override public boolean onDrag(float displacement) { - float range = mContent.getHeight(); + float range = getShiftRange(); displacement = Utilities.boundToRange(displacement, 0, range); setTranslationShift(displacement / range); return true; diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java index 5543cc2696..8a435c9647 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -55,8 +55,15 @@ public class AllAppsState extends LauncherState { @Override public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) { - return new ScaleAndTranslation(1f, 0, - -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT); + ScaleAndTranslation scaleAndTranslation = + new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET); + if (launcher.getDeviceProfile().isTablet) { + scaleAndTranslation.scale = 0.97f; + } else { + scaleAndTranslation.translationY = + -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT; + } + return scaleAndTranslation; } @Override