+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.
--->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:viewportHeight="48.0"
- android:viewportWidth="48.0"
- android:width="24dp" >
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M14.83,30.83L24,21.66l9.17,9.17L36,28 24,16 12,28z"/>
-</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<pathInterpolator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
<color name="outline_color">#FFFFFFFF</color>
<color name="all_apps_divider_color">#1E000000</color>
+ <color name="all_apps_caret_color">#FFFFFFFF</color>
<color name="spring_loaded_panel_color">#40FFFFFF</color>
<color name="spring_loaded_highlighted_panel_border_color">#FFF</color>
<!-- The distance at which the animation should take the max duration -->
<integer name="config_dropAnimMaxDist">800</integer>
+ <!-- The duration of the caret animation -->
+ <integer name="config_caretAnimationDuration">200</integer>
+
<!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">true</bool>
<dimen name="container_min_margin">8dp</dimen>
<dimen name="container_max_width">0dp</dimen>
- <!-- All Apps -->
+<!-- All Apps -->
<dimen name="all_apps_button_scale_down">0dp</dimen>
<dimen name="all_apps_grid_view_start_margin">0dp</dimen>
<dimen name="all_apps_grid_section_y_offset">8dp</dimen>
<dimen name="all_apps_empty_search_bg_top_offset">144dp</dimen>
<dimen name="all_apps_background_canvas_width">700dp</dimen>
<dimen name="all_apps_background_canvas_height">475dp</dimen>
+ <dimen name="all_apps_caret_stroke_width">2dp</dimen>
+ <dimen name="all_apps_caret_inset">8dp</dimen>
- <!-- Search bar in All Apps -->
+<!-- Search bar in All Apps -->
<dimen name="all_apps_header_max_elevation">3dp</dimen>
<dimen name="all_apps_header_scroll_to_elevation">16dp</dimen>
<dimen name="all_apps_header_shadow_height">6dp</dimen>
if (!animated || !initialized) {
if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP &&
fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
- mAllAppsController.finishPullDown();
+ mAllAppsController.finishPullDown(false);
}
fromView.setVisibility(View.GONE);
dispatchOnLauncherTransitionPrepare(fromView, animated, multiplePagesVisible);
float finalAlpha = mHotseatAlpha[0] * mHotseatAlpha[1] * mHotseatAlpha[2];
mLauncher.getHotseat().setAlpha(finalAlpha);
- mPageIndicator.setAlpha(finalAlpha);
}
public ValueAnimator createHotseatAlphaAnimator(float finalValue) {
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
+import com.android.launcher3.pageindicators.CaretDrawable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
private Hotseat mHotseat;
private float mHotseatBackgroundAlpha;
+ private ObjectAnimator mCaretAnimator;
+ private final long mCaretAnimationDuration;
+ private final Interpolator mCaretInterpolator;
+
private float mStatusBarHeight;
private final Launcher mLauncher;
private static final float DEFAULT_SHIFT_RANGE = 10;
-
private static final float RECATCH_REJECTION_FRACTION = .0875f;
private int mBezelSwipeUpHeight;
private long mAnimationDuration;
-
private AnimatorSet mCurrentAnimation;
private boolean mNoIntercept;
mShiftCurrent = mShiftRange = DEFAULT_SHIFT_RANGE;
mBezelSwipeUpHeight = launcher.getResources().getDimensionPixelSize(
R.dimen.all_apps_bezel_swipe_height);
+
+ mCaretAnimationDuration = launcher.getResources().getInteger(
+ R.integer.config_caretAnimationDuration);
+ mCaretInterpolator = AnimationUtils.loadInterpolator(launcher,
+ R.interpolator.caret_animation_interpolator);
}
@Override
if (canceled) {
return;
} else {
- finishPullDown();
+ finishPullDown(true);
cleanUpAnimation();
mDetector.finishedScrolling();
}
public void finishPullUp() {
mHotseat.setVisibility(View.INVISIBLE);
setProgress(0f);
+ animateCaret();
}
- public void finishPullDown() {
+ public void finishPullDown(boolean animated) {
mAppsView.setVisibility(View.INVISIBLE);
mHotseat.setBackgroundTransparent(false /* transparent */);
mHotseat.setVisibility(View.VISIBLE);
mAppsView.reset();
setProgress(mShiftRange);
+ if (animated) {
+ animateCaret();
+ } else {
+ mWorkspace.getPageIndicator().getCaretDrawable()
+ .setLevel(CaretDrawable.LEVEL_CARET_POINTING_UP);
+ }
}
private void cancelAnimation() {
mCurrentAnimation = null;
}
+ private void animateCaret() {
+ if (mCaretAnimator.isRunning()) {
+ mCaretAnimator.cancel(); // stop the animator in its tracks
+ }
+
+ if (mLauncher.isAllAppsVisible()) {
+ mCaretAnimator.setIntValues(CaretDrawable.LEVEL_CARET_POINTING_DOWN);
+ } else {
+ mCaretAnimator.setIntValues(CaretDrawable.LEVEL_CARET_POINTING_UP);
+ }
+
+ mCaretAnimator.start();
+ }
+
public void setupViews(AllAppsContainerView appsView, Hotseat hotseat, Workspace workspace) {
mAppsView = appsView;
mHotseat = hotseat;
mWorkspace = workspace;
+ mCaretAnimator = ObjectAnimator.ofInt(mWorkspace.getPageIndicator().getCaretDrawable(),
+ "level", CaretDrawable.LEVEL_CARET_POINTING_UP); // we will set values later
+ mCaretAnimator.setDuration(mCaretAnimationDuration);
+ mCaretAnimator.setInterpolator(mCaretInterpolator);
mHotseat.addOnLayoutChangeListener(this);
}
--- /dev/null
+/*
+ * Copyright (C) 2016 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 com.android.launcher3.pageindicators;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+
+import com.android.launcher3.R;
+
+import android.graphics.drawable.Drawable;
+
+public class CaretDrawable extends Drawable {
+ public static final int LEVEL_CARET_POINTING_UP = 0; // minimum possible level value
+ public static final int LEVEL_CARET_POINTING_DOWN = 10000; // maximum possible level value
+ public static final int LEVEL_CARET_NEUTRAL = LEVEL_CARET_POINTING_DOWN / 2;
+
+ private float mCaretProgress;
+
+ private Paint mPaint = new Paint();
+ private Path mPath = new Path();
+ private int mInset;
+
+ public CaretDrawable(Context context) {
+ final Resources res = context.getResources();
+
+ mPaint.setColor(res.getColor(R.color.all_apps_caret_color));
+ mPaint.setAntiAlias(true);
+ mPaint.setStrokeWidth(res.getDimensionPixelSize(R.dimen.all_apps_caret_stroke_width));
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeCap(Paint.Cap.SQUARE);
+ mPaint.setStrokeJoin(Paint.Join.MITER);
+
+ mInset = res.getDimensionPixelSize(R.dimen.all_apps_caret_inset);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final float width = getBounds().width();
+ final float height = getBounds().height();
+ final float left = getBounds().left;
+ final float top = getBounds().top;
+
+ final float verticalInset = (height / 4);
+ final float caretHeight = (height - (verticalInset * 2));
+
+ mPath.reset();
+ mPath.moveTo(left, top + caretHeight * (1 - mCaretProgress));
+ mPath.lineTo(left + (width / 2), top + caretHeight * mCaretProgress);
+ mPath.lineTo(left + width, top + caretHeight * (1 - mCaretProgress));
+
+ canvas.drawPath(mPath, mPaint);
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ mCaretProgress = (float) level / (float) LEVEL_CARET_POINTING_DOWN;
+ invalidateSelf();
+ return true;
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // no-op
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ // no-op
+ }
+
+ @Override
+ public void setBounds(int left, int top, int right, int bottom) {
+ super.setBounds(left + mInset, top + mInset, right - mInset, bottom - mInset);
+ }
+}
package com.android.launcher3.pageindicators;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
* Base class for a page indicator.
*/
public abstract class PageIndicator extends View {
+ private CaretDrawable mCaretDrawable;
protected int mNumPages = 1;
mNumPages--;
onPageCountChanged();
}
+
public void setMarkersCount(int numMarkers) {
mNumPages = numMarkers;
onPageCountChanged();
}
- protected void onPageCountChanged() { }
+ public CaretDrawable getCaretDrawable() {
+ return mCaretDrawable;
+ }
+
+ public void setCaretDrawable(CaretDrawable caretDrawable) {
+ if (mCaretDrawable != null) {
+ mCaretDrawable.setCallback(null);
+ }
+
+ mCaretDrawable = caretDrawable;
+
+ if (mCaretDrawable != null) {
+ mCaretDrawable.setCallback(this);
+ }
+ }
+
+ protected void onPageCountChanged() {}
public void setShouldAutoHide(boolean shouldAutoHide) {}
public void updateColor(ExtractedColors extractedColors) {}
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || who == getCaretDrawable();
+ }
}
package com.android.launcher3.pageindicators;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.dynamicui.ExtractedColors;
/**
* Simply draws the caret drawable in the center. Used for the landscape layout.
*/
public class PageIndicatorCaretLandscape extends PageIndicator {
// all apps pull up handle drawable.
- private final Drawable caretDrawable;
public PageIndicatorCaretLandscape(Context context) {
this(context, null);
public PageIndicatorCaretLandscape(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- Resources res = context.getResources();
- caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+ setCaretDrawable(new CaretDrawable(context));
Launcher l = (Launcher) context;
setOnTouchListener(l.getHapticFeedbackTouchListener());
setOnClickListener(l);
super.onLayout(changed, left, top, right, bottom);
int size = bottom - top;
int l = (right - left) / 2 - size / 2;
- caretDrawable.setBounds(l, 0, l + size, size);
+ getCaretDrawable().setBounds(l, 0, l + size, size);
}
@Override
protected void onDraw(Canvas canvas) {
- caretDrawable.draw(canvas);
+ getCaretDrawable().draw(canvas);
}
}
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.graphics.ColorUtils;
private int mTotalScroll;
private Paint mLinePaint;
private Launcher mLauncher;
- // all apps pull up handle drawable.
- private final Drawable caretDrawable;
private final int mLineHeight;
private final Rect mTouchHitRect = new Rect();
private final int mTouchExtensionHeight;
setOnClickListener(mLauncher);
setOnFocusChangeListener(mLauncher.mFocusHandler);
Resources res = context.getResources();
- caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+ setCaretDrawable(new CaretDrawable(context));
mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
mTouchExtensionHeight = res.getDimensionPixelSize(
R.dimen.dynamic_grid_page_indicator_extra_touch_height);
super.onLayout(changed, left, top, right, bottom);
int size = bottom - top;
int l = (right - left) / 2 - size / 2;
- caretDrawable.setBounds(l, 0, l+ size, size);
+ getCaretDrawable().setBounds(l, 0, l + size, size);
// The touch area is expanded below this view by #mTouchExtensionHeight
// which extends to the top of the hotseat.
@Override
protected void onDraw(Canvas canvas) {
- caretDrawable.draw(canvas);
+ getCaretDrawable().draw(canvas);
if (mTotalScroll == 0 || mNumPagesFloat == 0) {
return;
}