第七章 实现炫酷效果—图像和动画(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()中启动动画,就只能看到第一张图片。

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

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Java程序设计》课程实验指导书程序代码(答案)(实验五:Java的异常处理),个人原创,仅供参考与交流。 希望多多交流,共同进步! 实验五 Java的异常处理 一、实验目的: 理解 java 语言中独特的异常处理机制; 掌握异常处理方法; 正确地使用捕获异常和声明抛弃异常的两种异常处理的方法; 了解自定义异常类的使用; 理解抛出异常和声明抛出异常的区别与联系; 二、实验内容: 1. 从命令行得到5个整数,放入一整型数组,然后打印输出,要求:如果输入数据不为整数,要捕获Integer.parseInt()产生的异常,显示“请输入整数”,捕获输入参数不足5个的异常(数组越界),显示“请输入至少5个整数”。 2.写一个方法void sanjiao(int a,int b,int c),判断三个参数是否能构成一个三角形,如果不能则抛出异常IllegalArgumentException,显示异常信息a,b,c+”不能构成三角形”,如果可以构成则显示三角形三个边长,在主方法中得到命令行输入的三个整数,调用此方法,并捕获异常。 3.自定义类Sanj,其中有成员 x,y,z,作为三边长,构造方法Sanj(a,b,c)分别给x,y,z赋值,方法求面积getArea和显示三角形信息(三个边长)showInfo,这2个方法中当三条边不能构成一个三角形时要抛出自定义异常NotSanjiaoException,否则显示正确信息。在另外一个类中的主方法中构造一个Sanj对象(三边为命令行输入的三个整数),显示三角形信息和面积,要求捕获异常。 三、实验要求: 1. 通过实验掌握捕获异常和声明抛弃异常的两种异常处理的方法; 2. 程序必须能够捕获Integer.parseInt()产生的异常并作相应的处理; 3. 程序必须能够将处理的相应的信息输出出来; 4. 写出实验报告。要求记录编译和执行Java程序当中的系统错误信息提材示,并给出解决办法。(附运行界面、源代码)。 四、实验步骤: 1. (第1题) 使用try…..catch…. finally语句对Integer.parseInt()产生的异常进行捕获处理; 2. (第2题) 定义方法void sanjiao(int a,int b,int c)中,不符合条件则抛出异常(if a+b<=c(或a+c<=b,b+c<=a) then throw new IllegalArgumentException(),),再定义main方法,调用此方法,用try…..catch…. finally语句并捕获异常; 3. (第3题) 定义三角形类及相应的方法, 在定义的方法中对不符合条件则抛出异常(如上题) ,再定义main方法,对正确的数据输出正确信息,否则捕获异常; 五、自做实验 1.参考下面的程序,试修改程序,捕获相关异常,使得程序能正常运行。[提示:用错误数据测试,即可得到异常类名,运行时主方法参数输入 abc 测试] public class StringIndexOutOf{ public static void main(String args[]){ System.out.println("字符串索引越界异常"); String str=args[0]; System.out.println(“第四个字符为 ”+str.charAt(3)); int aa=Integer.parseInt(args[0]); System.out.println(“平方为 ”+aa*aa); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值