读书人

Android开发之对下上两个图层的操作

发布时间: 2012-08-17 02:08:34 作者: rapoo

Android开发之对上下两个图层的操作
Android开发之对上下两个图层的操作

/*

* Android开发之对上下两个图层的操作

* 北京Android俱乐部群:167839253

* Created on: 2012-7-17

* Author: blueeagle

* Email:liujiaxiang@gmail.com

*/

我们在玩“美女脱衣服”游戏中,看到的可以把美女身上的衣服脱掉,其实是运用了图层的技术。其根本还是两张图片,将上层图片来依据手的触摸使上层图层消失。可以理解为,上层图层是一个View,下层可以是View的一个背景。新建一个View类,myView

这样去写他的构造函数:

注意:Android可设置为随着窗口大小调整缩放比例,但即便如此,手机程序设计人员还是必须知道手机屏幕的边界,以避免缩放造成的布局变形问题。

手机的分辨率信息是手机的一项重要信息,很好的是,Android已经提供DisplayMetircs类可以很方便的获取分辨率。

Andorid.util包下的DisplayMetrics类提供了一种关于显示的通用信息,如显示大小,分辨率和字体。

为了获取DisplayMetrics成员,首先初始化一个对象如下:

DisplayMetrics myMetrics=new DisplayMetrics();

myMetrics =this.getResources().getDisplayMetrics();

//getWindowManager().getDefaultDisplay().getMetrics(myMetrics);

两种方式来给myMetrics值。

注:构造函数DisplayMetrics不需要传递任何参数;调用getWindowManager()之后,会取得现有Activity的Handle,此时,getDefaultDisplay()方法将取得的宽高维度存放于DisplayMetrics对象中,而取得的宽高维度是以像素为单位(Pixel),“像素”所指的是“绝对像素”而非“相对像素”。

setUpBmp(bmp);函数就是设置已经获取到的bmp为上层图像。

在setUpBmp(bmp);函数中,进行以下操作:

Xfermode有三个子类,分别如下:

AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素XOR操作。

PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

要应用转换模式,可以使用setXferMode方法

对应的模式:

PorterDuff.Mode

ADD

Saturate(S + D)

PorterDuff.Mode

CLEAR

[0, 0]

PorterDuff.Mode

DARKEN

[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]

PorterDuff.Mode

DST

[Da, Dc]

PorterDuff.Mode

DST_ATOP

[Sa, Sa * Dc + Sc * (1 - Da)]

PorterDuff.Mode

DST_IN

[Sa * Da, Sa * Dc]

PorterDuff.Mode

DST_OUT

[Da * (1 - Sa), Dc * (1 - Sa)]

PorterDuff.Mode

DST_OVER

[Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc]

PorterDuff.Mode

LIGHTEN

[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]

PorterDuff.Mode

MULTIPLY

[Sa * Da, Sc * Dc]

PorterDuff.Mode

OVERLAY

PorterDuff.Mode

SCREEN

[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]

PorterDuff.Mode

SRC

[Sa, Sc]

PorterDuff.Mode

SRC_ATOP

[Da, Sc * Da + (1 - Sa) * Dc]

PorterDuff.Mode

SRC_IN

[Sa * Da, Sc * Da]

PorterDuff.Mode

SRC_OUT

[Sa * (1 - Da), Sc * (1 - Da)]

PorterDuff.Mode

SRC_OVER

[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc]

PorterDuff.Mode

XOR

[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]

1.PorterDuff.Mode.CLEAR

所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC

显示上层绘制图片
3.PorterDuff.Mode.DST

显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER

正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER

上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN

取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN

取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT

取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT

取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP

取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP

取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR


13.PorterDuff.Mode.DARKEN


14.PorterDuff.Mode.LIGHTEN


15.PorterDuff.Mode.MULTIPLY


16.PorterDuff.Mode.SCREEN

效果图:

Android开发之对下上两个图层的操作

myPaint.setDither(true);

有时候你可能发现设置了背景图片之后,在屏幕上的效果不太理想,主要表现为颜色过渡不平滑,色块现象比较严重.主要原因是因为WiEngine底层设置OpenGL的缓冲区格式缺省是RGB565,这个设置可以提高速度,但是很显然颜色精度会受到影响.这个时候可以用setDither(true)来解决, setDither是TextureNode的方法.

