效果展示
本文檔將介紹在android上如何實現一個倒影效果的Gallery。
爲了達到上圖所示的效果,
首先,是需要有一個自定義的gallery,實現了對Gallery的繼承,通過重寫getChildStaticTransformation方 法來控制,每個子view有不同的縮放比例,形成階梯狀的展示。這個gallery是在坤庭的代碼基礎上實現的,我這裏就不再重複介紹。
接下來,gallery中的每個view,都是一個自定義的MirrorView,由它來實現了畫原圖及畫倒影。新的算法解決了性能問題,下面就重 點說一下這部分內容:
鏡像特效最近還蠻流行的,尤其在HTC 的Sense 介面上,常常都可以見到。大家可以看到,加了個鏡像特效後,那感覺就很立體,感覺上好像是這些圖片擺立在一個玻璃桌面上。
在Android 上要幫圖片加上鏡像特效,會不會很麻煩?一點也不麻煩,只要幾行代碼,就可以搞定。
因此,在開始看答案之前,我會建議你要先有Photoshop 的使用經驗。想想,如果用Photoshop 要幫圖片加上鏡像特效,要如何做?我想一般不外乎是先複製個圖片,並將其垂直翻轉,接着再對這翻轉的圖片,加個由灰到黑的漸層mask 即可。
好了,讓我們來看一下答案。底下就是幫圖片加上鏡像特效的程式範例。
Paint m_paint;
int m_nShadowH;
Drawable m_dw;
Bitmap m_bitmap;
Matrix mMatrix;
int shadowHeight;
public MirrorView(Context context, Bitmap bitmap) {
super (context);
m_bitmap = bitmap;
_Init();
}
private void _Init() {
//m_dw = new BitmapDrawable(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
m_dw = new BitmapDrawable(m_bitmap);
m_dw.setBounds(0,0,m_dw.getIntrinsicWidth(),m_dw.getIntrinsicHeight());
m_nShadowH = m_dw.getIntrinsicHeight()/1;
m_paint = new Paint(Paint.ANTI_ALIAS_FLAG );
LinearGradient lg = new LinearGradient(0, 0, 0, m_nShadowH, 0xB0FFFFFF, 0×00000000, Shader.TileMode.CLAMP );
m_paint.setShader(lg);
m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY ));
mMatrix = new Matrix();
}
@Override
public void onDraw(Canvas canvas) {
super .onDraw(canvas);
int nX = 0;
int nY = 0;
_DrawNormalImg(canvas, nX, nY);
_DrawMirror(canvas, nX, nY);
}
private void _DrawNormalImg(Canvas canvas, int nX, int nY) {
canvas.save(Canvas.MATRIX_SAVE_FLAG );
canvas.translate(nX, nY);
m_dw.draw(canvas);
canvas.restore();
}
private void _DrawMirror(Canvas canvas, int nX, int nY) {
int nW = m_dw.getIntrinsicWidth();
int nH = m_dw.getIntrinsicHeight();
shadowHeight=nH/2;
float [] src={0, nH, nW, nH, nW,nH – m_nShadowH, 0, nH – m_nShadowH};
float [] dst={ 0, nH, nW, nH,nW, shadowHeight, 0, shadowHeight };
canvas.save();
mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
canvas.concat(mMatrix);
//draw mirror image
canvas.save(Canvas.MATRIX_SAVE_FLAG );
canvas.scale(1.0f, -1.0f);
canvas.translate(nX, -(nY + nH * 2));
canvas.clipRect(0, nH, nW, nH – m_nShadowH);
m_dw.draw(canvas);
canvas.restore();
//draw mask
canvas.save();
canvas.translate(nX, nY + nH);
canvas.drawRect(0, 0, nW, m_nShadowH, m_paint);
canvas.restore();
canvas.restore();
}
}
_DrawMirror() 方法是關鍵。用Photoshop 要如何做出鏡像特效?第一步是先畫出垂直翻轉的圖片。
Android 繪圖座標體系預設的原點在左上角,X 軸往右是越來越大的正值,而Y 軸往下,則是越來越大的正值。要畫出垂直翻轉的圖片,其實也就是要垂直翻轉整個繪圖座標體系。在 Android 中,要如何做?答案就是 canvas.scale(1.0f, -1.0f)。很簡單吧,沒想到給scale() 函式一個負值,就可以翻轉相對應的軸。
在Photoshop 中,做鏡像特效的第二步是要對這翻轉的圖片,加個由灰到黑的漸層mask。
在Android 中,要畫漸層色,那就一定得用LinearGradient 這個類別。至於要對背景圖加上個mask,就請參考一下Paint 的setXfermode() 函式。 _Init() 這個函式,就是負責生成一個由灰到黑漸層mask 的m_paint 物件。
這個控件我測試過,200張圖片加入adapter,在大數據量情況下性能也沒有問題。