1 package com.android.launcher3;
2 
3 import android.content.Context;
4 import android.content.res.TypedArray;
5 import android.graphics.Rect;
6 import android.util.AttributeSet;
7 import android.view.View;
8 import android.view.ViewDebug;
9 import android.view.ViewGroup;
10 import android.widget.FrameLayout;
11 
12 public class InsettableFrameLayout extends FrameLayout implements Insettable {
13 
14     @ViewDebug.ExportedProperty(category = "launcher")
15     protected Rect mInsets = new Rect();
16 
getInsets()17     public Rect getInsets() {
18         return mInsets;
19     }
20 
InsettableFrameLayout(Context context, AttributeSet attrs)21     public InsettableFrameLayout(Context context, AttributeSet attrs) {
22         super(context, attrs);
23     }
24 
setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets)25     public void setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets) {
26         final LayoutParams lp = (LayoutParams) child.getLayoutParams();
27 
28         if (child instanceof Insettable) {
29             ((Insettable) child).setInsets(newInsets);
30         } else if (!lp.ignoreInsets) {
31             lp.topMargin += (newInsets.top - oldInsets.top);
32             lp.leftMargin += (newInsets.left - oldInsets.left);
33             lp.rightMargin += (newInsets.right - oldInsets.right);
34             lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
35         }
36         child.setLayoutParams(lp);
37     }
38 
39     @Override
setInsets(Rect insets)40     public void setInsets(Rect insets) {
41         final int n = getChildCount();
42         for (int i = 0; i < n; i++) {
43             final View child = getChildAt(i);
44             setFrameLayoutChildInsets(child, insets, mInsets);
45         }
46         mInsets.set(insets);
47     }
48 
49     @Override
generateLayoutParams(AttributeSet attrs)50     public LayoutParams generateLayoutParams(AttributeSet attrs) {
51         return new InsettableFrameLayout.LayoutParams(getContext(), attrs);
52     }
53 
54     @Override
generateDefaultLayoutParams()55     protected LayoutParams generateDefaultLayoutParams() {
56         return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
57     }
58 
59     // Override to allow type-checking of LayoutParams.
60     @Override
checkLayoutParams(ViewGroup.LayoutParams p)61     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
62         return p instanceof InsettableFrameLayout.LayoutParams;
63     }
64 
65     @Override
generateLayoutParams(ViewGroup.LayoutParams p)66     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
67         return new LayoutParams(p);
68     }
69 
70     public static class LayoutParams extends FrameLayout.LayoutParams {
71         public boolean ignoreInsets = false;
72 
LayoutParams(Context c, AttributeSet attrs)73         public LayoutParams(Context c, AttributeSet attrs) {
74             super(c, attrs);
75             TypedArray a = c.obtainStyledAttributes(attrs,
76                     R.styleable.InsettableFrameLayout_Layout);
77             ignoreInsets = a.getBoolean(
78                     R.styleable.InsettableFrameLayout_Layout_layout_ignoreInsets, false);
79             a.recycle();
80         }
81 
LayoutParams(int width, int height)82         public LayoutParams(int width, int height) {
83             super(width, height);
84         }
85 
LayoutParams(ViewGroup.LayoutParams lp)86         public LayoutParams(ViewGroup.LayoutParams lp) {
87             super(lp);
88         }
89     }
90 
91     @Override
onViewAdded(View child)92     public void onViewAdded(View child) {
93         super.onViewAdded(child);
94         setFrameLayoutChildInsets(child, mInsets, new Rect());
95     }
96 
dispatchInsets(ViewGroup parent, Rect insets)97     public static void dispatchInsets(ViewGroup parent, Rect insets) {
98         final int n = parent.getChildCount();
99         for (int i = 0; i < n; i++) {
100             final View child = parent.getChildAt(i);
101             if (child instanceof Insettable) {
102                 ((Insettable) child).setInsets(insets);
103             }
104         }
105     }
106 }
107