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 RecentsScrollViewPerformanceHelper { 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 42 public static RecentsScrollViewPerformanceHelper create(Context context, 43 AttributeSet attrs, View scrollView, boolean isVertical) { 44 boolean isTablet = context.getResources(). 45 getBoolean(R.bool.config_recents_interface_for_tablets); 46 if (!isTablet && (OPTIMIZE_SW_RENDERED_RECENTS || USE_DARK_FADE_IN_HW_ACCELERATED_MODE)) { 47 return new RecentsScrollViewPerformanceHelper(context, attrs, scrollView, isVertical); 48 } else { 49 return null; 50 } 51 } 52 53 public RecentsScrollViewPerformanceHelper(Context context, 54 AttributeSet attrs, View scrollView, boolean isVertical) { 55 mScrollView = scrollView; 56 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View); 57 mFadingEdgeLength = a.getDimensionPixelSize(android.R.styleable.View_fadingEdgeLength, 58 ViewConfiguration.get(context).getScaledFadingEdgeLength()); 59 mIsVertical = isVertical; 60 } 61 62 public void onAttachedToWindowCallback( 63 RecentsCallback callback, LinearLayout layout, boolean hardwareAccelerated) { 64 mSoftwareRendered = !hardwareAccelerated; 65 if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) 66 || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { 67 mScrollView.setVerticalFadingEdgeEnabled(false); 68 mScrollView.setHorizontalFadingEdgeEnabled(false); 69 } 70 } 71 72 public void addViewCallback(View newLinearLayoutChild) { 73 if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { 74 final RecentsPanelView.ViewHolder holder = 75 (RecentsPanelView.ViewHolder) newLinearLayoutChild.getTag(); 76 holder.labelView.setDrawingCacheEnabled(true); 77 holder.labelView.buildDrawingCache(); 78 } 79 } 80 81 public void drawCallback(Canvas canvas, 82 int left, int right, int top, int bottom, int scrollX, int scrollY, 83 float topFadingEdgeStrength, float bottomFadingEdgeStrength, 84 float leftFadingEdgeStrength, float rightFadingEdgeStrength) { 85 86 if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) 87 || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { 88 Paint p = new Paint(); 89 Matrix matrix = new Matrix(); 90 // use use a height of 1, and then wack the matrix each time we 91 // actually use it. 92 Shader fade = new LinearGradient(0, 0, 0, 1, 0xCC000000, 0, Shader.TileMode.CLAMP); 93 // PULL OUT THIS CONSTANT 94 95 p.setShader(fade); 96 97 // draw the fade effect 98 boolean drawTop = false; 99 boolean drawBottom = false; 100 boolean drawLeft = false; 101 boolean drawRight = false; 102 103 float topFadeStrength = 0.0f; 104 float bottomFadeStrength = 0.0f; 105 float leftFadeStrength = 0.0f; 106 float rightFadeStrength = 0.0f; 107 108 final float fadeHeight = mFadingEdgeLength; 109 int length = (int) fadeHeight; 110 111 // clip the fade length if top and bottom fades overlap 112 // overlapping fades produce odd-looking artifacts 113 if (mIsVertical && (top + length > bottom - length)) { 114 length = (bottom - top) / 2; 115 } 116 117 // also clip horizontal fades if necessary 118 if (!mIsVertical && (left + length > right - length)) { 119 length = (right - left) / 2; 120 } 121 122 if (mIsVertical) { 123 topFadeStrength = Math.max(0.0f, Math.min(1.0f, topFadingEdgeStrength)); 124 drawTop = topFadeStrength * fadeHeight > 1.0f; 125 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, bottomFadingEdgeStrength)); 126 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 127 } 128 129 if (!mIsVertical) { 130 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, leftFadingEdgeStrength)); 131 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 132 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, rightFadingEdgeStrength)); 133 drawRight = rightFadeStrength * fadeHeight > 1.0f; 134 } 135 136 if (drawTop) { 137 matrix.setScale(1, fadeHeight * topFadeStrength); 138 matrix.postTranslate(left, top); 139 fade.setLocalMatrix(matrix); 140 canvas.drawRect(left, top, right, top + length, p); 141 } 142 143 if (drawBottom) { 144 matrix.setScale(1, fadeHeight * bottomFadeStrength); 145 matrix.postRotate(180); 146 matrix.postTranslate(left, bottom); 147 fade.setLocalMatrix(matrix); 148 canvas.drawRect(left, bottom - length, right, bottom, p); 149 } 150 151 if (drawLeft) { 152 matrix.setScale(1, fadeHeight * leftFadeStrength); 153 matrix.postRotate(-90); 154 matrix.postTranslate(left, top); 155 fade.setLocalMatrix(matrix); 156 canvas.drawRect(left, top, left + length, bottom, p); 157 } 158 159 if (drawRight) { 160 matrix.setScale(1, fadeHeight * rightFadeStrength); 161 matrix.postRotate(90); 162 matrix.postTranslate(right, top); 163 fade.setLocalMatrix(matrix); 164 canvas.drawRect(right - length, top, right, bottom, p); 165 } 166 } 167 } 168 169 public int getVerticalFadingEdgeLengthCallback() { 170 return mFadingEdgeLength; 171 } 172 173 public int getHorizontalFadingEdgeLengthCallback() { 174 return mFadingEdgeLength; 175 } 176 177 } 178