1 /**
2  * Copyright (C) 2015 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.folder;
18 
19 import android.view.View;
20 
21 import com.android.launcher3.folder.FolderIcon.PreviewItemDrawingParams;
22 
23 import java.util.List;
24 
25 public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule {
26 
27     static final int MAX_NUM_ITEMS_IN_PREVIEW = 3;
28 
29     // The degree to which the item in the back of the stack is scaled [0...1]
30     // (0 means it's not scaled at all, 1 means it's scaled to nothing)
31     private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
32 
33     // The amount of vertical spread between items in the stack [0...1]
34     private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
35 
36     private float mBaselineIconScale;
37     private int mBaselineIconSize;
38     private int mAvailableSpaceInPreview;
39     private float mMaxPerspectiveShift;
40 
41     @Override
init(int availableSpace, int intrinsicIconSize, boolean rtl)42     public void init(int availableSpace, int intrinsicIconSize, boolean rtl) {
43         mAvailableSpaceInPreview = availableSpace;
44 
45         // cos(45) = 0.707  + ~= 0.1) = 0.8f
46         int adjustedAvailableSpace = (int) ((mAvailableSpaceInPreview / 2) * (1 + 0.8f));
47 
48         int unscaledHeight = (int) (intrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR));
49 
50         mBaselineIconScale = (1.0f * adjustedAvailableSpace / unscaledHeight);
51 
52         mBaselineIconSize = (int) (intrinsicIconSize * mBaselineIconScale);
53         mMaxPerspectiveShift = mBaselineIconSize * PERSPECTIVE_SHIFT_FACTOR;
54     }
55 
56     @Override
computePreviewItemDrawingParams(int index, int curNumItems, PreviewItemDrawingParams params)57     public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
58             PreviewItemDrawingParams params) {
59         float scale = scaleForItem(index, curNumItems);
60 
61         index = MAX_NUM_ITEMS_IN_PREVIEW - index - 1;
62         float r = (index * 1.0f) / (MAX_NUM_ITEMS_IN_PREVIEW - 1);
63 
64         float offset = (1 - r) * mMaxPerspectiveShift;
65         float scaledSize = scale * mBaselineIconSize;
66         float scaleOffsetCorrection = (1 - scale) * mBaselineIconSize;
67 
68         // We want to imagine our coordinates from the bottom left, growing up and to the
69         // right. This is natural for the x-axis, but for the y-axis, we have to invert things.
70         float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
71         float transX = (mAvailableSpaceInPreview - scaledSize) / 2;
72         float totalScale = mBaselineIconScale * scale;
73         final float overlayAlpha = (80 * (1 - r)) / 255f;
74 
75         if (params == null) {
76             params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
77         } else {
78             params.update(transX, transY, totalScale);
79             params.overlayAlpha = overlayAlpha;
80         }
81         return params;
82     }
83 
84     @Override
maxNumItems()85     public int maxNumItems() {
86         return MAX_NUM_ITEMS_IN_PREVIEW;
87     }
88 
89     @Override
scaleForItem(int index, int numItems)90     public float scaleForItem(int index, int numItems) {
91         // Scale is determined by the position of the icon in the preview.
92         index = MAX_NUM_ITEMS_IN_PREVIEW - index - 1;
93         float r = (index * 1.0f) / (MAX_NUM_ITEMS_IN_PREVIEW - 1);
94         return (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
95     }
96 
97     @Override
clipToBackground()98     public boolean clipToBackground() {
99         return false;
100     }
101 
102     @Override
getItemsToDisplay(Folder folder)103     public List<View> getItemsToDisplay(Folder folder) {
104         List<View> items = folder.getItemsInReadingOrder();
105         return items.subList(0, Math.min(items.size(), MAX_NUM_ITEMS_IN_PREVIEW));
106     }
107 }
108