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