Sprite bg= ...;

bg.setDither(true);

Dither的意思是抖动,是一种用有限颜色模拟其它颜色的方式,比如将白色和红色均匀的混合,你会看到粉红色.通过这种方式, 可以消除背景上的色块,使颜色过渡平滑.这种方式当然会损失一点性能,但是基本也就是背景用一下,问题不大.

WYGLSurfaceView支持透明背景,这种模式下OpenGL使用RGBA8888格式的缓冲区,所以不需要抖动背景图片也将显示的很好.使用透明背景的WYGLSurfaceView很简单:

WYGLSurfaceViewv=new WYGLSurfaceView(this,true);//第二个参数传true表示背景透明

setContentView(v);

游戏需要用透明背景的不多,一般透明背景WYGLSurfaceView可以用在增强现实的应用中

myPaint.setStrokeCap(Paint.Cap.ROUND);

设置笔帽的样子。

myPaint.setStrokeJoin(Paint.Join.ROUND);

Paint.setStrokeJoin(Joinjoin)这里的Join参数为设置结合处的样子,Miter:结合处为锐角, Round:结合处为圆弧:BEVEL:结合处为直线。

OnDraw的实现:

package com.blueeagle.www;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Bitmap.Config;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.MotionEvent;import android.view.View; public class DuotucengActivity extends Activity {    private int SCREENW;    private int SCREENH;    /** Calledwhen the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(new myView(this));    }    public class myView extends View {       private Bitmap myBitmap;    private Canvas myCanvas;    private Paint myPaint;    private Path myPath;    private float myX,myY;    private static final float TOUCH_TOLERANCE = 4;        public myView(Context context) {           super(context);           setFocusable(true);           setScreenWH();           setBackgroundResource(R.drawable.back);           Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.background);           setUpBmp(bmp);       }        private void setUpBmp(Bitmap bmp) {           // TODO Auto-generatedmethod stub           myPaint = new Paint();           myPaint.setAlpha(0);           myPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));           myPaint.setAntiAlias(true);           myPaint.setDither(true);           myPaint.setStyle(Paint.Style.STROKE);           //myPaint.setStrokeCap(Paint.Cap.ROUND);           myPaint.setStrokeJoin(Paint.Join.ROUND);           myPaint.setStrokeWidth(20);           // 设置路径           myPath = new Path();           myBitmap = Bitmap.createBitmap(SCREENW, SCREENH,Config.ARGB_8888);           myCanvas = new Canvas();           myCanvas.setBitmap(myBitmap);           myCanvas.drawBitmap(bmp, 0, 0,null);       }        private void setScreenWH() {           // TODO Auto-generatedmethod stub           DisplayMetrics dm = new DisplayMetrics();           //dm =this.getResources().getDisplayMetrics();           getWindowManager().getDefaultDisplay().getMetrics(dm);           int screenWidth = dm.widthPixels;           int screenHeight = dm.heightPixels;           SCREENW = screenWidth;           SCREENH = screenHeight;       }             protected void onDraw(Canvas canvas){           canvas.drawBitmap(myBitmap, 0, 0,null);           myCanvas.drawPath(myPath, myPaint);           super.onDraw(canvas);       }             private void touch_start(float x, float y){           myPath.reset();           myPath.moveTo(x, y);           myX=x;           myY=y;       }       private void touch_move(float x,float y){           float dx = Math.abs(x-myX);           float dy = Math.abs(y-myY);           if(dx>=TOUCH_TOLERANCE || dy>=TOUCH_TOLERANCE ){              myPath.quadTo(myX, myY, (x+myX)/2, (y+myY)/2);              myX=x;              myY=y;           }       }       private void touch_up(){           myPath.lineTo(myX, myY);           myCanvas.drawPath(myPath,myPaint);           myPath.reset();       }       public boolean onTouchEvent(MotionEvent event){           float x = event.getX();           float y = event.getY();           switch(event.getAction()){           case MotionEvent.ACTION_DOWN:              touch_start(x,y);              invalidate();              break;           case MotionEvent.ACTION_MOVE:              touch_move(x,y);              invalidate();              break;           case MotionEvent.ACTION_UP:              touch_up();              invalidate();              break;           }           return true;       }     }}




读书人网 >Android

热点推荐