利用自定义View实现头像截取页面
来源:互联网 发布:阿里云做socket服务器 编辑:程序博客网 时间:2024/05/01 13:09
在一些应用中,特别是有帐号体系的应用,通过相册选择图片和照相机拍照,然后对所获取的头像进行截取,最后获取选择框中的内容作为头像,一般效果会如下显示:
那么,如何制作这样一个效果呢,关键点在哪里呢?
做法其实可以有多种,
1)可以直接继承ImageView,然后在ImageView的OnDraw函数中直接绘制圆形或者方形的高亮圈;
2)也可以直接继承View,自己将Bitmap给传进来,在onDraw函数中先绘制图片,接着利用Path来绘制这个圆形或者方形的选择区域,利用Region.OP.DIFFERENCE来反向获取蒙板层。
不过利用clipPath来实现这个蒙板层的绘制,画出来的圆形会有锯齿,这个目前我还没有找到比较好的办法去掉这个锯齿,不知道有没有哪位朋友能够提供一下建议。
关键代码如下:
@Override protected void onDraw(Canvas canvas) { if(!mIsInit){ initCropRect(getWidth(), getHeight()); mOptBitmap = getProperBitmap(mBitmap, mCropRect.width()); ... mIsInit = true; } canvas.save(); canvas.concat(mDrawMatrix); canvas.drawBitmap(mOptBitmap, 0, 0, null); canvas.restore(); if(mToDrawHighlight){ canvas.save(); mPath.reset(); if (mIsCircle) { float radius = mCropRect.width() / 2 ; mPath.addCircle(mCropRect.left + radius, mCropRect.top + radius, radius, Path.Direction.CW); } else { mPath.addRect(mCropRect, Path.Direction.CW); } canvas.clipPath(mPath, Region.Op.DIFFERENCE); canvas.drawPaint(mDimPaint); canvas.restore(); } }
大家只关注关键代码即可。
首先,在第一次Ondraw的时候,已经可以获取当前View和bitmap的大小,这个时候,我们要先确定CropRect,也即选择框的大小和范围,不管是圆形,还是方形,其实都是一个正方形区域,所以,首先要确定这个区域,这是在代码initCropRect中实现的。
而紧接着的操作,其实是对图片的一些移动和缩放操作,为了使图片能够居中,或者将比较小的图片放大到选择区域那么大,大家可先暂时忽略。
接下来利用canvas.drawBitmap将对应的位图画出来先。
第二步,我们要先定义一个Path,根据画圆还是画方,在path上添加一个图形,然后利用clipPath和Region.OP.DIFFERENCE来反向获取蒙板区域,然后在Canvas上利用mDimPaint来画蒙板(mDimPaint就是一个颜色为半透明的画笔,这样才不会遮盖掉画在下面的bitmap)。
画出蒙板和选择圈之后,更多时候,我们还需要对图片进行移动和缩放,类似于微信和支付宝那样,那么我们可以利用GestureDetector和ScaleGestureDetector来实现对移动和缩放的控制,如下:
mScaleGestureDetector = new ScaleGestureDetector(context, this);mGestureDetector = new GestureDetector(context, new MyGestureListener());
其中MyGestureListener是我们自定义的一个GestureDetector,因为我们并不需要太多的Gesture,所以我们可以利用SimpleOnGestureListener来实现我们处理,如下:
class MyGestureListener extends SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){ mDrawMatrix.postTranslate(-distanceX, -distanceY); checkBorderWhenTranslate(); return true; } }
其实很简单,在当前View上往某个方向移动的时候,我们是需要将Canvas反方向移动,这样画出来的bitmap才是跟着我们手指移动,所以这里为什么是负数的distance的原因就在这。
这只是针对移动的,还需要缩放的,我们就需要实现一个OnScaleGestureListener,让当前的view去实现此接口即可,如下:
float scaleFactor = detector.getScaleFactor(); float[] values = new float[9]; mDrawMatrix.getValues(values); float curScale = values[Matrix.MSCALE_X]; if ((curScale < SCALE_MAX && scaleFactor > 1.0f) || (curScale > mInitScale && scaleFactor < 1.0f)) { if (scaleFactor * curScale < mInitScale) { scaleFactor = mInitScale / curScale; } if (scaleFactor * curScale > SCALE_MAX) { scaleFactor = SCALE_MAX / curScale; } mDrawMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); checkBorderAndCenterWhenScale(); } return true;
这里边具体的逻辑就依赖于各位朋友自己的想法了,最后不要忘了,从哪里获取到这些移动事件呢,当然是onTouch方法里面,如下:
@Override public boolean onTouch(View v, MotionEvent event) { ... mScaleGestureDetector.onTouchEvent(event); mGestureDetector.onTouchEvent(event); invalidate(); return true; }
好了,关于如何利用自定义View截取头像的大概思路就跟各位朋友说到这了,大家可以自行根据此思路再完善一下。
- 利用自定义View实现头像截取页面
- 自定义VIew,原型头像
- 自定义view圆形头像
- 自定义view之圆形头像(2种实现方式)
- 自定义ImageView实现圆形头像 利用Xferomede实现
- cropper插件实现头像截取
- jq实现截取头像上传
- android圆形头像,自定义view
- Android 自定义View -->圆形头像
- 仿QQ头像自定义截取功能
- Android 利用OnDraw实现自定义View
- 自定义View利用缓冲区实现绘画板功能
- 自定义实现圆头像
- 自定义View之利用组合View实现复用
- 通过ng-Img-Crop实现头像截取
- 利用系统控件集合实现自定义view(自定义菜单)
- Android自定义View之圆形头像
- android自定义圆形头像view,继承imageview
- vc托盘图标的实现以及托盘右键菜单的响应
- 计时器
- stat,fstat以及lstat函数
- 如何实现W5200E01-M3中的UPnP(通用即插即用) 端口转发(三)
- bzoj1014: [JSOI2008]火星人prefix
- 利用自定义View实现头像截取页面
- SQL SERVER数据库判断对象是否存在的方法汇总
- jquery 实现checkbox全选、取消全选功能
- dll和exe的共享节------多进程共享dll/exe全局变量
- scala设计模式
- linux C程序中获取shell脚本输出(如获取system命令输出)
- jdk命令积累
- 自适应网页设计是怎么做到的的相关知识点总结
- Android View的绘制过程