android.graphics.Movie-NinePatch

来源:互联网 发布:js parsefloat 精度 编辑:程序博客网 时间:2024/05/29 14:50

  Movie,NinePatch两个类都内容比较少,都是图片相关的,故放在一起翻译。Movie和Bitmap是一样的都是用来处理图片的,只不过Movie是专门用来处理gif图片的,它没有Bitmap那么强大,基本上的功能就是把gif图片显示出来就ok了,它没有初始化函数,由静态函数处获取Movie对象。下面看函数,

public static Movie decodeByteArray (byte[] data, int offset, int length)

public static Movie decodeFile (String pathName)

public static Movie decodeStream (InputStream is)

这三个函数都是用来获取Movie对象的,使用方法跟BitmapFactory类中定义的同名静态函数是一样的。

public void draw(Canvas canvas, float x, float y,Paint paint)

public void draw(Canvas canvas, float x, float y)

在canvas的x,y点(不)使用paint将图片画出来,注意该函数只能画出gif动画的某一帧来,具体某帧由函数setTime确定

public int duration()

该gif动画有多少帧

public int height()

public int width()

获取该gif图片的宽高

public boolean isOpaque()

判断图片是否为不透明的

public boolean setTime(int relativeMilliseconds)

设置当前为第几帧用于显示。

举例使用

private long mMovieStart=0;

 Movie m1=this.getResources().getMovie(R.drawable.poon);
 Movie m2=this.getResources().getMovie(R.drawable.wancan); 
// InputStream is=this.getContext().getResources().openRawResource(R.drawable.usb);
// Movie m1=Movie.decodeStream(is);
 int duration=m1.duration();
 int duration2=m2.duration();
 if(duration==0)
  duration=1000;
 if(duration2==0)
  duration2=1000;
    long now=android.os.SystemClock.uptimeMillis();
    if(mMovieStart==0)
     mMovieStart=now;
    System.out.println("time="+(now-mMovieStart));
    int index=(int)(now-mMovieStart)%duration;
    int index2=(int)(now-mMovieStart)%duration2;
 m1.setTime(index);
 m1.draw(canvas, 100, 100);
 m2.setTime(index2);
 m2.draw(canvas, 100, 300);
 this.invalidate();

 两个动画一起画,第一个动画显示一卡一卡的,第2个动画更夸张,丢掉了很多帧,看起来很不连贯,不明白为何要通过setTime这种方式来画,而没有设置帧数这样的方法。(ps:最近重看了下代码,发现一卡一卡的原因,丢掉很多帧的原因是把对文件的操作放到ondraw函数里边去了,这样每次draw的时候都要先对文件操作一番,生成movie对象,才会画出图片来,难怪卡成那样,把对movie的生成放到view的初始化函数里边去了之后,动画一点都不卡了)

Movie只支持gif格式的图片,用它来解码其它类型的图片都会导致异常。

在搜索Movie的相关信息中,发现很多人都提到Movie没法处理sdcard中的图片,我自己试了一下,发现通过

File file=new File("/mnt/sdcard/txt/poon.gif"); 

FileInputStream fi=null;

Movie m2=null;
 try{
  fi=new FileInputStream(file);

 m2=Movie.decodeStream(fi);

 fi.close();
 }catch(Exception e){}

或者直接调用m2=Movie.decodeFile("/mnt/sdcard/txt/poon.gif");

这样得出来的Movie不是空的,但是画到屏幕上时什么都显示不出来,

查看了下decodeFile,decodeStream两个函数的参考代码,发现两个函数其实是一个函数,第一个函数代码实现是依赖第二个函数的

后来我把try里边的代码改了下

 try{

  fi=new FileInputStream(file);
 int len;
 byte array[]=new byte[1024];
 ByteArrayOutputStream baos=new ByteArrayOutputStream(1024);
 while((len=fi.read(array))>0)
 {
  baos.write(array);
 }
 byte buffe[]=baos.toByteArray();
 m2=Movie.decodeByteArray(buffe, 0, buffe.length);
 //m2=Movie.decodeStream(fi);
 fi.close();
 }catch(Exception e){}

这样gif动画就可以画出到屏幕上来了,这就解决了怎么显示sdcard中的动画问题了。

NinePatch

类NinePatch默认将bitmap分成9个部分来画,其中4个角是不能收缩的,4个边选定一个轴线来进行收缩,中间部分按同一个轴线来收缩,正常情况下中间部分是透明的,这样patch能提供一个长方形区域,当图片增加的内容超过了它本来的边界的时候,NinePatch本质上是允许图片按照用户自定义的方式来伸缩。要了解NinePatch的详细情况,不妨看看2D Graphics的讨论。

Draw 9-Patch工具是一个很有效的创建NinePatch图片的工具,用WYSIWYG的图片编辑方式。

public NinePatch(Bitmap bitmap, byte[] chunk, String srcName)

初始化函数,用于创建NinePatch对象,第2个参数可以如此获取,bitmap.getNinePatchChunk();第三个参数一般为null

 

public void draw(Canvas canvas,Rect location)

public void draw(Canvas canvas,Rect location, Paint paint)

public void draw(Canvas canvas,RectF location)

在location的位置画出该9patch图片。

public int getDensity()

获取图片的density

public int getHeight()

public int getWidth()

获取宽高度

public final Region getTransparentRegion (Rect location)

获取图片在location位置的透明区域

public final boolean hasAlpha()

判断图片是否有alpha这个值,详见bitmap的该函数,意义一样

public static boolean isNinePatchChunk(byte[] chunk)

判断数组chunk是否为该图片的Chunk。

public void setPaint(Paint p)

给该图片设置画笔。

该类的用法要配合android-sdk-windows\tools\draw9patch.bat工具使用,对处理图片的拉伸能减小模糊度。

用法请百度,很多例子