/* * Copyright (c) 2015 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com> * All Rights Reserved. */ package me.zhanghai.android.douya.ui; import android.annotation.TargetApi; import android.os.Build; import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewCompat; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; import android.widget.FrameLayout; /** * Helper for dispatching transformed insets to children. Also dispatch insets to newly added child. */ // Notice that WindowInsets is immutable. public class DispatchInsetsHelper { private Delegate mDelegate; // TODO: Use Object for compatibility? private WindowInsets mInsets; public DispatchInsetsHelper(Delegate delegate) { mDelegate = delegate; } // Not calling super deliberately. @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { mInsets = insets; ViewGroup viewGroup = mDelegate.getOwner(); int layoutDirection = ViewCompat.getLayoutDirection(viewGroup); for (int i = 0, count = viewGroup.getChildCount(); i < count; ++i) { View child = viewGroup.getChildAt(i); dispatchInsetsToChild(layoutDirection, child, child.getLayoutParams()); } return insets.consumeSystemWindowInsets(); } public void addView(View child, int index, ViewGroup.LayoutParams params) { if (mInsets != null) { dispatchInsetsToChild(child, params); } mDelegate.superAddView(child, index, params); } public boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout) { if (mInsets != null) { dispatchInsetsToChild(child, params); } return mDelegate.superAddViewInLayout(child, index, params, preventRequestLayout); } @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) private void dispatchInsetsToChild(int layoutDirection, View child, ViewGroup.LayoutParams childLayoutParams) { int childGravity = GravityCompat.getAbsoluteGravity( mDelegate.getGravityFromLayoutParams(childLayoutParams), layoutDirection); // In fact equivalent to the algorithm in Gravity.apply(). int childInsetLeft = mInsets.getSystemWindowInsetLeft(); int childInsetRight = mInsets.getSystemWindowInsetRight(); if (childLayoutParams.width != FrameLayout.LayoutParams.MATCH_PARENT) { if ((childGravity & (Gravity.AXIS_PULL_BEFORE << Gravity.AXIS_X_SHIFT)) == 0) { childInsetLeft = 0; } if ((childGravity & (Gravity.AXIS_PULL_AFTER << Gravity.AXIS_X_SHIFT)) == 0) { childInsetRight = 0; } } int childInsetTop = mInsets.getSystemWindowInsetTop(); int childInsetBottom = mInsets.getSystemWindowInsetBottom(); if (childLayoutParams.height != FrameLayout.LayoutParams.MATCH_PARENT) { if ((childGravity & (Gravity.AXIS_PULL_BEFORE << Gravity.AXIS_Y_SHIFT)) == 0) { childInsetTop = 0; } if ((childGravity & (Gravity.AXIS_PULL_AFTER << Gravity.AXIS_Y_SHIFT)) == 0) { childInsetBottom = 0; } } WindowInsets childInsets = mInsets.replaceSystemWindowInsets(childInsetLeft, childInsetTop, childInsetRight, childInsetBottom); child.dispatchApplyWindowInsets(childInsets); } private void dispatchInsetsToChild(View child, ViewGroup.LayoutParams childLayoutParams) { dispatchInsetsToChild(ViewCompat.getLayoutDirection(mDelegate.getOwner()), child, childLayoutParams); } public interface Delegate { int getGravityFromLayoutParams(ViewGroup.LayoutParams layoutParams); ViewGroup getOwner(); void superAddView(View child, int index, ViewGroup.LayoutParams params); boolean superAddViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout); } }