Android實現圖片的倒影效果
原理:
原圖和倒影圖分解成兩個Bitmap, 倒影的Bitmap設計為原圖的高度一半,寬度一致。然后創建一個可變空的Bitmap, 寬度跟原圖保持一致,寬度為原圖的1.5倍(寬度包括原圖和倒影圖的寬度之和),然后用Canvas關聯這個可變空的Bitmap,在Canvas上將原 圖和倒影圖依次繪制上去就行,為了更接近倒影的效果,需要設計漸變等效果。
主要邏輯如下:
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.widget.ImageView;public class MainActivity extends Activity {
private ImageView mRevertImageView;
private Bitmap mSourceBitmap; //原圖
private Bitmap mRevertBitmap; //倒立圖@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRevertImageView = (ImageView)findViewById(R.id.im_revert); mSourceBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.source); mRevertImageView.setBackground(new BitmapDrawable(getResources(), revertBitmap())); } private Bitmap revertBitmap() { //1.倒立圖 Matrix matrix = new Matrix(); matrix.preScale(1, -1); //以X軸向下翻轉 int width = mSourceBitmap.getWidth(); int height = mSourceBitmap.getHeight(); //生成倒立圖,寬度和原圖一致,高度為原圖的一半 mRevertBitmap = Bitmap.createBitmap(mSourceBitmap, 0, height / 2, width, height / 2, matrix, false); //2.要生成原圖加上倒立圖,先生成一個可變空的Bitmap, 高度為原圖高度的1.5倍(包括原圖和倒立圖的高度) int gap = 10; //間隙空白 Bitmap bitmap = Bitmap.createBitmap(width, height + height / 2, Bitmap.Config.ARGB_8888); Paint paint = new Paint(); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(mSourceBitmap, 0, 0, paint); //繪制原圖 canvas.drawBitmap(mRevertBitmap, 0, height + gap, paint); //繪制倒立圖 //3.畫筆使用LinearGradient 線性漸變渲染 LinearGradient lg = new LinearGradient(0, height + gap, width, bitmap.getHeight(), 0xabff0000, 0x00ffff00, Shader.TileMode.MIRROR); paint.setShader(lg); //4.指定畫筆的Xfermode 即繪制的模式(不同的模式,繪制的區域不同) paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)); //5.在倒立圖區,繪制矩形渲染圖層 canvas.drawRect(0, height + gap, width, bitmap.getHeight(), paint); paint.setXfermode(null); return bitmap; } //縮放圖片 private Bitmap resizeImage(Bitmap bitmap, int width, int height) { int originWidth = bitmap.getWidth(); int originHeight = bitmap.getHeight(); float scaleWidth = width / originWidth; float scaleHeight = height / originHeight; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, originWidth, originHeight, matrix, true); return resizeBitmap; }
} </pre>
PorterDuffXfermode 定義的模式如下:
private static final Xfermode[] sModes = {
new PorterDuffXfermode(PorterDuff.Mode.CLEAR), //所繪制不會提交到畫布上
new PorterDuffXfermode(PorterDuff.Mode.SRC), //顯示上層繪制圖片
new PorterDuffXfermode(PorterDuff.Mode.DST), //顯示下層繪制圖片
new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), //正常繪制顯示,上下層繪制疊蓋
new PorterDuffXfermode(PorterDuff.Mode.DST_OVER), //上下層都顯示。下層居上顯示
new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), //取兩層繪制交集。顯示上層
new PorterDuffXfermode(PorterDuff.Mode.DST_IN), //取兩層繪制交集。顯示下層
new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT), //取上層繪制非交集部分
new PorterDuffXfermode(PorterDuff.Mode.DST_OUT), //取下層繪制非交集部分
new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP), //取下層非交集部分與上層交集部分
new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), //取上層非交集部分與下層交集部分
new PorterDuffXfermode(PorterDuff.Mode.XOR), //濾色效果
new PorterDuffXfermode(PorterDuff.Mode.DARKEN), //濾色效果
new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), //濾色效果
new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY), //濾色效果
new PorterDuffXfermode(PorterDuff.Mode.SCREEN) //濾色效果
};