• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3.allapps;
18 
19 import static androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT;
20 import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT;
21 
22 import android.content.Context;
23 import android.graphics.PorterDuff;
24 import android.graphics.PorterDuffColorFilter;
25 import android.graphics.drawable.Drawable;
26 import android.util.AttributeSet;
27 import android.widget.TextView;
28 
29 import androidx.constraintlayout.widget.ConstraintLayout;
30 import androidx.core.graphics.ColorUtils;
31 
32 import com.android.launcher3.R;
33 import com.android.launcher3.Utilities;
34 
35 /**
36  * A TextView that is used to display the letter list in the fast scroller.
37  */
38 public class LetterListTextView extends TextView {
39     private static final float ABSOLUTE_TRANSLATION_X = 30f;
40     private static final float ABSOLUTE_SCALE = 1.4f;
41     private final Drawable mLetterBackground;
42     private final int mLetterListTextWidthAndHeight;
43     private final int mTextColor;
44 
LetterListTextView(Context context)45     public LetterListTextView(Context context) {
46         this(context, null, 0);
47     }
48 
LetterListTextView(Context context, AttributeSet attrs)49     public LetterListTextView(Context context, AttributeSet attrs) {
50         this(context, attrs, 0);
51     }
52 
LetterListTextView(Context context, AttributeSet attrs, int defStyle)53     public LetterListTextView(Context context, AttributeSet attrs, int defStyle) {
54         super(context, attrs, defStyle);
55         mLetterBackground = context.getDrawable(R.drawable.bg_letter_list_text);
56         mLetterListTextWidthAndHeight = context.getResources().getDimensionPixelSize(
57                 R.dimen.fastscroll_list_letter_size);
58         mTextColor = context.getColor(R.color.materialColorOnSurface);
59     }
60 
61     @Override
onFinishInflate()62     public void onFinishInflate() {
63         super.onFinishInflate();
64         setBackground(mLetterBackground);
65         setTextColor(mTextColor);
66         setClickable(false);
67         setWidth(mLetterListTextWidthAndHeight);
68         setTextSize(mLetterListTextWidthAndHeight);
69         setVisibility(VISIBLE);
70     }
71 
72     /**
73      * Applies a viewId to the letter list text view and sets the background and text based on the
74      * sectionInfo.
75      */
apply(AlphabeticalAppsList.FastScrollSectionInfo fastScrollSectionInfo, int viewId)76     public void apply(AlphabeticalAppsList.FastScrollSectionInfo fastScrollSectionInfo,
77             int viewId) {
78         setId(viewId);
79         setText(fastScrollSectionInfo.sectionName);
80         ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(
81                 MATCH_CONSTRAINT, WRAP_CONTENT);
82         lp.dimensionRatio = "v,1:1";
83         setLayoutParams(lp);
84     }
85 
86     /**
87      * Animates the letter list text view based on the current finger position.
88      *
89      * @param currentFingerY The Y position of where the finger is placed on the fastScroller in
90      *                       pixels.
91      */
animateBasedOnYPosition(int currentFingerY)92     public void animateBasedOnYPosition(int currentFingerY) {
93         if (getBackground() == null) {
94             return;
95         }
96         float cutOffMin = currentFingerY - (getHeight() * 2);
97         float cutOffMax = currentFingerY + (getHeight() * 2);
98         float cutOffDistance = cutOffMax - cutOffMin;
99         boolean isWithinAnimationBounds = getY() < cutOffMax && getY() > cutOffMin;
100         translateBasedOnYPosition(currentFingerY, cutOffDistance, isWithinAnimationBounds);
101         scaleBasedOnYPosition(currentFingerY, cutOffDistance, isWithinAnimationBounds);
102     }
103 
scaleBasedOnYPosition(int y, float cutOffDistance, boolean isWithinAnimationBounds)104     private void scaleBasedOnYPosition(int y, float cutOffDistance,
105             boolean isWithinAnimationBounds) {
106         float raisedCosineScale = (float) Math.cos(((y - getY()) / (cutOffDistance)) * Math.PI)
107                 * ABSOLUTE_SCALE;
108         if (isWithinAnimationBounds) {
109             raisedCosineScale = Utilities.boundToRange(raisedCosineScale, 1f, ABSOLUTE_SCALE);
110             setScaleX(raisedCosineScale);
111             setScaleY(raisedCosineScale);
112         } else {
113             setScaleX(1);
114             setScaleY(1);
115         }
116     }
117 
translateBasedOnYPosition(int y, float cutOffDistance, boolean isWithinAnimationBounds)118     private void translateBasedOnYPosition(int y, float cutOffDistance,
119             boolean isWithinAnimationBounds) {
120         float raisedCosineTranslation =
121                 (float) Math.cos(((y - getY()) / (cutOffDistance)) * Math.PI)
122                         * ABSOLUTE_TRANSLATION_X;
123         if (isWithinAnimationBounds) {
124             raisedCosineTranslation = -1 * Utilities.boundToRange(raisedCosineTranslation,
125                     0, ABSOLUTE_TRANSLATION_X);
126             setTranslationX(raisedCosineTranslation);
127         } else {
128             setTranslationX(0);
129         }
130     }
131 }
132