第七章 实现炫酷效果—图像和动画(3)

7.3.6超炫的特效—ShapeDrawable

当你想去使用一些常用的图形,ShapeDrawable对象可能会对你有很大的帮助。当然通过ShapeDrawable,你可以通过编程画出任何你想到的图像与样式,因为ShapeDrawable有自己的draw()方法。

ShapeDrawable继承了Drawable,所以你可以调用Drawable里有的函数,使用方法和其他的Drawable的子类差不多。下面我们来介绍它的特色。

通过ShapeDrawable的XML构造文件来了解ShapeDrawable的特性。下面是一个完整图形所包含的所有元素。


<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"

android:shape=["rectangle" | "oval" | "line" | "ring"]>

<gradient

android:angle="integer"

android:centerX="integer"

android:centerY="integer"

android:centerColor="integer"

android:endColor="color"

android:gradientRadius="integer"

android:startColor="color"

android:type=["linear" | "radial" | "sweep"]

android:usesLevel=["true" | "false"] />

<solid

android:color="color" />

<stroke

android:width="integer"

android:color="color"

android:dashWidth="integer"

android:dashGap="integer" />

<padding

android:left="integer"

android:top="integer"

android:right="integer"

android:bottom="integer" />

<corners

android:radius="integer"

android:topLeftRadius="integer"

android:topRightRadius="integer"

android:bottomLeftRadius="integer"

android:bottomRightRadius="integer" />

</shape>

1)android:shape—定义Shape的类型。有效的值包括:"rectangle"矩形,为默认形状。"oval",椭圆。"line",水平直线。需要<stroke>元素定义线的宽度。"ring",环形。

2)<gradient>—为Shape指定渐变色。

l  android:angle—Integer。渐变色的角度值。0表示从左到右,90表示从下到上。必须是45的倍数,默认是0。

l  android:centerX—Float。渐变色中心的X相对位置(0-1.0)。当android:type=”linear”时无效。

l  android:centerY—Float。渐变色中心的Y相对位置(0-1.0)。当android:type=”linear”时无效。

l  android:centerColor—Color。可选的颜色,出现在start和end颜色之间。

l  android:endColor—Color。end颜色。

l  android:gradientRadius—Float。渐变色的半径。当android:type="radial"时有效,而且必须设置。

l  android:startColor—Color。start颜色。

l  android:type—Keyword。渐变色的样式。有效值为:"linear",线性渐变,默认值。"radial",环形渐变。start颜色是处于中间的颜色。"sweep",梯度渐变。"sweep"与"radial"不同的是,"radial"的颜色是从内往外渐变,"sweep"的颜色是从0°到360°渐变。

l  android:useLevel—Boolean。"true"表示可以当作LevelListDrawable使用。

l  android:innerRadius—Dimension。内环的半径。(只能在android:shape="ring"时使用)

l  android:innerRadiusRatio—Float。以环的宽度比率来表示内环的半径。例如,如果android:innerRadiusRatio="5",内环半径等于环的宽度除以5。这个值可以被android:innerRadius覆盖。默认值是9。(只能在android:shape="ring"时使用)

l  android:thickness—Dimension。环的厚度。(只能在android:shape="ring"时使用)

l  android:thicknessRatio—Float。以环的宽度比率来表示环的厚度。例如,如果android:thicknessRatio="2",厚度就等于环的宽度除以2。这个值可以被android:thickness覆盖。默认值是3。(只能在android:shape="ring"时使用)

3)<solid>—填充shape的单一色。

l  android:color—Color。这个颜色会应用到shape上。

4)<stroke>— shape的线形。

l  android:width—Dimension。线的宽度。

l  android:color— Color。线的颜色。

l  android:dashGap—Dimension。线断与线段之间的空白距离。仅在android:dashWidth设定时有效。

l  android:dashWidth—Dimension。线段的长度。仅在android:dashGap设定时有效。

5)<padding>— Dimension。内部View元素的边距。

6)< corners >—为shape创建圆角。当shape是一个“rectangle”时有效。

l  android:radius—Dimension。圆角的半径。会被下面的特性覆盖。

l  android:topLeftRadius—Dimension。左上圆角半径。

l  android:topRightRadius—Dimension。右上圆角半径。

l  android:bottomLeftRadius—Dimension。实际是右下角圆角半径。(android的bug)

l  android:bottomRightRadius—Dimension。实际是左下圆角半径。(android的bug)

在代码中可以直接使用ShapeDrawable的XML文件:


Drawable dr = (Drawable)getResources().getDrawable(R.drawable.shape_1);

dr.setBounds(x, y, x + width, y + height);

dr.draw(canvas);

下面提供一个例子,使用代码来实现如图7-2的效果:

图7-2 ShapeDrawable效果图

下面是具体的代码。


