当前位置: 代码迷 >> Android >> Android 仿qq上传头像(1)
  详细解决方案

Android 仿qq上传头像(1)

热度:20   发布时间:2016-04-28 01:34:40.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;	}

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

项目源码





  相关解决方案