Android自定義View_BitmapShader實現望遠鏡效果
日拱一卒,功不唐捐
一、背景
這個特效來源於有一天逛網站的時候,一家網站實現了這樣的一個效果:在你向下滾動頁面的時候,他的背景的圖片隨著你的滑動,以視窗的方式展示著圖片的某一部分。瀏覽完就想著以Android的方式能不能實現,也就演變成了以下的效果。

Telescope
二、知識點BitmapShader
【官方】Shader用於繪製點陣圖作為紋理。點陣圖可以設定模式為重複或映象或平鋪。
簡單來說,Shader可以用來實現一些漸變,反轉,映象,重複等效果。本文的效果核心使用的是Shader中的BitmapShader——點陣圖Shader。
BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
從構造方法可以看出,第一個引數為點陣圖bitmap,第二個和第三個引數分別為橫方向和縱方向的平鋪模式。
平鋪模式有如下幾種模式:
- CLAMP :拉伸,水平拉伸圖片左右方向最後一個畫素,,垂直拉伸圖片上下方向的最後一個畫素。
- MIRROR:映象,水平和垂直方向重複影象,交替映象,使相鄰的影象始終相連。
- REPEAT:重複,水平和垂直方向不斷重複圖片。
三、基本思路
1、建立一張圖片,將畫筆設定為帶有影象填充功能;
2、根據獲取手指所點選位置的座標,根據獲得的座標繪製圓形或者其他圖形。
四、實現
從上述基本思路來看,步驟還是很簡單,那麼接下來分析實現的程式碼。
mPaint = new Paint(); mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.photo2);
首先就是初始化畫筆和建立一張點陣圖。接下來為核心內容。
mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); canvas.drawCircle(400,400,300,mPaint);
BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)新建立一個BitmapShader,並將水平和垂直方向的平鋪模式設定為CLAMP拉伸模式,將BitmapShader屬性設定給畫筆,使畫筆具有影象填充功能,這是後面畫筆可以繪製出一個帶有圖片的圓形的原因。接著利用Canvas在座標(400,400)處繪製出一個半徑為300的圓形。
目前基本的繪製已經結束,執行程式碼可以看出會有圓形圖片在介面顯示,如下圖:

Paint.jpeg
從上面的圖片來看,是不是發現其實這就是一個圓形的頭像,到這裡我們可以想到前面有一篇 Android自定義菱形圖片 使用PorterDuffXfermode的相關屬性繪製菱形的頭像,其實這裡我們也可以使用BitmapShader進行操作,程式碼相比較更加簡潔。
目前實現的是靜態的影象,接下來實現隨著手指動態移動的效果。
private float mTouchEventY = -1; private float mTouchEventX = -1; ...... @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTouchEventX = event.getX(); mTouchEventY = event.getY(); return true; case MotionEvent.ACTION_MOVE: mTouchEventX = event.getX(); mTouchEventY = event.getY(); postInvalidate(); break; } postInvalidate(); return super.onTouchEvent(event); }
首先我們建立兩個全域性變數mTouchEventX,mTouchEventY。在onTouchEvent事件中,手指MotionEvent.ACTION_DOWN的時候,動態獲取手指的位置,在ACTION_DOWN的程式碼中記得 return true ,這涉及到事件的分發機制,當return false時,代表手指的down事件未完成,那麼事件將不會繼續向下傳遞,也就是說ACTION_DOWN動作後的ACTION_MOVE是不會觸發的。
同樣的,我們在MotionEvent.ACTION_MOVE中也動態獲取手指的位置,也就是隨著手指動態調整圓形的位置。
最後在Canvas繪製圓形的時候,將獲取到的位置設定進去,隨著手指的不斷移動,不斷獲取到位置值,也就實現了動態繪製圖像的效果。
canvas.drawCircle(mTouchEventX,mTouchEventY,300,mPaint);
五、最後
在上述的過程中,發現BitmapShader可以很容易的實現不規則頭像。另外,上述也只使用了BitmapShader的拉伸模式,還有映象和重複模式可以實現更多的特效,有待發掘。
文章同步個人部落格: https://fuusy.github.io
專案地址: https://github.com/fuusy/ShaderTelescope.git
公眾號:小猿說

小猿說.jpg