个人资料上传头像模块,拍照+图库+图片剪裁+圆形头像

2024-01-04 09:59

本文主要是介绍个人资料上传头像模块,拍照+图库+图片剪裁+圆形头像,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先看效果图:

注意: 因为模拟器的原因裁剪图片的页面只能拖拽,实际在手机上是可以放大旋转等操作的

实现思路:

1.三个自定义的view,分别是圆形的Imageview,可拖拽放大旋转的Imageview,裁剪图片的view(裁剪页面的矩形)

2.点击主界面的上传头像,开启一个透明的透明的Activity,在这个Activity中可以选择拍照或者是图库,不管选择哪种,将返回结果的图片路径传递到裁剪页面

3.裁剪页面:先将图片根据屏幕的比例等比例缩小加载成bitmap对象,设置给可拖拽放大旋转的Imageview,这个时候我们就可以对图片进行拖动放大等,最后我们将图片传递到MainActivity设置为头像,并上传至服务器

具体步骤:

1.先在MainActivity中,我们需要做三件事:点击后开启透明的选择获取图片方式的页面,注册广播接受者来接受最终处理好的图片,上传图片

                @Overridepublic void onReceive(Context context, Intent intent) {if ("account_active".equals(intent.getAction())) {byte[] bis = intent.getByteArrayExtra("bitmap");Bitmap bitmap = BitmapFactory.decodeByteArray(bis, 0,bis.length);// 将图片数组转换成图片iv_head_img.setImageBitmap(bitmap);//这个Imageview是圆形的Imageview// 在这里上传图片 上传的格式看你们公司的要求了// 如果要转换成数组上传就使用BitmapFactory将bitmap对象转换成数组再传// if(bitmap != null){// uploadImage(bitmap, BaseApplication.userBean.getUsername());// }else{// CustomToast.createToast().showFaild(AccountUpdateActivity.this,// "图片文件错误");// }}} 
注意:上传图片我们这边是将图片转换成base64位,进行上传的,注意用post请求

2.选择图片页面,我们需要做的是:选择图片的方式拍照或者是图库,获取到的图片进行判断,将图片的位置传递给裁剪页面

       第1种    选择拍照:

               // 执行拍照前,应该先判断SD卡是否存在String SDState = Environment.getExternalStorageState();if (SDState.equals(Environment.MEDIA_MOUNTED)) {// 如果内存卡已经挂载Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "camera.jpg")));intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);startActivityForResult(intent, SELECT_PIC_BY_TAKE_PHOTO);} else {Toast.makeText(this, "内存卡不存在", Toast.LENGTH_SHORT).show();} 
             返回结果后将图片路径传递给剪裁界面:

                                try {Intent intent = new Intent(this, ClipPictureActivity.class);// 开启裁剪的界面intent.putExtra("picPath", "/sdcard/camera.jpg");intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);finish();} catch (Exception e) {e.printStackTrace();} 
        第2种     从图库获取图片路径

               // 选择照片的时候也一样,我们用Action为Intent.ACTION_GET_CONTENT,// 有些人使用其他的Action但我发现在有些机子中会出问题,所以优先选择这个Intent intent = new Intent();intent.setType("image/*");intent.setAction(Intent.ACTION_GET_CONTENT);startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);

           返回结果时,进行非空格式的判断等,并将图片路径传递给剪裁界面:
               	if (requestCode == SELECT_PIC_BY_PICK_PHOTO) {// 从相册取图片,有些手机有异常情况,请注意if (data == null) {Toast.makeText(this, "选择图片文件出错", Toast.LENGTH_LONG).show();return;}photoUri = data.getData();if (photoUri == null) {Toast.makeText(this, "选择图片文件出错", Toast.LENGTH_LONG).show();return;}}String[] pojo = { MediaStore.Images.Media.DATA };@SuppressWarnings("deprecation")Cursor cursor = managedQuery(photoUri, pojo, null, null, null);if (cursor != null) {int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);cursor.moveToFirst();picPath = cursor.getString(columnIndex);cursor.close();}if (picPath != null&& (picPath.endsWith(".png") || picPath.endsWith(".PNG")|| picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) {Intent intent = new Intent(this, ClipPictureActivity.class);intent.putExtra("picPath", picPath);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);finish();} else {Toast.makeText(this, "选择图片文件不正确", Toast.LENGTH_SHORT).show();}
3.裁剪界面:为TouchImageview添加触摸事件的监听和添加全局view树的观察者,将裁剪的view添加进去,在触摸事件中对图片操作,保存图片并发广播通知MainActivity

   第一步     添加全局view树的观察者,将裁剪的view添加进去.可是为什么不直接将裁剪的view放在布局文件中?因为这个裁剪的view的大小是不确定的,我们需要根据图片的大小来设置剪裁view的大小!

    那为什么不在直接在onCreate中添加,而要在TouchImageview的全局view树的观察者中添加呢?因为在系统再调用onCreate方法时,并没有把布局文件中的每个view画出来,

                只是知道布局中有这么个东西,不信你可以试试,在onCreate方法中获取任何一个空间的宽和高试试,会是0.而我们在viewTree的观察者中的onGlobalLayout是在控件已经

                 全部画上去之后才调用,这个时候我们自然也会能获得每个空间的真实大小,而不是0

     

             ViewTreeObserver observer = srcPic.getViewTreeObserver();observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@SuppressWarnings("deprecation")public void onGlobalLayout() {srcPic.getViewTreeObserver().removeGlobalOnLayoutListener(this);initClipView(srcPic.getTop());//添加裁剪的view}});

第二步  添加裁剪的view,并将图片按屏幕的比例显示出来           
        /*** 初始化截图区域,并将源图按裁剪框比例缩放* * @param top*/private void initClipView(int top) {bitmap = getBitmapByPath(url);//将原图压缩到原来的1/2clipview = new ClipView(ClipPictureActivity.this);clipview.setCustomTopBarHeight(top);clipview.addOnDrawCompleteListener(new OnDrawListenerComplete() {public void onDrawCompelete() {clipview.removeOnDrawCompleteListener();int clipHeight = clipview.getClipHeight();int clipWidth = clipview.getClipWidth();int midX = clipview.getClipLeftMargin() + (clipWidth / 2);int midY = clipview.getClipTopMargin() + (clipHeight / 2);int imageWidth = bitmap.getWidth();int imageHeight = bitmap.getHeight();// 按裁剪框求缩放比例float scale = (clipWidth * 1.0f) / imageWidth;if (imageWidth > imageHeight) {scale = (clipHeight * 1.0f) / imageHeight;}// 起始中心点float imageMidX = imageWidth * scale / 2;float imageMidY = clipview.getCustomTopBarHeight()+ imageHeight * scale / 2;srcPic.setScaleType(ScaleType.MATRIX);// 缩放matrix.postScale(scale, scale);// 平移matrix.postTranslate(midX - imageMidX, midY - imageMidY);srcPic.setImageMatrix(matrix);srcPic.setImageBitmap(bitmap);}});this.addContentView(clipview, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));} 
第三步  触摸事件 

     第一个手指按下默认是拖拽   第二个手机按下根据两个手指间的距离  如果大于10个像素  就认为是缩放  根据手机移动的距离将图片移动和缩放

    手指离开屏幕清除模式

  

        public boolean onTouch(View v, MotionEvent event) {ImageView view = (ImageView) v;switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:savedMatrix.set(matrix);// 设置开始点位置start.set(event.getX(), event.getY());mode = DRAG;break;case MotionEvent.ACTION_POINTER_DOWN://第二个手指按下oldDist = spacing(event);if (oldDist > 10f) {//缩放savedMatrix.set(matrix);midPoint(mid, event);mode = ZOOM;}break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_POINTER_UP:mode = NONE;break;case MotionEvent.ACTION_MOVE:if (mode == DRAG) {matrix.set(savedMatrix);matrix.postTranslate(event.getX() - start.x, event.getY()- start.y);} else if (mode == ZOOM) {float newDist = spacing(event);if (newDist > 10f) {matrix.set(savedMatrix);float scale = newDist / oldDist;matrix.postScale(scale, scale, mid.x, mid.y);//根据mid进行缩放}}break;}view.setImageMatrix(matrix);return true;}/*** 多点触控时,计算最先放下的两指距离* * @param event* @return*/private float spacing(MotionEvent event) {float x = event.getX(0) - event.getX(1);float y = event.getY(0) - event.getY(1);return (float) Math.sqrt(x * x + y * y);}/*** 多点触控时,计算最先放下的两指中心坐标* * @param point* @param event*/private void midPoint(PointF point, MotionEvent event) {float x = event.getX(0) + event.getX(1);float y = event.getY(0) + event.getY(1);point.set(x / 2, y / 2);}
第四步  保存图片并将图片传递到MainActivity中
     
 	private void save() {Bitmap clipBitmap = getBitmap();ByteArrayOutputStream baos = new ByteArrayOutputStream();clipBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//将图片转换成数组byte[] bitmapByte = baos.toByteArray();Intent intent = new Intent("account_active");//发广播   将图片的数组传过去intent.putExtra("bitmap", bitmapByte);sendBroadcast(intent);finish();}/*** 获取裁剪框内截图* * @return*/private Bitmap getBitmap() {// 获取截屏View view = this.getWindow().getDecorView();view.setDrawingCacheEnabled(true);view.buildDrawingCache();// 获取状态栏高度Rect frame = new Rect();this.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);int statusBarHeight = frame.top;Bitmap finalBitmap = Bitmap.createBitmap(view.getDrawingCache(),clipview.getClipLeftMargin(), clipview.getClipTopMargin()+ statusBarHeight, clipview.getClipWidth(),clipview.getClipHeight());// 释放资源view.destroyDrawingCache();return finalBitmap;} 

最后,点击这里获取源码









这篇关于个人资料上传头像模块,拍照+图库+图片剪裁+圆形头像的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/Jeff169/article/details/51619887
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/568959

相关文章

使用Python实现base64字符串与图片互转的详细步骤

《使用Python实现base64字符串与图片互转的详细步骤》要将一个Base64编码的字符串转换为图片文件并保存下来,可以使用Python的base64模块来实现,这一过程包括解码Base64字符串... 目录1. 图片编码为 Base64 字符串2. Base64 字符串解码为图片文件3. 示例使用注意

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函

GitLab文件的上传与下载方式

《GitLab文件的上传与下载方式》:本文主要介绍GitLab文件的上传与下载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录GitLab 项目拉取到本地GitLab 项目上传方法方法 1:本地项目未初始化Git方法 2:本地项目已初始化GitGitLab 上

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现

Nginx 413修改上传文件大小限制的方法详解

《Nginx413修改上传文件大小限制的方法详解》在使用Nginx作为Web服务器时,有时会遇到客户端尝试上传大文件时返回​​413RequestEntityTooLarge​​... 目录1. 理解 ​​413 Request Entity Too Large​​ 错误2. 修改 Nginx 配置2.1

Java应用如何防止恶意文件上传

《Java应用如何防止恶意文件上传》恶意文件上传可能导致服务器被入侵,数据泄露甚至服务瘫痪,因此我们必须采取全面且有效的防范措施来保护Java应用的安全,下面我们就来看看具体的实现方法吧... 目录恶意文件上传的潜在风险常见的恶意文件上传手段防范恶意文件上传的关键策略严格验证文件类型检查文件内容控制文件存储

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

Java如何根据文件名前缀自动分组图片文件

《Java如何根据文件名前缀自动分组图片文件》一大堆文件(比如图片)堆在一个目录下,它们的命名规则遵循一定的格式,混在一起很难管理,所以本文小编就和大家介绍一下如何使用Java根据文件名前缀自动分组图... 目录需求背景分析思路实现代码输出结果知识扩展需求一大堆文件(比如图片)堆在一个目录下,它们的命名规

Java实现MinIO文件上传的加解密操作

《Java实现MinIO文件上传的加解密操作》在云存储场景中,数据安全是核心需求之一,MinIO作为高性能对象存储服务,支持通过客户端加密(CSE)在数据上传前完成加密,下面我们来看看如何通过Java... 目录一、背景与需求二、技术选型与原理1. 加密方案对比2. 核心算法选择三、完整代码实现1. 加密上