一直想對之前做過的一款圖片社交軟件cos醬(類似in nice)的代碼進行梳理别厘,但是由于時間的關(guān)系拖到今天才開始這個工作怎棱。
在項目中哩俭,主要對照片裁剪、旋轉(zhuǎn)拳恋、翻轉(zhuǎn)(在之前的文章有提到過)凡资、貼紙、濾鏡谬运、文字隙赁、邊框、標簽等功能梆暖。
如何添加貼紙
- 自定義WaterMarkView;
- 移動伞访、縮放貼紙(用戶的操作行為);
- 合成圖片轰驳。
自定義WaterMarkView
具體如下圖
有圖片中我們可以看到厚掷,貼紙由3部分組成(主體內(nèi)容、刪除按鈕级解、縮放按鈕)冒黑。
所以在ondraw中
canvas.drawBitmap(mBitmap, matrix, paint); mPath.reset(); mPath.moveTo(mLTPoint.x,mLTPoint.y); mPath.lineTo(mRTPoint.x, mRTPoint.y); mPath.lineTo(mRBPoint.x, mRBPoint.y); mPath.lineTo(mLBPoint.x, mLBPoint.y); mPath.lineTo(mLTPoint.x, mLTPoint.y); mPath.lineTo(mRTPoint.x, mRTPoint.y); canvas.drawPath(mPath, mPaint);//畫旋轉(zhuǎn), 縮放圖標controlDrawable.setBounds(mControlPoint.x - mDrawableWidth / 2, mControlPoint.y - mDrawableHeight / 2, mControlPoint.x + mDrawableWidth / 2, mControlPoint.y + mDrawableHeight/2); controlDrawable.draw(canvas); removeDrawable.setBounds(mremovePoint.x - mRemoveDrawableWidth / 2, mremovePoint.y - mRemoveDrawableHeight / 2, mremovePoint.x + mRemoveDrawableWidth / 2, mremovePoint.y + mRemoveDrawableHeight / 2); removeDrawable.draw(canvas);
然后結(jié)合GestureDetector和onTouchEvent進行縮放、移動蠕趁、刪除操作薛闪。具體代碼如下:
switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (!isEditable) { //取消其余貼紙的編輯狀態(tài),只有一個處于編輯狀態(tài) Bundle bundle = new Bundle(); bundle.putSerializable("selectWaterMarkView", this); EventBus.getEventBus().post(new BasePostEvent(CosCameraConstants.WATER_MARK_EDITSTATE_CANCLE, bundle)); //設(shè)置本身被選中 setEditState(true); } mPreMovePointF.set(event.getX() + mViewPaddingLeft, event.getY() + mViewPaddingTop); mStatus = JudgeStatus(event.getX(), event.getY()); break; case MotionEvent.ACTION_UP: mStatus = STATUS_INIT; WaterMarkClicked(event.getX(), event.getY()); break; case MotionEvent.ACTION_MOVE: mCurMovePointF.set(event.getX() + mViewPaddingLeft, event.getY() + mViewPaddingTop); if (mStatus == STATUS_ROTATE_ZOOM) { float scale = 1f; int halfBitmapWidth = mBitmap.getWidth() / 2; int halfBitmapHeight = mBitmap.getHeight() / 2; //圖片某個點到圖片中心的距離 float bitmapToCenterDistance = FloatMath.sqrt(halfBitmapWidth * halfBitmapWidth + halfBitmapHeight * halfBitmapHeight); //移動的點到圖片中心的距離 float moveToCenterDistance = distance4PointF(mCenterPoint, mCurMovePointF); //計算縮放比例 scale = moveToCenterDistance / bitmapToCenterDistance; //縮放比例的界限判斷 if (scale <= MIN_SCALE) { scale = MIN_SCALE; } else if (scale >= MAX_SCALE) { scale = MAX_SCALE; } // 角度 double a = distance4PointF(mCenterPoint, mPreMovePointF); double b = distance4PointF(mPreMovePointF, mCurMovePointF); double c = distance4PointF(mCenterPoint, mCurMovePointF); double cosb = (a * a + c * c - b * b) / (2 * a * c); if (cosb >= 1) { cosb = 1f; } double radian = Math.acos(cosb); float newDegree = (float) radianToDegree(radian); //center -> proMove的向量俺陋, 我們使用PointF來實現(xiàn) PointF centerToProMove = new PointF((mPreMovePointF.x - mCenterPoint.x), (mPreMovePointF.y - mCenterPoint.y)); //center -> curMove 的向量 PointF centerToCurMove = new PointF((mCurMovePointF.x - mCenterPoint.x), (mCurMovePointF.y - mCenterPoint.y)); //向量叉乘結(jié)果, 如果結(jié)果為負數(shù)豁延, 表示為逆時針, 結(jié)果為正數(shù)表示順時針 float result = centerToProMove.x * centerToCurMove.y - centerToProMove.y * centerToCurMove.x; if (result < 0) { newDegree = -newDegree; } mDegree = mDegree + newDegree; mScale = scale; transformDraw(); } else if (mStatus == STATUS_REMOVE) { this.mOnRemoveWaterListener.onRemoveClick(this); } else if (mStatus == STATUS_DRAG) { // 修改中心點 mCenterPoint.x += mCurMovePointF.x - mPreMovePointF.x; mCenterPoint.y += mCurMovePointF.y - mPreMovePointF.y; adjustLayout(); } mPreMovePointF.set(mCurMovePointF); break; }
重要方法transformDraw()介紹
/** * 設(shè)置Matrix, 強制刷新 */ public void transformDraw(){ int bitmapWidth = (int)(mBitmap.getWidth() * mScale); int bitmapHeight = (int)(mBitmap.getHeight()* mScale); computeRect(-framePadding, -framePadding, bitmapWidth + framePadding, bitmapHeight + framePadding, mDegree); //設(shè)置縮放比例 matrix.setScale(mScale, mScale); //繞著圖片中心進行旋轉(zhuǎn) matrix.postRotate(mDegree % 360, bitmapWidth/2, bitmapHeight/2); //設(shè)置畫該圖片的起始點 matrix.postTranslate(offsetX + mDrawableWidth/2, offsetY + mDrawableHeight/2); invalidate(); }
重要方法transformDraw()介紹
/** * 調(diào)整View的大小腊状,位置 */ public void adjustLayout(){ int actualWidth = mViewWidth + mDrawableWidth; int actualHeight = mViewHeight + mDrawableHeight; int newPaddingLeft = (int) (mCenterPoint.x - actualWidth /2); int newPaddingTop = (int) (mCenterPoint.y - actualHeight/2); if(mViewPaddingLeft != newPaddingLeft || mViewPaddingTop != newPaddingTop){ mViewPaddingLeft = newPaddingLeft; mViewPaddingTop = newPaddingTop; layout(newPaddingLeft, newPaddingTop, newPaddingLeft + actualWidth, newPaddingTop + actualHeight); } }
合成圖片
很笨挫的辦法诱咏,通過view生成圖片:
Canvas canvas = new Canvas(new_bitmap); photo_area_rl.draw(canvas);