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 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 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 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 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 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 181 public int getVerticalFadingEdgeLength() { 182 return mFadingEdgeLength; 183 } 184 185 public int getHorizontalFadingEdgeLength() { 186 return mFadingEdgeLength; 187 } 188 189 } 190