<shape xmlns:android="http://schemas.android.com/apk/res/android"

android:shape="rectangle">

<gradient

android:startColor="#FFFF0000"

android:endColor="#FF0000FF"

android:centerColor="#FF00FF00"

android:angle="315"/>

<corners android:topLeftRadius="8dp"

android:bottomLeftRadius="8dp" />

</shape>


经验分享:

这里对ShapeDrawable的属性进行了详细的解释,是因为在手机软件的设计中,APK包的大小和内存的大小一直是困扰我们的问题,图片又是这些问题中的一个重头戏,而一个简单的xml可以实现一张图片的效果,那么我们就可以减少APK包的大小和内存,何乐而不为呢!同时也很方便的修改,这么有用的东西,希望大家用好它。

同时通过上面的例子我们找到一个Android的问题。android:bottomLeftRadius="8dp",从android的api的说明是左下圆角,而实际设置里却是右下圆角,android:bottomLeftRadius和android:bottomRightRadius是相反的。可能与GradientDrawable.setCornerRadii(float[8] radii)中设置的圆角顺序是相同的,radii是一个长度为8的float数组,设置的是按照顺时针的顺序。

上面主要讲的是通过XML文件来产生一个形状的Drawable,我们也可以通过代码来实现。使用ShapeDrawable的构造函数(publicShapeDrawable(Shape s))来定义一个形状,然后使用mShapeDrawable.getPaint().setShader(Shadershader)来设置ShapeDrawable画笔的渲染方式。这里涉及到两个类android.graphics.drawable.Shapes.Shape,android.graphics.Shader。

图7-3是android.graphics.drawable.Shapes.Shape及它的子类。

图7-3 Shape及它的子类

下面对其子类简单说明一下。

PathShape 使用Path类创建几何路径。

RectShape定义一个矩形。

ArcShape定义一个弧形。

OvalShape定义一个椭圆形。

RoundRectShape定义一个圆角矩形。

在Android中提供了Shader类及其子类,主要是用来渲染图像。图7-4说明了Shader 类的子类。

图7-4 Shader 及它的子类

下面对其子类简单说明一下。

BitmapShader主要用来渲染图像。

LinearGradient 用来进行梯度渲染。

RadialGradient 用来进行环形渲染。

SweepGradient 用来进行梯度渲染。

ComposeShader则是一个混合渲染。

有了上面的基础,我们就可以来实现比较复杂的图形。如图7-5所示:

图7-5 实现复杂的图形效果

是不是很炫,下面提供代码以仔细说明。


// import略

public class ShapeDrawable1 extends GraphicsActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(new SampleView(this));

}

private static class SampleView extends View {

private ShapeDrawable[] mDrawables;

private static Shader makeSweep() {

/* *

* 创建SweepGradient并设置渐变的颜色数组

* 第一个 中心点的x坐标

* 第二个 中心点的y坐标

* 第三个 这个也是一个数组用来指定颜色数组的相对位置

* 如果为null 就沿坡度线均匀分布

* 第四个 设置一个位置数组相对应的颜色数组,从0到1.0。

* 如果位置是null,就将颜色自动均匀的分布。

*/

return new SweepGradient(150, 25,

new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFF0000 }, null);

}

private static Shader makeLinear() {

/* *

* 创建LinearGradient并设置渐变的颜色数组

* 第一个 起始的x坐标

* 第二个 起始的y坐标

* 第三个 结束的x坐标

* 第四个 结束的y坐标

* 第五个 颜色数组

* 第六个 这个也是一个数组用来指定颜色数组的相对位置

* 如果为null 就沿坡度线均匀分布

* 第七个 渲染模式

*/

return new LinearGradient(0, 0, 50, 50,

new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF },null,

Shader.TileMode.MIRROR);

}

private static Shader makeTiling() {

int[] pixels = new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0};

Bitmap bm = Bitmap.createBitmap(pixels, 2, 2, Bitmap.Config.ARGB_8888);

/* 创建一个重复绘画的BitmapShader * */

return new BitmapShader(bm, Shader.TileMode.REPEAT,

Shader.TileMode.REPEAT);

}

/* 自定义一个ShapeDrawable  重写onDraw()方法 * */

private static class MyShapeDrawable extends ShapeDrawable {

private Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

public MyShapeDrawable(Shape s) {

super(s);

mStrokePaint.setStyle(Paint.Style.STROKE);

}

public Paint getStrokePaint() {

return mStrokePaint;

}

@Override

protected void onDraw(Shape s, Canvas c, Paint p) {

s.draw(c, p);

s.draw(c, mStrokePaint);

}

}

