* commit 'ee7ace065f77b53a57cb6273b9f2f5d85caba90c': Fix rendering artifact in edge fades. Bug #4092053
This commit is contained in:
@@ -245,12 +245,13 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
private static native void nDestroyDisplayList(int displayList);
|
||||
|
||||
@Override
|
||||
public boolean drawDisplayList(DisplayList displayList, Rect dirty) {
|
||||
public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) {
|
||||
return nDrawDisplayList(mRenderer,
|
||||
((GLES20DisplayList) displayList).mNativeDisplayList, dirty);
|
||||
((GLES20DisplayList) displayList).mNativeDisplayList, width, height, dirty);
|
||||
}
|
||||
|
||||
private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty);
|
||||
private static native boolean nDrawDisplayList(int renderer, int displayList,
|
||||
int width, int height, Rect dirty);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Hardware layer
|
||||
|
||||
@@ -53,13 +53,15 @@ public abstract class HardwareCanvas extends Canvas {
|
||||
* Draws the specified display list onto this canvas.
|
||||
*
|
||||
* @param displayList The display list to replay.
|
||||
* @param width The width of the display list.
|
||||
* @param height The height of the display list.
|
||||
* @param dirty The dirty region to redraw in the next pass, matters only
|
||||
* if this method returns true, can be null.
|
||||
*
|
||||
* @return True if the content of the display list requires another
|
||||
* drawing pass (invalidate()), false otherwise
|
||||
*/
|
||||
abstract boolean drawDisplayList(DisplayList displayList, Rect dirty);
|
||||
abstract boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty);
|
||||
|
||||
/**
|
||||
* Draws the specified layer onto this canvas.
|
||||
|
||||
@@ -608,7 +608,8 @@ public abstract class HardwareRenderer {
|
||||
|
||||
DisplayList displayList = view.getDisplayList();
|
||||
if (displayList != null) {
|
||||
if (canvas.drawDisplayList(displayList, mRedrawClip)) {
|
||||
if (canvas.drawDisplayList(displayList, view.getWidth(),
|
||||
view.getHeight(), mRedrawClip)) {
|
||||
if (mRedrawClip.isEmpty() || view.getParent() == null) {
|
||||
view.invalidate();
|
||||
} else {
|
||||
|
||||
@@ -59,7 +59,6 @@ import android.util.Pools;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.View.MeasureSpec;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityEventSource;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
@@ -4651,6 +4650,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
* @return True if the event was handled by the view, false otherwise.
|
||||
*/
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event) {
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
|
||||
&& mOnGenericMotionListener.onGenericMotion(this, event)) {
|
||||
return true;
|
||||
@@ -9326,7 +9326,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
}
|
||||
|
||||
final ScrollabilityCache scrollabilityCache = mScrollCache;
|
||||
int length = scrollabilityCache.fadingEdgeLength;
|
||||
final float fadeHeight = scrollabilityCache.fadingEdgeLength;
|
||||
int length = (int) fadeHeight;
|
||||
|
||||
// clip the fade length if top and bottom fades overlap
|
||||
// overlapping fades produce odd-looking artifacts
|
||||
@@ -9341,16 +9342,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
|
||||
if (verticalEdges) {
|
||||
topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
|
||||
drawTop = topFadeStrength > 0.0f;
|
||||
drawTop = topFadeStrength * fadeHeight > 1.0f;
|
||||
bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
|
||||
drawBottom = bottomFadeStrength > 0.0f;
|
||||
drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
|
||||
}
|
||||
|
||||
if (horizontalEdges) {
|
||||
leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
|
||||
drawLeft = leftFadeStrength > 0.0f;
|
||||
drawLeft = leftFadeStrength * fadeHeight > 1.0f;
|
||||
rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
|
||||
drawRight = rightFadeStrength > 0.0f;
|
||||
drawRight = rightFadeStrength * fadeHeight > 1.0f;
|
||||
}
|
||||
|
||||
saveCount = canvas.getSaveCount();
|
||||
@@ -9388,7 +9389,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
final Paint p = scrollabilityCache.paint;
|
||||
final Matrix matrix = scrollabilityCache.matrix;
|
||||
final Shader fade = scrollabilityCache.shader;
|
||||
final float fadeHeight = scrollabilityCache.fadingEdgeLength;
|
||||
|
||||
if (drawTop) {
|
||||
matrix.setScale(1, fadeHeight * topFadeStrength);
|
||||
@@ -9438,6 +9438,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*
|
||||
* @return The known solid color background for this view, or 0 if the color may vary
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(category = "drawing")
|
||||
public int getSolidColor() {
|
||||
return 0;
|
||||
}
|
||||
@@ -11644,6 +11645,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
* @return true if scrolling was clamped to an over-scroll boundary along either
|
||||
* axis, false otherwise.
|
||||
*/
|
||||
@SuppressWarnings({"UnusedParameters"})
|
||||
protected boolean overScrollBy(int deltaX, int deltaY,
|
||||
int scrollX, int scrollY,
|
||||
int scrollRangeX, int scrollRangeY,
|
||||
|
||||
@@ -2585,7 +2585,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
}
|
||||
} else {
|
||||
child.mPrivateFlags &= ~DIRTY_MASK;
|
||||
((HardwareCanvas) canvas).drawDisplayList(displayList, null);
|
||||
((HardwareCanvas) canvas).drawDisplayList(displayList, cr - cl, cb - ct, null);
|
||||
}
|
||||
}
|
||||
} else if (cache != null) {
|
||||
|
||||
@@ -5226,6 +5226,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
*
|
||||
* @return The cache color hint
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(category = "drawing")
|
||||
public int getCacheColorHint() {
|
||||
return mCacheColorHint;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject o,
|
||||
const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
|
||||
|
||||
SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
|
||||
SkScalar* pos = NULL;
|
||||
SkScalar* pos = NULL;
|
||||
|
||||
if (posArray) {
|
||||
AutoJavaFloatArray autoPos(env, posArray, count);
|
||||
@@ -164,7 +164,11 @@ static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader*
|
||||
}
|
||||
} else {
|
||||
storedPositions[0] = 0.0f;
|
||||
storedPositions[1] = 1.0f;
|
||||
const jfloat step = 1.0f / (count - 1);
|
||||
for (size_t i = 1; i < count - 1; i++) {
|
||||
storedPositions[i] = step * i;
|
||||
}
|
||||
storedPositions[count - 1] = 1.0f;
|
||||
}
|
||||
|
||||
SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
|
||||
@@ -289,7 +293,11 @@ static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader*
|
||||
}
|
||||
} else {
|
||||
storedPositions[0] = 0.0f;
|
||||
storedPositions[1] = 1.0f;
|
||||
const jfloat step = 1.0f / (count - 1);
|
||||
for (size_t i = 1; i < count - 1; i++) {
|
||||
storedPositions[i] = step * i;
|
||||
}
|
||||
storedPositions[count - 1] = 1.0f;
|
||||
}
|
||||
|
||||
SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
|
||||
@@ -384,7 +392,11 @@ static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* s
|
||||
}
|
||||
} else {
|
||||
storedPositions[0] = 0.0f;
|
||||
storedPositions[1] = 1.0f;
|
||||
const jfloat step = 1.0f / (count - 1);
|
||||
for (size_t i = 1; i < count - 1; i++) {
|
||||
storedPositions[i] = step * i;
|
||||
}
|
||||
storedPositions[count - 1] = 1.0f;
|
||||
}
|
||||
|
||||
SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
|
||||
|
||||
@@ -498,9 +498,10 @@ static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
|
||||
}
|
||||
|
||||
static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
|
||||
jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty) {
|
||||
jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList,
|
||||
jint width, jint height, jobject dirty) {
|
||||
android::uirenderer::Rect bounds;
|
||||
bool redraw = renderer->drawDisplayList(displayList, bounds);
|
||||
bool redraw = renderer->drawDisplayList(displayList, width, height, bounds);
|
||||
if (redraw && dirty != NULL) {
|
||||
env->CallVoidMethod(dirty, gRectClassInfo.set,
|
||||
int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
|
||||
@@ -664,7 +665,7 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
|
||||
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
|
||||
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
|
||||
{ "nDrawDisplayList", "(IILandroid/graphics/Rect;)Z",
|
||||
{ "nDrawDisplayList", "(IIIILandroid/graphics/Rect;)Z",
|
||||
(void*) android_view_GLES20Canvas_drawDisplayList },
|
||||
|
||||
{ "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
|
||||
|
||||
@@ -285,9 +285,12 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level)
|
||||
break;
|
||||
case DrawDisplayList: {
|
||||
DisplayList* displayList = getDisplayList();
|
||||
DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
|
||||
displayList, level + 1);
|
||||
needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1);
|
||||
uint32_t width = getUInt();
|
||||
uint32_t height = getUInt();
|
||||
DISPLAY_LIST_LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
|
||||
displayList, width, height, level + 1);
|
||||
needsInvalidate |= renderer.drawDisplayList(displayList, width, height,
|
||||
dirty, level + 1);
|
||||
}
|
||||
break;
|
||||
case DrawLayer: {
|
||||
@@ -674,11 +677,13 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot
|
||||
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
|
||||
}
|
||||
|
||||
bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
|
||||
bool DisplayListRenderer::drawDisplayList(DisplayList* displayList,
|
||||
uint32_t width, uint32_t height, Rect& dirty, uint32_t level) {
|
||||
// dirty is an out parameter and should not be recorded,
|
||||
// it matters only when replaying the display list
|
||||
addOp(DisplayList::DrawDisplayList);
|
||||
addDisplayList(displayList);
|
||||
addSize(width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,10 @@ private:
|
||||
return mReader.readInt();
|
||||
}
|
||||
|
||||
inline uint32_t getUInt() {
|
||||
return mReader.readU32();
|
||||
}
|
||||
|
||||
SkMatrix* getMatrix() {
|
||||
return (SkMatrix*) getInt();
|
||||
}
|
||||
@@ -238,7 +242,8 @@ public:
|
||||
|
||||
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
|
||||
bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
|
||||
bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
|
||||
Rect& dirty, uint32_t level = 0);
|
||||
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
|
||||
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
||||
@@ -323,6 +328,11 @@ private:
|
||||
mWriter.writeInt(value);
|
||||
}
|
||||
|
||||
inline void addSize(uint32_t w, uint32_t h) {
|
||||
mWriter.writeInt(w);
|
||||
mWriter.writeInt(h);
|
||||
}
|
||||
|
||||
void addInts(const int32_t* values, uint32_t count) {
|
||||
mWriter.writeInt(count);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
|
||||
@@ -403,10 +403,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
|
||||
|
||||
// Window coordinates of the layer
|
||||
Rect bounds(left, top, right, bottom);
|
||||
if (fboLayer) {
|
||||
// Clear the previous layer regions before we change the viewport
|
||||
clearLayerRegions();
|
||||
} else {
|
||||
if (!fboLayer) {
|
||||
mSnapshot->transform->mapRect(bounds);
|
||||
|
||||
// Layers only make sense if they are in the framebuffer's bounds
|
||||
@@ -464,8 +461,14 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
|
||||
snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
|
||||
}
|
||||
// Enqueue the buffer coordinates to clear the corresponding region later
|
||||
mLayers.push(new Rect(bounds));
|
||||
|
||||
// Clear the framebuffer where the layer will draw
|
||||
glScissor(bounds.left, mSnapshot->height - bounds.bottom,
|
||||
bounds.getWidth(), bounds.getHeight());
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
dirtyClip();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,31 +763,6 @@ void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLRenderer::clearLayerRegions() {
|
||||
if (mLayers.size() == 0 || mSnapshot->isIgnored()) return;
|
||||
|
||||
Rect clipRect(*mSnapshot->clipRect);
|
||||
clipRect.snapToPixelBoundaries();
|
||||
|
||||
for (uint32_t i = 0; i < mLayers.size(); i++) {
|
||||
Rect* bounds = mLayers.itemAt(i);
|
||||
if (clipRect.intersects(*bounds)) {
|
||||
// Clear the framebuffer where the layer will draw
|
||||
glScissor(bounds->left, mSnapshot->height - bounds->bottom,
|
||||
bounds->getWidth(), bounds->getHeight());
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Restore the clip
|
||||
dirtyClip();
|
||||
}
|
||||
|
||||
delete bounds;
|
||||
}
|
||||
|
||||
mLayers.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Transforms
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -870,7 +848,6 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::setupDraw() {
|
||||
clearLayerRegions();
|
||||
if (mDirtyClip) {
|
||||
setScissorFromClip();
|
||||
}
|
||||
@@ -1064,12 +1041,18 @@ void OpenGLRenderer::finishDrawTexture() {
|
||||
// Drawing
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
|
||||
bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
|
||||
Rect& dirty, uint32_t level) {
|
||||
if (quickReject(0.0f, 0.0f, width, height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
|
||||
// will be performed by the display list itself
|
||||
if (displayList) {
|
||||
return displayList->replay(*this, dirty, level);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,8 @@ public:
|
||||
bool quickReject(float left, float top, float right, float bottom);
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
|
||||
virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
|
||||
virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
|
||||
Rect& dirty, uint32_t level = 0);
|
||||
virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
|
||||
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
||||
@@ -246,12 +247,6 @@ private:
|
||||
*/
|
||||
void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
|
||||
|
||||
/**
|
||||
* Clears all the regions corresponding to the current list of layers.
|
||||
* This method MUST be invoked before any drawing operation.
|
||||
*/
|
||||
void clearLayerRegions();
|
||||
|
||||
/**
|
||||
* Mark the layer as dirty at the specified coordinates. The coordinates
|
||||
* are transformed with the supplied matrix.
|
||||
@@ -499,9 +494,6 @@ private:
|
||||
// Various caches
|
||||
Caches& mCaches;
|
||||
|
||||
// List of rectangles to clear due to calls to saveLayer()
|
||||
Vector<Rect*> mLayers;
|
||||
|
||||
// Indentity matrix
|
||||
const mat4 mIdentity;
|
||||
|
||||
|
||||
@@ -231,9 +231,11 @@ struct ProgramDescription {
|
||||
* Logs the specified message followed by the key identifying this program.
|
||||
*/
|
||||
void log(const char* message) const {
|
||||
#if DEBUG_PROGRAMS
|
||||
programid k = key();
|
||||
PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
|
||||
uint32_t(k & 0xffffffff));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
22
tests/HwAccelerationTest/res/drawable/gradient.xml
Normal file
22
tests/HwAccelerationTest/res/drawable/gradient.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:startColor="#FF707070"
|
||||
android:endColor="#FF0C0C0C"
|
||||
android:angle="270" />
|
||||
</shape>
|
||||
@@ -193,6 +193,7 @@ public class GradientsActivity extends Activity {
|
||||
private final float mDrawWidth;
|
||||
private final float mDrawHeight;
|
||||
private final LinearGradient mGradient;
|
||||
private final LinearGradient mGradientStops;
|
||||
private final Matrix mMatrix;
|
||||
|
||||
ShadersView(Context c) {
|
||||
@@ -202,6 +203,9 @@ public class GradientsActivity extends Activity {
|
||||
mDrawHeight = 200;
|
||||
|
||||
mGradient = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
|
||||
mGradientStops = new LinearGradient(0, 0, 0, 1,
|
||||
new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF }, null, Shader.TileMode.CLAMP);
|
||||
|
||||
mMatrix = new Matrix();
|
||||
|
||||
mPaint = new Paint();
|
||||
@@ -255,6 +259,19 @@ public class GradientsActivity extends Activity {
|
||||
mGradient.setLocalMatrix(mMatrix);
|
||||
canvas.drawRect(left, top, left + mDrawWidth, bottom, mPaint);
|
||||
|
||||
right = left + mDrawWidth;
|
||||
left = 40.0f;
|
||||
top = bottom + 20.0f;
|
||||
bottom = top + 50.0f;
|
||||
|
||||
mPaint.setShader(mGradientStops);
|
||||
|
||||
mMatrix.setScale(1, mDrawWidth);
|
||||
mMatrix.postRotate(90);
|
||||
mMatrix.postTranslate(right, top);
|
||||
mGradientStops.setLocalMatrix(mMatrix);
|
||||
canvas.drawRect(left, top, right, bottom, mPaint);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class TransparentListActivity extends Activity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.default_wallpaper));
|
||||
getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.gradient));
|
||||
setContentView(R.layout.list_activity);
|
||||
|
||||
ListAdapter adapter = new SimpleListAdapter(this);
|
||||
|
||||
Reference in New Issue
Block a user