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