public SampleView(Context context) {

super(context);

setFocusable(true);

float[] outerR = new float[] { 12, 12, 12, 12, 0, 0, 0, 0 };

RectF   inset = new RectF(6, 6, 6, 6);

float[] innerR = new float[] { 12, 12, 0, 0, 12, 12, 0, 0 };

Path path = new Path();

path.moveTo(50, 0);

path.lineTo(0, 50);

path.lineTo(50, 100);

path.lineTo(100, 50);

path.close();

mDrawables = new ShapeDrawable[7];

mDrawables[0] = new ShapeDrawable(new RectShape());

mDrawables[1] = new ShapeDrawable(new OvalShape());

mDrawables[2] = new ShapeDrawable(new RoundRectShape(outerR, null, null));

mDrawables[3] = new ShapeDrawable(new RoundRectShape(outerR, inset, null));

mDrawables[4] =new ShapeDrawable(new RoundRectShape(outerR, inset, innerR));

/**

* 创建一个PathShape,参数说明:

* 第一个 PathShape的路径

* 第二个 x坐标缩放的原始比例,例如: ShapeDrawable实际大小为200,

* 那么显示出来的Path图形的x轴是原始的200/100倍

* 第三个 y坐标缩放的原始比例

*/

mDrawables[5] = new ShapeDrawable(new PathShape(path, 100, 100));

/**

* 创建一个弧形ArcShape,参数说明:

* 第一个 开始的角度(注意起始角度在右侧水平为0°角,顺时针增大)

* 第二个 弧度延伸的角度,正数为顺时针延伸

*/

mDrawables[6] = new MyShapeDrawable(new ArcShape(45, -270));

mDrawables[0].getPaint().setColor(0xFFFF0000);

mDrawables[1].getPaint().setColor(0xFF00FF00);

mDrawables[2].getPaint().setColor(0xFF0000FF);

mDrawables[3].getPaint().setShader(makeSweep());

mDrawables[4].getPaint().setShader(makeLinear());

mDrawables[5].getPaint().setShader(makeTiling());

mDrawables[6].getPaint().setColor(0x88FF8844);

PathEffect pe = new DiscretePathEffect(10, 4);

PathEffect pe2 = new CornerPathEffect(4);

mDrawables[3].getPaint().setPathEffect(new ComposePathEffect(pe2, pe));

MyShapeDrawable msd = (MyShapeDrawable)mDrawables[6];

msd.getStrokePaint().setStrokeWidth(4);

}

@Override protected void onDraw(Canvas canvas) {

int x = 10;

int y = 10;

int width = 300;

int height = 50;

// 画出所有Drawable

for (Drawable dr : mDrawables) {

dr.setBounds(x, y, x + width, y + height);

dr.draw(canvas);

y += height + 5;

}

}

}

}

7.3.7简单的帧动画—AnimationDrawable

AnimationDrawable是Android实现动画的一种简单的形式,可以用来实现帧动画。后续有一章节会详细介绍Android的动画。

下面我们来实现一个按钮点击后自动播放不同图片的AnimationDrawable的例子:

1)在res/drawable下定义animation_1.xml文件:


<?xml version="1.0" encoding="utf-8"?>

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"

android:oneshot="false" >

<item android:drawable="@drawable/a1" android:duration="500"></item>

<item android:drawable="@drawable/a2" android:duration="500"></item>

</animation-list>

根标签为animation-list,其中android:oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画,根标签下,通过item标签对动画中的每一个图片进行声明,android:duration表示展示所用的该图片的时间长度。

2)在java代码中载入:


Button mButton = (Button)findViewById(R.id.your_btn);

mButton.setBackgroundResource(R.drawable. animation_1);

AnimationDrawable mAnimationDrawable

= (AnimationDrawable) mButton.getBackground();

// 或当做AnimationDrawable单独拿出来:

AnimationDrawable mAnimationDrawable

= (AnimationDrawable) getResources().getDrawable(R.drawable.animation_1);

3)执行动画


// 动画是否正在运行

if (mAnimationDrawable.isRunning()) {

// 停止动画播放

mAnimationDrawable.stop();

} else {

// 开始或者继续动画播放

mAnimationDrawable.start();

}


经验分享:

默认情况下,在onCreate()中执行animation.start();是无效的,因为在onCreate()中AnimationDrawable还没有完全的与Button绑定,在onCreate()中启动动画,就只能看到第一张图片。

解决的办法,在其它事件中响应触发动画。

时间: 2024-08-23 10:35:12

第七章 实现炫酷效果—图像和动画(3)的相关文章

第七章 实现炫酷效果—图像和动画(1)

第七章实现炫酷效果-图像和动画 学完上一章,相信读者对Android画图核心部分有了一定的了解.为了实现更加炫酷的效果,我们可能会在我们的应用中使用大量的图像和动画效果. 本章我们将详细介绍Android中的各种图像对象的使用,以及动画的使用.学习完本章,相信读者可以独立开发出有着绚丽的视觉效果的Android应用了. 7.1 Android的几种常用图像类型 Android中的图像对象,主要有android.graphics.Bitmap(位图).android.graphics.drawab

