码迷,mamicode.com
首页 > 移动开发 > 详细

Android 仿qq上传头像(一)

时间:2015-04-11 14:55:20      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:android   qq上传头像   剪裁头像   

       转载请注明出处http://blog.csdn.net/u014163726/article/details/44994197


       这么长时间没写博客感觉手都要生了啊,最近因为工作的关系来到了上海,目前还算稳定,所以抓紧时间写篇博客压压惊。

     标题早已经看穿一切,这次我们来模仿一下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;
	}

今天这部分的代码就到这里了,可以看到目前我们还欠缺的是随手势放大背景图片,以及最后的剪切!这就留到下一次吧。。。





Android 仿qq上传头像(一)

标签:android   qq上传头像   剪裁头像   

原文地址:http://blog.csdn.net/u014163726/article/details/44994197

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!