使用GradientDrawable
GradientDrawable的作用在于定于各种样式的渐变。在XML文件中使用<shape>元素定义。-
文件位置:
-
res/drawable/filename.xml
文件名即资源ID
编译资源类型:
-
指向
GradientDrawable
.
资源引用
-
In Java:
R.drawable.filename
In XML:@[package:]drawable/filename
语法
-
<span class="pun"><?</span><span class="pln">xml version</span><span class="pun">=</span><span class="str">"1.0"</span><span class="pln"> encoding</span><span class="pun">=</span><span class="str">"utf-8"</span><span class="pun">?></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">shape</a><span class="pln"> </span><span class="atn">xmlns:android</span><span class="pun">=</span><span class="atv">"http://schemas.android.com/apk/res/android"</span><span class="pln"> </span><span class="atn">android:shape</span><span class="pun">=</span><span class="atv">["rectangle"</span><span class="pln"> | </span><span class="atv">"oval"</span><span class="pln"> | </span><span class="atv">"line"</span><span class="pln"> | </span><span class="atv">"ring"</span><span class="pln">] </span><span class="tag">></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">corners</a><span class="pln"> </span><span class="atn">android:radius</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:topLeftRadius</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:topRightRadius</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:bottomLeftRadius</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:bottomRightRadius</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">gradient</a><span class="pln"> </span><span class="atn">android:angle</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:centerX</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:centerY</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:centerColor</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:endColor</span><span class="pun">=</span><span class="atv">"</span><em>color</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:gradientRadius</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:startColor</span><span class="pun">=</span><span class="atv">"</span><em>color</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:type</span><span class="pun">=</span><span class="atv">["linear"</span><span class="pln"> | </span><span class="atv">"radial"</span><span class="pln"> | </span><span class="atv">"sweep"</span><span class="pln">] </span><span class="atn">android:useLevel</span><span class="pun">=</span><span class="atv">["true"</span><span class="pln"> | </span><span class="atv">"false"</span><span class="pln">] </span><span class="tag">/></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">padding</a><span class="pln"> </span><span class="atn">android:left</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:top</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:right</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:bottom</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">size</a><span class="pln"> </span><span class="atn">android:width</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:height</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">solid</a><span class="pln"> </span><span class="atn">android:color</span><span class="pun">=</span><span class="atv">"</span><em>color</em><span class="atv">"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"><</span><a target=_blank style="color: rgb(202, 0, 0);">stroke</a><span class="pln"> </span><span class="atn">android:width</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:color</span><span class="pun">=</span><span class="atv">"</span><em>color</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:dashWidth</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="atn">android:dashGap</span><span class="pun">=</span><span class="atv">"</span><em>integer</em><span class="atv">"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"></shape></span>
元素:
-
<padding>
-
内容与视图边界的距离
示例:
-
XML file saved at
res/drawable/gradient_box.xml
:<span class="pun"><?</span><span class="pln">xml version</span><span class="pun">=</span><span class="str">"1.0"</span><span class="pln"> encoding</span><span class="pun">=</span><span class="str">"utf-8"</span><span class="pun">?></span><span class="pln"> </span><span class="tag"><shape</span><span class="pln"> </span><span class="atn">xmlns:android</span><span class="pun">=</span><span class="atv">"http://schemas.android.com/apk/res/android"</span><span class="pln"> </span><span class="atn">android:shape</span><span class="pun">=</span><span class="atv">"rectangle"</span><span class="tag">></span><span class="pln"> </span><span class="tag"><gradient</span><span class="pln"> </span><span class="atn">android:startColor</span><span class="pun">=</span><span class="atv">"#FFFF0000"</span><span class="pln"> </span><span class="atn">android:endColor</span><span class="pun">=</span><span class="atv">"#80FF00FF"</span><span class="pln"> </span><span class="atn">android:angle</span><span class="pun">=</span><span class="atv">"45"</span><span class="tag">/></span><span class="pln"> </span><span class="tag"><padding</span><span class="pln"> </span><span class="atn">android:left</span><span class="pun">=</span><span class="atv">"7dp"</span><span class="pln"> </span><span class="atn">android:top</span><span class="pun">=</span><span class="atv">"7dp"</span><span class="pln"> </span><span class="atn">android:right</span><span class="pun">=</span><span class="atv">"7dp"</span><span class="pln"> </span><span class="atn">android:bottom</span><span class="pun">=</span><span class="atv">"7dp"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"><corners</span><span class="pln"> </span><span class="atn">android:radius</span><span class="pun">=</span><span class="atv">"8dp"</span><span class="pln"> </span><span class="tag">/></span><span class="pln"> </span><span class="tag"></shape></span>
This layout XML applies the shape drawable to a View:
<span class="tag"><TextView</span><span class="pln"> </span><span class="atn">android:background</span><span class="pun">=</span><span class="atv">"@drawable/gradient_box"</span><span class="pln"> </span><span class="atn">android:layout_height</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln"> </span><span class="atn">android:layout_width</span><span class="pun">=</span><span class="atv">"wrap_content"</span><span class="pln"> </span><span class="tag">/></span>
This application code gets the shape drawable and applies it to a View:
<span class="typ">Resources</span><span class="pln"> res </span><span class="pun">=</span><span class="pln"> </span><code><a target=_blank style="color: rgb(202, 0, 0);"><span class="pln">getResources</span><span class="pun">()</span></a></code><span class="pun">;</span><span class="pln"> </span><span class="typ">Drawable</span><span class="pln"> shape </span><span class="pun">=</span><span class="pln"> res</span><span class="pun">.</span><span class="pln"> </span><code><a target=_blank style="color: rgb(202, 0, 0);">getDrawable</a></code><span class="pun">(</span><span class="pln">R</span><span class="pun">.</span><span class="pln">drawable</span><span class="pun">.</span><span class="pln">gradient_box</span><span class="pun">);</span><span class="pln"> </span><span class="typ">TextView</span><span class="pln"> tv </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">TextView</span><span class="pun">)</span><span class="pln">findViewByID</span><span class="pun">(</span><span class="pln">R</span><span class="pun">.</span><span class="pln">id</span><span class="pun">.</span><span class="pln">textview</span><span class="pun">);</span><span class="pln"> tv</span><span class="pun">.</span><span class="pln">setBackground</span><span class="pun">(</span><span class="pln">shape</span><span class="pun">);</span>
参考:
下面是API的Demo:
- package com.example.shapedrawable;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.graphics.Picture;
- import android.graphics.Rect;
- import android.graphics.drawable.Drawable;
- import android.graphics.drawable.GradientDrawable;
- import android.graphics.drawable.ShapeDrawable;
- import android.os.Bundle;
- import android.util.AttributeSet;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.ViewParent;
- import android.widget.TextView;
- public class MainActivity extends GraphicsActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(new SampleView(this));
- }
- private static class SampleView extends View {
- private Path mPath;
- private Paint mPaint;
- private Rect mRect;
- private GradientDrawable mDrawable;
- public SampleView(Context context) {
- super(context);
- setFocusable(true);
- mPath = new Path();
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mRect = new Rect(0, 0, 120, 120);
- mDrawable = new GradientDrawable(
- GradientDrawable.Orientation.TL_BR, new int[] { 0xFFFF0000,
- 0xFF00FF00, 0xFF0000FF });
- mDrawable.setShape(GradientDrawable.RECTANGLE);
- mDrawable.setGradientRadius((float) (Math.sqrt(2) * 60));
- }
- static void setCornerRadii(GradientDrawable drawable, float r0,
- float r1, float r2, float r3) {
- drawable.setCornerRadii(new float[] { r0, r0, r1, r1, r2, r2, r3,
- r3 });
- }
- //重点的绘制过程
- @Override
- protected void onDraw(Canvas canvas) {
- mDrawable.setBounds(mRect);
- float r = 16;
- canvas.save();
- canvas.translate(10, 10);
- mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
- setCornerRadii(mDrawable, r, r, 0, 0);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(10 + mRect.width() + 10, 10);
- mDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
- setCornerRadii(mDrawable, 0, 0, r, r);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.translate(0, mRect.height() + 10);
- canvas.save();
- canvas.translate(10, 10);
- mDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT);
- setCornerRadii(mDrawable, 0, r, r, 0);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(10 + mRect.width() + 10, 10);
- mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
- setCornerRadii(mDrawable, r, 0, 0, r);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.translate(0, mRect.height() + 10);
- canvas.save();
- canvas.translate(10, 10);
- mDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
- setCornerRadii(mDrawable, r, 0, r, 0);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(10 + mRect.width() + 10, 10);
- mDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT);
- setCornerRadii(mDrawable, 0, r, 0, r);
- mDrawable.draw(canvas);
- canvas.restore();
- }
- }
- }
- class GraphicsActivity extends Activity {
- // set to true to test Picture
- private static final boolean TEST_PICTURE = false;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
- @Override
- public void setContentView(View view) {
- if (TEST_PICTURE) {
- ViewGroup vg = new PictureLayout(this);
- vg.addView(view);
- view = vg;
- }
- super.setContentView(view);
- }
- }
- class PictureLayout extends ViewGroup {
- private final Picture mPicture = new Picture();
- public PictureLayout(Context context) {
- super(context);
- }
- public PictureLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- @Override
- public void addView(View child) {
- if (getChildCount() > 1) {
- throw new IllegalStateException(
- "PictureLayout can host only one direct child");
- }
- super.addView(child);
- }
- @Override
- public void addView(View child, int index) {
- if (getChildCount() > 1) {
- throw new IllegalStateException(
- "PictureLayout can host only one direct child");
- }
- super.addView(child, index);
- }
- @Override
- public void addView(View child, LayoutParams params) {
- if (getChildCount() > 1) {
- throw new IllegalStateException(
- "PictureLayout can host only one direct child");
- }
- super.addView(child, params);
- }
- @Override
- public void addView(View child, int index, LayoutParams params) {
- if (getChildCount() > 1) {
- throw new IllegalStateException(
- "PictureLayout can host only one direct child");
- }
- super.addView(child, index, params);
- }
- @Override
- protected LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT);
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int count = getChildCount();
- int maxHeight = 0;
- int maxWidth = 0;
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- measureChild(child, widthMeasureSpec, heightMeasureSpec);
- }
- }
- maxWidth += getPaddingLeft() + getPaddingRight();
- maxHeight += getPaddingTop() + getPaddingBottom();
- Drawable drawable = getBackground();
- if (drawable != null) {
- maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
- maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
- }
- setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
- resolveSize(maxHeight, heightMeasureSpec));
- }
- private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
- float sy) {
- canvas.save();
- canvas.translate(x, y);
- canvas.clipRect(0, 0, w, h);
- canvas.scale(0.5f, 0.5f);
- canvas.scale(sx, sy, w, h);
- canvas.drawPicture(mPicture);
- canvas.restore();
- }
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
- mPicture.endRecording();
- int x = getWidth() / 2;
- int y = getHeight() / 2;
- if (false) {
- canvas.drawPicture(mPicture);
- } else {
- drawPict(canvas, 0, 0, x, y, 1, 1);
- drawPict(canvas, x, 0, x, y, -1, 1);
- drawPict(canvas, 0, y, x, y, 1, -1);
- drawPict(canvas, x, y, x, y, -1, -1);
- }
- }
- @Override
- public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
- location[0] = getLeft();
- location[1] = getTop();
- dirty.set(0, 0, getWidth(), getHeight());
- return getParent();
- }
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- final int count = super.getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- final int childLeft = getPaddingLeft();
- final int childTop = getPaddingTop();
- child.layout(childLeft, childTop,
- childLeft + child.getMeasuredWidth(),
- childTop + child.getMeasuredHeight());
- }
- }
- }
GradientDrawable 表示一个渐变区域,可以实现线性渐变、发散渐变和平铺渐变效果,在Android中可以使用GradientDrawable表示很多复杂而又绚丽的界面效果。
可以使用xml定义GradientDrawable,相对于ColorDrawable类型,GradientDrawable要复杂很多,它有很多的元素组成。在xml文件中使用shape作为根节点来创建GradientDrawable,它包含很多属性和子节点,下面是GradientDrawable的xml文档节点结构。
其中每个节点都有许多属性需要设置,以达到不同的渐变效果。
以下是几种不同渐变效果实现的xml文件代码:
以下几幅图展示了上述三个渐变效果:
可以使用xml定义GradientDrawable,相对于ColorDrawable类型,GradientDrawable要复杂很多,它有很多的元素组成。在xml文件中使用shape作为根节点来创建GradientDrawable,它包含很多属性和子节点,下面是GradientDrawable的xml文档节点结构。
1 | <? xml version = "1.0" encoding = "utf-8" ?> |
2 | < shape xmlns:android = "http://schemas.android.com/apk/res/android" > |
3 | < size /> //定义区域的大小 |
4 | < gradient >//设置区域背景的渐变效果 |
5 | < solid />//设置区域的背景颜色,如果设置了solid会覆盖gradient的效果 |
6 | < stroke />//设置区域的边框效果 |
7 | < padding />//设置区域的内边距 |
8 | </ shape > |
其中每个节点都有许多属性需要设置,以达到不同的渐变效果。
以下是几种不同渐变效果实现的xml文件代码:
01 | <!-- 线性渐变效果的椭圆--> |
02 | <? xml version = "1.0" encoding = "utf-8" ?> |
03 | < shape |
04 | xmlns:android = "http://schemas.android.com/apk/res/android" |
05 | android:shape = "oval" > |
06 |
07 | < gradient |
08 | android:startColor = "#ff0000" |
09 | android:centerColor = "#00ff00" |
10 | android:endColor = "#0000ff" |
11 | android:angle = "90" /> |
12 | < stroke |
13 | android:width = "3dip" |
14 | android:color = "#fff" |
15 | android:dashWidth = "4dip" |
16 | android:dashGap = "5dip" /> |
17 | </ shape > |
18 |
19 | <!-- 平铺渐变效果的圆环--> |
20 | <? xml version = "1.0" encoding = "utf-8" ?> |
21 | < shape xmlns:android = "http://schemas.android.com/apk/res/android" |
22 | android:shape = "ring" android:innerRadiusRatio = "8" |
23 | android:thicknessRatio = "3" android:useLevel = "false" > |
24 | < gradient android:type = "sweep" android:useLevel = "false" |
25 | android:startColor = "#ff0000" android:endColor = "#0000ff" android:centerColor = "#00ff00" /> |
26 | </ shape > |
27 |
28 | <!-- 发散渐变效果的圆--> |
29 | <? xml version = "1.0" encoding = "utf-8" ?> |
30 | < shape xmlns:android = "http://schemas.android.com/apk/res/android" |
31 | android:shape = "ring" android:innerRadius = "0dip" |
32 | android:thickness = "70dip" android:useLevel = "false" > |
33 | < gradient android:type = "radial" android:useLevel = "false" android:gradientRadius = "70" |
34 | android:startColor = "#ff0000" android:endColor = "#0000ff" android:centerColor = "#00ff00" /> |
35 | </ shape > |
以下几幅图展示了上述三个渐变效果:
图6-1 线性渐变效果的椭圆
图6-2 平铺渐变效果的圆环
图6-3 发散渐变效果的圆