第七章 实现炫酷效果—图像和动画(5)

7.7渐变动画-Tween Animation 7.7.1Tween Animation简介 一个Tween动画将对视图对象中的内容进行一系列简单的转换(位置,大小,旋转,透明性).如果你有一个文本视图对象,你可以移动它,旋转它,让它变大或让它变小,如果文字下面还有背景图像,背景图像也会随着文件进行转换. 可以使用XML来定义Tween Animation.首先将动画的XML文件在工程中res/anim目录,这个文件必须包含一个根元素,可以使<alpha><scale> <t

第七章 实现炫酷效果—图像和动画(2)

7.3变化多端-Drawable(绘图类) Drawable资源是Android系统中使用最广泛.最灵活的资源,可以直接使用png.jpg.gif.9.png等图片做为资源文件,也可以使用多种XML文件做为资源文件. 下面详细介绍下各种Drawable资源. 7.3.1Drawable的一些常用子类 Android平台的Drawable代表可以绘制在屏幕上的资源,可以使用getDrawable(int)从资源文件中获取Drawable资源,或者在XML资源文件中采用@drawable方式来引用一

第七章 实现炫酷效果—图像和动画(6)

7.8渐变动画-Frame Animation FrameAnimation是按顺序播放事先做好的图像,跟播放电影类似.可以参考前面的7.3.7章节--<简单的帧动画-AnimationDrawable>. 经验分享: AnimationDrawable也可以通过代码来生成AnimationDrawable对象: AnimationDrawable mAnimationDrawable = new AnimationDrawable(); mAnimationDrawable.addFrame

10大炫酷的HTML5文字动画特效欣赏

文字是网页中最基本的元素,在CSS2.0时代,我们只能在网页上展示静态的文字,只能改变他的大小和颜色,显得枯燥无味.随着HTML5的发展,现在网页中的文字样式变得越来越丰富了,甚至出现了文字动画,HTML5和CSS3的强大之处就在于此.本文分享的10款炫酷的HTML5文字动画特效非常不错,一起来看看吧. 1.HTML5 Canvas粒子效果文字动画特效 之前我们分享过很多超酷的文字特效,其中也有利用HTML5和CSS3的.今天我们要来分享一款基于HTML5 Canvas的文字特效,输入框中输入想

html5跟随鼠标炫酷网站引导页动画特效

html5跟随鼠标炫酷网站引导页动画特效一款非常不错的引导页,文字效果渐变,鼠标跟随出绚丽的条纹.html5炫酷网站引导页,鼠标跟随出特效. 体验效果:http://hovertree.com/texiao/html5/ 效果图: 以下是源代码: 1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="Co

开源分享三(炫酷的Android Loading动画)

开源分享三(炫酷的Android Loading动画) 分享GitHub上的一些Loading,为了提升产品用户体验,一个好的Loading必然是不可缺少的,对于一些耗时需要用户等待的页面来说会转移用户注意力,不会显得那么烦躁,所以你可以看到市面上一些App中的各种各样的Loading动画,从这些实现思路上可以打开你们自己的思维,没准也会有创新的Loading动画出现. android-shapeLoadingView 新版58同城加载页面动画. CircleProgress 一个效果很酷炫很创

8个经典炫酷的HTML5 Canvas动画欣赏

HTML5非常强大,尤其是Canvas技术的应用,让HTML5几乎可以完成所有Flash能完成的效果.本文精选了8个经典炫酷的HTML5 Canvas动画欣赏,每一个都提供全部的源代码,希望对你有所帮助. 1.HTML5 Canvas可拖动的弹性大树摇摆动画 今天让我们继续来分享一个炫酷的HTML5动画,它是一款基于HTML5 Canvas的大树摇摆动画,这款HTML5动画的特点是我们可以拖拽树枝,从而让整棵树摇摆起来,这样就真实地模拟了大树从摇摆到静止的整个过程,相当逼真. 在线演示     

经典炫酷的HTML5/jQuery动画应用示例及源码

jQuery是一款普遍受前端开发者欢迎的Javascript框架,但是开发者貌似更关注jQuery开发的插件,海量的jQuery插件让前端开发者非常方便.HTML5的加入让jQuery这个家族更加丰富多彩,因为利用HTML5,我们可以制作更加绚丽动感的动画特效,HTML5结合jQuery,真是我们开发者的福利啊.本文分享了一些经典炫酷的HTML5/jQuery动画应用,喜欢的朋友可以分享和收藏. jquery视差滑块幻灯特效 很传统的一款jQuery焦点图插件,但是该焦点图插件是宽屏的,整体看起