老規(guī)矩,先上圖,這個(gè)效果大家應(yīng)該都很熟悉 想要實(shí)現(xiàn)這樣的效果,在自定義控件的的時(shí)候,要首先分析一下功能要點(diǎn)有下面幾個(gè): 獲取點(diǎn)擊圖片所在位置 獲取相應(yīng)bitmap 在對(duì)應(yīng)位置繪制bitmap 重寫onTouch,實(shí)現(xiàn)一系列的操作
獲取到點(diǎn)擊的控件,獲取到控件的位置和大小,以及索要顯示的圖片
/** * 設(shè)置傳入進(jìn)來的View * * @param originView */ public void setOriginView(View originView, Bitmap bitmap) { viewRect = new Rect(); startRect = new Rect(); //獲取控件的寬高 int width = originView.getWidth(); int height = originView.getHeight(); viewRect.right = width; viewRect.bottom = height;
//記錄控件的原始寬高 startRect.right = width; startRect.bottom = height; int[] loaction = ViewUtils.getLoaction(originView); //獲取到控件相對(duì)于屏幕的絕對(duì)位置 currentPoint.x = loaction[0] ; currentPoint.y = loaction[1] - DeviceUtils.getStatuBarHeight(getContext()); //獲取到控件剛傳入時(shí)候的位置,用于后面歸為的標(biāo)記 startPoint.x = loaction[0] ; startPoint.y = loaction[1] - DeviceUtils.getStatuBarHeight(getContext()); this.bitmap = bitmap; } 在 onDraw 方法中,繪制出相應(yīng)的圖片在繪制的時(shí)候,要注意直接繪制到(0,0)位置,然后再通過translate將圖片唯一到相應(yīng)的位置,這種實(shí)現(xiàn)方法有一個(gè)好處,就是在進(jìn)行計(jì)算的時(shí)候,非常簡(jiǎn)單;
??一開始的時(shí)候我是想通過scaleY,縮放動(dòng)畫來實(shí)現(xiàn)這樣的效果,結(jié)果搞了一天,發(fā)現(xiàn)大小在視覺效果上非常好,但是在唯一和坐標(biāo)確定的計(jì)算上非常麻煩(當(dāng)然,數(shù)學(xué)已經(jīng)還給老師這樣的話我是不會(huì)亂說的) ; mPaint.setColor(Color.BLACK); mPaint.setAlpha((int) ((int) (255*v)/maxScaleX)); canvas.drawRect(0,0,mWidth,mHeight,mPaint); canvas.save(); canvas.translate(currentPoint.x, currentPoint.y); Bitmap bitmap = creatBitmap(this.bitmap, viewRect); canvas.drawBitmap(bitmap,0, 0, null); canvas.restore(); 很明顯,繪制過程非常簡(jiǎn)單,一個(gè)簡(jiǎn)單的繪制背景和圖片操作,背景是不會(huì)改變的,圖片則會(huì)隨著一些動(dòng)作,比如拖拽,動(dòng)畫等效果來改變; ??creatBitmap(this.bitmap, viewRect),這個(gè)方法也是非常簡(jiǎn)單的,沒有什么技術(shù)那點(diǎn),但是為了防止圖片變形,我還是做了一些小小的限制,讓然,一般情況下是沒有問題的; private Bitmap creatBitmap(Bitmap bitmap, Rect viewRect) { float width = viewRect.width(); float height = width * (bitmap.getHeight() * 1.0f / bitmap.getWidth()); return Bitmap.createScaledBitmap(bitmap, (int) width, (int) height, true); } 剩下的就是對(duì) onDraw 方法里面用到的參數(shù)進(jìn)行操作了; ??由于這個(gè)控件涉及到了單擊、雙擊、長(zhǎng)按、拖拽等操作,所以我直接使用了手勢(shì) GestureDetector 來輔助操作; ??首先是拖拽,代碼里面寫的就非常清楚了,就是隨之手指的移動(dòng),不斷的更改圖片的大小和位置參數(shù),然后 postInvalidate();更新下UI就好了 @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!isSacel) { //手指移動(dòng)距離 distanceY = e2.getRawY() - e1.getRawY(); distanceX = e2.getRawX() - e1.getRawX();
if (distanceY > Math.abs(distanceX) && Math.abs(distanceY) > DeviceUtils.getMinTouchSlop(getContext())) { isCanDrag = true;
} if (isCanDrag) {
//滑動(dòng)造成的縮放倍數(shù) float abs = Math.abs((mHeight - distanceY) * maxScaleX / mHeight); abs = abs > maxScaleX ? maxScaleX : (abs < minScaleX ? minScaleX : abs);
//當(dāng)前顯示圖片的寬高 float width = (startRect.width() * abs); float height = (startRect.height() * abs);
//防止圖片變形進(jìn)行的操作 double v = bitmap.getWidth() * 1.0 / bitmap.getHeight(); float endTranX = 0; float endTranY = 0; if (mWidth/mHeight> v){ width = (float) (height*v); endTranX =(mWidth-width)/2; }else { height = (float) (width/v); endTranY=(mHeight-height)/2; }
//更改對(duì)應(yīng)參數(shù) currentPoint.x = distanceX + endTranX; currentPoint.y = distanceY+endTranY; viewRect.right = (int) width; viewRect.bottom = (int) height;
postInvalidate(); } } else { float y = -distanceY*doubliScale + getTranslationY(); float x = -distanceX*doubliScale + getTranslationX(); setTranslationY(y); setTranslationX(x); }
return true; } 這樣,一個(gè)位移縮放功能就完成,由于一開始已經(jīng)記錄下來了圖片的原始數(shù)據(jù),在歸為的時(shí)候只要使用動(dòng)畫歸為就行了,這個(gè)比較簡(jiǎn)單,代碼我就不放了; 最后:附上源碼
http://download.csdn.net/detail/sangxiaonian/9797698
|