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 13 ViewGroup.OnHierarchyChangeListener, Insettable { 14 15 @ViewDebug.ExportedProperty(category = "launcher") 16 protected Rect mInsets = new Rect(); 17 getInsets()18 public Rect getInsets() { 19 return mInsets; 20 } 21 InsettableFrameLayout(Context context, AttributeSet attrs)22 public InsettableFrameLayout(Context context, AttributeSet attrs) { 23 super(context, attrs); 24 setOnHierarchyChangeListener(this); 25 } 26 setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets)27 public void setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets) { 28 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 29 30 if (child instanceof Insettable) { 31 ((Insettable) child).setInsets(newInsets); 32 } else if (!lp.ignoreInsets) { 33 lp.topMargin += (newInsets.top - oldInsets.top); 34 lp.leftMargin += (newInsets.left - oldInsets.left); 35 lp.rightMargin += (newInsets.right - oldInsets.right); 36 lp.bottomMargin += (newInsets.bottom - oldInsets.bottom); 37 } 38 child.setLayoutParams(lp); 39 } 40 41 @Override setInsets(Rect insets)42 public void setInsets(Rect insets) { 43 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by 44 // modifying child layout params. 45 if (insets.equals(mInsets)) return; 46 47 final int n = getChildCount(); 48 for (int i = 0; i < n; i++) { 49 final View child = getChildAt(i); 50 setFrameLayoutChildInsets(child, insets, mInsets); 51 } 52 mInsets.set(insets); 53 } 54 55 @Override generateLayoutParams(AttributeSet attrs)56 public LayoutParams generateLayoutParams(AttributeSet attrs) { 57 return new InsettableFrameLayout.LayoutParams(getContext(), attrs); 58 } 59 60 @Override generateDefaultLayoutParams()61 protected LayoutParams generateDefaultLayoutParams() { 62 return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 63 } 64 65 // Override to allow type-checking of LayoutParams. 66 @Override checkLayoutParams(ViewGroup.LayoutParams p)67 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 68 return p instanceof InsettableFrameLayout.LayoutParams; 69 } 70 71 @Override generateLayoutParams(ViewGroup.LayoutParams p)72 protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 73 return new LayoutParams(p); 74 } 75 76 public static class LayoutParams extends FrameLayout.LayoutParams { 77 boolean ignoreInsets = false; 78 LayoutParams(Context c, AttributeSet attrs)79 public LayoutParams(Context c, AttributeSet attrs) { 80 super(c, attrs); 81 TypedArray a = c.obtainStyledAttributes(attrs, 82 R.styleable.InsettableFrameLayout_Layout); 83 ignoreInsets = a.getBoolean( 84 R.styleable.InsettableFrameLayout_Layout_layout_ignoreInsets, false); 85 a.recycle(); 86 } 87 LayoutParams(int width, int height)88 public LayoutParams(int width, int height) { 89 super(width, height); 90 } 91 LayoutParams(ViewGroup.LayoutParams lp)92 public LayoutParams(ViewGroup.LayoutParams lp) { 93 super(lp); 94 } 95 } 96 97 @Override onChildViewAdded(View parent, View child)98 public void onChildViewAdded(View parent, View child) { 99 setFrameLayoutChildInsets(child, mInsets, new Rect()); 100 } 101 102 @Override onChildViewRemoved(View parent, View child)103 public void onChildViewRemoved(View parent, View child) { 104 } 105 106 } 107