Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 仿qq上傳頭像(一)

Android 仿qq上傳頭像(一)

編輯:關於Android編程

 

 

這麼長時間沒寫博客感覺手都要生了啊,最近因為工作的關系來到了上海,目前還算穩定,所以抓緊時間寫篇博客壓壓驚。

標題早已經看穿一切,這次我們來模仿一下qq上傳頭像的功能,先上一個未完成版的效果圖,銀魂第四季重開放上一張萌萌哒的圖片。

\

這還是要用到我們自定義View的知識,首先從相冊中獲取圖片的部分我就不詳細介紹了。

/**
	 * 獲得圖片
	 */
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == CHOOSE_BIG_PICTURE) {
			photoBitmap = null;
			photoViewBitmap = null;
			try {
				Uri originalUri = data.getData();
				int angle = getExifOrientation(getRealPathFromURI(originalUri));
				if (angle != 0) { // 如果照片出現了 旋轉 那麼 就更改旋轉度數
					Matrix matrix = new Matrix();
					matrix.postRotate(angle);
					photoBitmap = getBitmapFromUri(photoBitmap, originalUri);
					photoViewBitmap = Bitmap.createBitmap(photoBitmap, 0, 0,
							photoBitmap.getWidth(), photoBitmap.getHeight(),
							matrix, true);
					clipView.setBitmap(photoViewBitmap);
				} else {
					clipView.setBitmap(getBitmapFromUri(photoBitmap,
							originalUri));
				}
				photoBitmap.recycle();
				photoViewBitmap.recycle();
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}
	}
