1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.recent; 18 19 import android.content.Context; 20 import android.content.res.TypedArray; 21 import android.graphics.Canvas; 22 import android.graphics.LinearGradient; 23 import android.graphics.Matrix; 24 import android.graphics.Paint; 25 import android.graphics.Shader; 26 import android.util.AttributeSet; 27 import android.view.View; 28 import android.view.ViewConfiguration; 29 import android.widget.LinearLayout; 30 31 import com.android.systemui.R; 32 33 public class FadedEdgeDrawHelper { 34 public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true; 35 public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true; 36 private View mScrollView; 37 38 private int mFadingEdgeLength; 39 private boolean mIsVertical; 40 private boolean mSoftwareRendered = false; 41 private Paint mBlackPaint; 42 private Paint mFadePaint; 43 private Matrix mFadeMatrix; 44 private LinearGradient mFade; 45 create(Context context, AttributeSet attrs, View scrollView, boolean isVertical)46 public static FadedEdgeDrawHelper create(Context context, 47 AttributeSet attrs, View scrollView, boolean isVertical) { 48 boolean isTablet = context.getResources(). 49 getBoolean(R.bool.config_recents_interface_for_tablets); 50 if (!isTablet && (OPTIMIZE_SW_RENDERED_RECENTS || USE_DARK_FADE_IN_HW_ACCELERATED_MODE)) { 51 return new FadedEdgeDrawHelper(context, attrs, scrollView, isVertical); 52 } else { 53 return null; 54 } 55 } 56 FadedEdgeDrawHelper(Context context, AttributeSet attrs, View scrollView, boolean isVertical)57 public FadedEdgeDrawHelper(Context context, 58 AttributeSet attrs, View scrollView, boolean isVertical) { 59 mScrollView = scrollView; 60 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View); 61 mFadingEdgeLength = a.getDimensionPixelSize(android.R.styleable.View_fadingEdgeLength, 62 ViewConfiguration.get(context).getScaledFadingEdgeLength()); 63 mIsVertical = isVertical; 64 } 65 onAttachedToWindowCallback( LinearLayout layout, boolean hardwareAccelerated)66 public void onAttachedToWindowCallback( 67 LinearLayout layout, boolean hardwareAccelerated) { 68 mSoftwareRendered = !hardwareAccelerated; 69 if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) 70 || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { 71 mScrollView.setVerticalFadingEdgeEnabled(false); 72 mScrollView.setHorizontalFadingEdgeEnabled(false); 73 } 74 } 75 addViewCallback(View newLinearLayoutChild)76 public void addViewCallback(View newLinearLayoutChild) { 77 if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { 78 final RecentsPanelView.ViewHolder holder = 79 (RecentsPanelView.ViewHolder) newLinearLayoutChild.getTag(); 80 holder.labelView.setDrawingCacheEnabled(true); 81 holder.labelView.buildDrawingCache(); 82 } 83 } 84 drawCallback(Canvas canvas, int left, int right, int top, int bottom, int scrollX, int scrollY, float topFadingEdgeStrength, float bottomFadingEdgeStrength, float leftFadingEdgeStrength, float rightFadingEdgeStrength, int mPaddingTop)85 public void drawCallback(Canvas canvas, 86 int left, int right, int top, int bottom, int scrollX, int scrollY, 87 float topFadingEdgeStrength, float bottomFadingEdgeStrength, 88 float leftFadingEdgeStrength, float rightFadingEdgeStrength, int mPaddingTop) { 89 90 if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) 91 || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { 92 if (mFadePaint == null) { 93 mFadePaint = new Paint(); 94 mFadeMatrix = new Matrix(); 95 // use use a height of 1, and then wack the matrix each time we 96 // actually use it. 97 mFade = new LinearGradient(0, 0, 0, 1, 0xCC000000, 0, Shader.TileMode.CLAMP); 98 // PULL OUT THIS CONSTANT 99 mFadePaint.setShader(mFade); 100 } 101 102 // draw the fade effect 103 boolean drawTop = false; 104 boolean drawBottom = false; 105 boolean drawLeft = false; 106 boolean drawRight = false; 107 108 float topFadeStrength = 0.0f; 109 float bottomFadeStrength = 0.0f; 110 float leftFadeStrength = 0.0f; 111 float rightFadeStrength = 0.0f; 112 113 final float fadeHeight = mFadingEdgeLength; 114 int length = (int) fadeHeight; 115 116 // clip the fade length if top and bottom fades overlap 117 // overlapping fades produce odd-looking artifacts 118 if (mIsVertical && (top + length > bottom - length)) { 119 length = (bottom - top) / 2; 120 } 121 122 // also clip horizontal fades if necessary 123 if (!mIsVertical && (left + length > right - length)) { 124 length = (right - left) / 2; 125 } 126 127 if (mIsVertical) { 128 topFadeStrength = Math.max(0.0f, Math.min(1.0f, topFadingEdgeStrength)); 129 drawTop = topFadeStrength * fadeHeight > 1.0f; 130 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, bottomFadingEdgeStrength)); 131 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 132 } 133 134 if (!mIsVertical) { 135 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, leftFadingEdgeStrength)); 136 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 137 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, rightFadingEdgeStrength)); 138 drawRight = rightFadeStrength * fadeHeight > 1.0f; 139 } 140 141 if (drawTop) { 142 mFadeMatrix.setScale(1, fadeHeight * topFadeStrength); 143 mFadeMatrix.postTranslate(left, top); 144 mFade.setLocalMatrix(mFadeMatrix); 145 canvas.drawRect(left, top, right, top + length, mFadePaint); 146 147 if (mBlackPaint == null) { 148 // Draw under the status bar at the top 149 mBlackPaint = new Paint(); 150 mBlackPaint.setColor(0xFF000000); 151 } 152 canvas.drawRect(left, top - mPaddingTop, right, top, mBlackPaint); 153 } 154 155 if (drawBottom) { 156 mFadeMatrix.setScale(1, fadeHeight * bottomFadeStrength); 157 mFadeMatrix.postRotate(180); 158 mFadeMatrix.postTranslate(left, bottom); 159 mFade.setLocalMatrix(mFadeMatrix); 160 canvas.drawRect(left, bottom - length, right, bottom, mFadePaint); 161 } 162 163 if (drawLeft) { 164 mFadeMatrix.setScale(1, fadeHeight * leftFadeStrength); 165 mFadeMatrix.postRotate(-90); 166 mFadeMatrix.postTranslate(left, top); 167 mFade.setLocalMatrix(mFadeMatrix); 168 canvas.drawRect(left, top, left + length, bottom, mFadePaint); 169 } 170 171 if (drawRight) { 172 mFadeMatrix.setScale(1, fadeHeight * rightFadeStrength); 173 mFadeMatrix.postRotate(90); 174 mFadeMatrix.postTranslate(right, top); 175 mFade.setLocalMatrix(mFadeMatrix); 176 canvas.drawRect(right - length, top, right, bottom, mFadePaint); 177 } 178 } 179 } 180 getVerticalFadingEdgeLength()181 public int getVerticalFadingEdgeLength() { 182 return mFadingEdgeLength; 183 } 184 getHorizontalFadingEdgeLength()185 public int getHorizontalFadingEdgeLength() { 186 return mFadingEdgeLength; 187 } 188 189 } 190