android 模仿qq 上传头像,Android 仿qq上传头像(一)

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

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

标题早已经看穿一切,这次我们来模仿一下qq上传头像的功能,先上一个未完成版的效果图,银魂第四季重开放上一张萌萌哒的图片。

0818b9ca8b590ca3270a3433284dd417.png

这还是要用到我们自定义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();

}做到这一步的时候我们再来看看效果

0818b9ca8b590ca3270a3433284dd417.png

可以看到我们光有了图片还是远远不够滴,我们还需要一个圆以及一个蒙版效果,那么问题就来了,这个蒙版效果是怎么做的呢,再上一张图,图片来自网络

0818b9ca8b590ca3270a3433284dd417.png

看到这张图我们要知道先绘制的是黄色的后绘制的是蓝色的,那么我们蒙版的效果要用哪种来实现呢。

我选择用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;

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值