1 package androidx.leanback.widget; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.drawable.Drawable; 6 import android.util.AttributeSet; 7 import android.view.View; 8 import android.widget.ImageView; 9 import android.widget.RelativeLayout; 10 11 import androidx.leanback.R; 12 13 /** 14 * Relative layout implementation that lays out child views based on provided keyline percent( 15 * distance of TitleView baseline from the top). 16 * 17 * Repositioning child views in PreDraw callback in {@link GuidanceStylist} was interfering with 18 * fragment transition. To avoid that, we do that in the onLayout pass. 19 */ 20 class GuidanceStylingRelativeLayout extends RelativeLayout { 21 private float mTitleKeylinePercent; 22 23 public GuidanceStylingRelativeLayout(Context context) { 24 this(context, null); 25 } 26 27 public GuidanceStylingRelativeLayout(Context context, AttributeSet attrs) { 28 this(context, attrs, 0); 29 } 30 31 public GuidanceStylingRelativeLayout(Context context, AttributeSet attrs, int defStyle) { 32 super(context, attrs, defStyle); 33 mTitleKeylinePercent = getKeyLinePercent(context); 34 } 35 36 public static float getKeyLinePercent(Context context) { 37 TypedArray ta = context.getTheme().obtainStyledAttributes( 38 R.styleable.LeanbackGuidedStepTheme); 39 float percent = ta.getFloat(R.styleable.LeanbackGuidedStepTheme_guidedStepKeyline, 40); 40 ta.recycle(); 41 return percent; 42 } 43 44 @Override 45 protected void onLayout(boolean changed, int l, int t, int r, int b) { 46 super.onLayout(changed, l, t, r, b); 47 48 View mTitleView = getRootView().findViewById(R.id.guidance_title); 49 View mBreadcrumbView = getRootView().findViewById(R.id.guidance_breadcrumb); 50 View mDescriptionView = getRootView().findViewById( 51 R.id.guidance_description); 52 ImageView mIconView = getRootView().findViewById(R.id.guidance_icon); 53 int mTitleKeylinePixels = (int) (getMeasuredHeight() * mTitleKeylinePercent / 100); 54 55 if (mTitleView != null && mTitleView.getParent() == this) { 56 int titleViewBaseline = mTitleView.getBaseline(); 57 int mBreadcrumbViewHeight = mBreadcrumbView.getMeasuredHeight(); 58 int guidanceTextContainerTop = mTitleKeylinePixels 59 - titleViewBaseline - mBreadcrumbViewHeight - mTitleView.getPaddingTop(); 60 int offset = guidanceTextContainerTop - mBreadcrumbView.getTop(); 61 62 if (mBreadcrumbView != null && mBreadcrumbView.getParent() == this) { 63 mBreadcrumbView.offsetTopAndBottom(offset); 64 } 65 66 mTitleView.offsetTopAndBottom(offset); 67 68 if (mDescriptionView != null && mDescriptionView.getParent() == this) { 69 mDescriptionView.offsetTopAndBottom(offset); 70 } 71 } 72 73 if (mIconView != null && mIconView.getParent() == this) { 74 Drawable drawable = mIconView.getDrawable(); 75 if (drawable != null) { 76 mIconView.offsetTopAndBottom( 77 mTitleKeylinePixels - mIconView.getMeasuredHeight() / 2); 78 } 79 } 80 } 81 } 82