我當時用的是三星的Note3測試發現獲取的圖片會發生旋轉十分的坑爹。。所以我們還需要根據uri拿到路徑然後再判斷圖片是否旋轉。
	/**
	 * 根據Uri獲得bitmap
	 * 
	 * @param bitmap
	 * @param uri
	 * @return
	 */
	private Bitmap getBitmapFromUri(Bitmap bitmap, Uri uri) {
		try {
			bitmap = MediaStore.Images.Media.getBitmap(
					this.getContentResolver(), uri);
			return bitmap;
		} catch (Exception e) {
			Log.d(TAG, e.getLocalizedMessage());
			return null;
		}
	}

	/**
	 * 獲得系統相冊圖片
	 */
	private void getAlbum() {
		Intent intent = new Intent(Intent.ACTION_PICK);
		intent.setType(image/*);// 相片類型
		startActivityForResult(intent, CHOOSE_BIG_PICTURE);
	}

	/**
	 * 旋轉圖片
	 * 
	 * @param filepath
	 * @return
	 */
	private int getExifOrientation(String filepath) {
		int degree = 0;
		ExifInterface exif = null;
		try {
			exif = new ExifInterface(filepath);
		} catch (IOException ex) {
		}
		if (exif != null) {
			int orientation = exif.getAttributeInt(
					ExifInterface.TAG_ORIENTATION, -1);
			if (orientation != -1) {
				switch (orientation) {
				case ExifInterface.ORIENTATION_ROTATE_90:
					degree = 90;
					break;
				case ExifInterface.ORIENTATION_ROTATE_180:
					degree = 180;
					break;
				case ExifInterface.ORIENTATION_ROTATE_270:
					degree = 270;
					break;
				}
			}
		}
		return degree;
	}

	/**
	 * 根據Uri拿到路徑
	 * 
	 * @param contentUri
	 * @return
	 */
	public String getRealPathFromURI(Uri contentUri) {
		String res = null;
		String[] proj = { MediaStore.Images.Media.DATA };
		Cursor cursor = getContentResolver().query(contentUri, proj, null,
				null, null);
		if (cursor.moveToFirst()) {
			int column_index = cursor
					.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			res = cursor.getString(column_index);
		}
		cursor.close();
		return res;
	}

拿到圖片之後就進入我們的自定義view環節啦。
public class ClipView extends View {

	/**
	 * 畫筆
	 */
	private Paint paint;
	/**
	 * 圖片
	 */
	private Bitmap mBitmap;
	/**
	 * 畫布
	 */
	private Canvas mCanvas;
	/**
	 * 蒙版
	 */
	private Bitmap bitmap;
	/**
	 * 起點坐標
	 */
	private int startX, startY;
	/**
	 * 移動距離
	 */
	private int distanceX, distanceY;
	/**
	 * 圖片坐標
	 */
	private int widthX, heightY;
	int x = 0, y = 0;

	public ClipView(Context context) {
		super(context);
		init();
		// TODO Auto-generated constructor stub
	}

	public ClipView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public ClipView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}
我們默認把傳進來的圖片縮放至600,800這樣不會讓圖片過大也不會過小。
/**
	 * 縮放圖片
	 * 
	 * @param bgimage
	 * @param newWidth
	 * @param newHeight
	 * @return
	 */
	private Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {
		// 獲取這個圖片的寬和高
		float width = bgimage.getWidth();
		float height = bgimage.getHeight();
		// 創建操作圖片用的matrix對象
		Matrix matrix = new Matrix();
		// 計算寬高縮放率
		float scaleWidth = ((float) newWidth) / width;
		float scaleHeight = ((float) newHeight) / height;
		// 縮放圖片動作
		matrix.postScale(scaleWidth, scaleHeight);
		Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
				(int) height, matrix, true);
		return bitmap;
	}

	/**
	 * 拿到圖片首先進行縮放
	 * 
	 * @param bitmap
	 */
	public void setBitmap(Bitmap bitmap) {
		this.mBitmap = zoomImage(bitmap, 600, 800);
		startX = -(600 / 2);
		startY = -(800 / 2);
		widthX = startX;
		heightY = startY;
		postInvalidate();
	}
做到這一步的時候我們再來看看效果 \

可以看到我們光有了圖片還是遠遠不夠滴,我們還需要一個圓以及一個蒙版效果,那麼問題就來了,這個蒙版效果是怎麼做的呢,再上一張圖,圖片來自網絡 \
看到這張圖我們要知道先繪制的是黃色的後繪制的是藍色的,那麼我們蒙版的效果要用哪種來實現呢。 我選擇用DstOut,這種模式取得是非交集下層部分。理清了思路,接下來我們就繼續寫代碼吧。
private void init() {
		// 創建空白畫布
		bitmap = Bitmap.createBitmap(600, 800, Config.ARGB_8888);
		mCanvas = new Canvas(bitmap);
		paint = new Paint();
		paint.setStyle(Style.FILL);
		paint.setStrokeWidth(2);
		paint.setAntiAlias(true);
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		canvas.translate(getWidth() / 2, getHeight() / 2);
		if (mBitmap != null) {
			restartCanvas();
			canvas.drawBitmap(mBitmap, widthX, heightY, null);
			mCanvas.drawCircle(-widthX, -heightY, 200, paint);
			canvas.drawBitmap(bitmap, widthX, heightY, null);
		}
	}
我們再onDraw中繪制了我們的背景圖片以及蒙版效果再加一個半徑為200的圓,接下來做的就是不斷的改變背景位置來完成移動的效果,每次移動之前要先clear掉上次的畫布。
	private void restartCanvas() {
		// 清空上一次的繪圖狀態
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
		mCanvas.drawPaint(paint);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
		mCanvas.drawColor(getResources().getColor(R.color.bg));
	}
要記清楚DSTOUT的效果哦!
/**
	 * 移動x位置
	 */
	private void getWidthX() {
		widthX = startX - distanceX;
		if (widthX > -200) {
			widthX = -200;
			distanceX = -100;
		} else if (widthX < -400) {
			widthX = -400;
			distanceX = 100;
		}
	}

	/**
	 * 移動y位置
	 */
	private void getHeightY() {
		heightY = startY - distanceY;
		if (heightY > -200) {
			heightY = -200;
			distanceY = -100;
		} else if (heightY < -600) {
			heightY = -600;
			distanceY = 100;
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			x = (int) event.getX();
			y = (int) event.getY();
			break;
		case MotionEvent.ACTION_MOVE:
			distanceX = x - (int) (event.getX());
			distanceY = y - (int) (event.getY());
			getWidthX();
			getHeightY();
			break;
		case MotionEvent.ACTION_UP:
			startX = widthX;
			startY = heightY;
			break;
		default:
			break;
		}
		postInvalidate();
		return true;
	}

今天這部分的代碼就到這裡了,可以看到目前我們還欠缺的是隨手勢放大背景圖片,以及最後的剪切!這就留到下一次吧。。。
項目源碼





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved