11db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu/* 21db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * Copyright (C) 2015 The Android Open Source Project 31db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * 41db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 51db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * in compliance with the License. You may obtain a copy of the License at 61db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * 71db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * http://www.apache.org/licenses/LICENSE-2.0 81db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * 91db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License 101db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 111db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * or implied. See the License for the specific language governing permissions and limitations under 121db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * the License. 131db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu */ 141db5382081756ee276c1fb88f5ebdbc138b70249Dake Gupackage android.support.v17.leanback.widget; 151db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 161db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.content.Context; 171db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.content.res.TypedArray; 181db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.graphics.Canvas; 191db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.graphics.Rect; 201db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.graphics.drawable.Drawable; 211db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.os.Build.VERSION; 221db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.util.AttributeSet; 231db5382081756ee276c1fb88f5ebdbc138b70249Dake Guimport android.widget.LinearLayout; 241db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 251db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu/** 261db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * Implements foreground drawable before M and falls back to M's foreground implementation. 271db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu */ 281db5382081756ee276c1fb88f5ebdbc138b70249Dake Guclass NonOverlappingLinearLayoutWithForeground extends LinearLayout { 291db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 301db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu private static final int VERSION_M = 23; 311db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 321db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu private Drawable mForeground; 331db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu private boolean mForegroundBoundsChanged; 341db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu private final Rect mSelfBounds = new Rect(); 351db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 361db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public NonOverlappingLinearLayoutWithForeground(Context context) { 371db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu this(context, null); 381db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 391db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 401db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public NonOverlappingLinearLayoutWithForeground(Context context, AttributeSet attrs) { 411db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu this(context, attrs, 0); 421db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 431db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 441db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public NonOverlappingLinearLayoutWithForeground(Context context, AttributeSet attrs, 451db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu int defStyle) { 461db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu super(context, attrs, defStyle); 471db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (context.getApplicationInfo().targetSdkVersion >= VERSION_M 481db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu && VERSION.SDK_INT >= VERSION_M) { 49c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas // don't need do anything, base View constructor >=M already reads the foreground if 501db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu // targetSDK is >= M. 511db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } else { 521db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu // in other cases, including M but targetSDK is less than M, we need setForeground in 531db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu // code. 541db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu TypedArray a = context.obtainStyledAttributes(attrs, 551db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu new int[] { android.R.attr.foreground }); 561db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu Drawable d = a.getDrawable(0); 571db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (d != null) { 581db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu setForegroundCompat(d); 591db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 60b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu a.recycle(); 611db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 621db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 631db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 641db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public void setForegroundCompat(Drawable d) { 651db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (VERSION.SDK_INT >= VERSION_M) { 661db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu // From M, foreground is naturally supported. 671db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu ForegroundHelper.getInstance().setForeground(this, d); 681db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } else { 691db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu // before M, do our own customized foreground draw. 701db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (mForeground != d) { 711db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForeground = d; 721db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForegroundBoundsChanged = true; 731db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu setWillNotDraw(false); 741db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForeground.setCallback(this); 751db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (mForeground.isStateful()) { 761db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForeground.setState(getDrawableState()); 771db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 781db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 791db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 801db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 811db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 821db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public Drawable getForegroundCompat() { 831db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (VERSION.SDK_INT >= VERSION_M) { 841db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu return ForegroundHelper.getInstance().getForeground(this); 851db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } else { 861db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu return mForeground; 871db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 881db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 891db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 901db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu @Override 911db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public void draw(Canvas canvas) { 921db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu super.draw(canvas); 931db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (mForeground != null) { 941db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu final Drawable foreground = mForeground; 951db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (mForegroundBoundsChanged) { 961db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForegroundBoundsChanged = false; 971db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu final Rect selfBounds = mSelfBounds; 981db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu final int w = getRight() - getLeft(); 991db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu final int h = getBottom() - getTop(); 1001db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu selfBounds.set(0, 0, w, h); 1011db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu foreground.setBounds(selfBounds); 1021db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1031db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu foreground.draw(canvas); 1041db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1051db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1061db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 1071db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu @Override 1081db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 1091db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu super.onLayout(changed, left, top, right, bottom); 1101db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForegroundBoundsChanged |= changed; 1111db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1121db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 1131db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu @Override 1141db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu protected boolean verifyDrawable(Drawable who) { 1151db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu return super.verifyDrawable(who) || (who == mForeground); 1161db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1171db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 1181db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu @Override 1191db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public void jumpDrawablesToCurrentState() { 1201db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu super.jumpDrawablesToCurrentState(); 1211db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (mForeground != null) { 1221db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForeground.jumpToCurrentState(); 1231db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1241db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1251db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 1261db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu @Override 1271db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu protected void drawableStateChanged() { 1281db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu super.drawableStateChanged(); 1291db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu if (mForeground != null && mForeground.isStateful()) { 1301db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu mForeground.setState(getDrawableState()); 1311db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1321db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1331db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu 1341db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu /** 1351db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * Avoids creating a hardware layer when animating alpha. 1361db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu */ 1371db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu @Override 1381db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu public boolean hasOverlappingRendering() { 1391db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu return false; 1401db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu } 1411db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu}