Android 修改用户图像笔记
来源:互联网 发布:中宏产业数据库 编辑:程序博客网 时间:2024/06/05 18:57
一:前言
还有两个月就可以回家过年了,项目上最近也不是很忙了,现在做的主要工作就是写一些项目中的js,源生的基本很少了,因为由于项目的需要,需要一些技术上的改变,但是源生还是以后吃饭最主要的技能,为了避免长时间知识的遗忘,和项目开发过程中,领导要求的一个开发效率,这里我就继续做下开发笔记,在任何开发的过程当中,都有用户图像的设置,而且大部分都是以照相机和图库的方式去选择照片。这篇我们就为设置用户的图片做个笔记。
二:需求
- 以圆形显示图片
- 点击图片从底部弹出选择修改图片的来源
- 从手机图库选择图片,然后裁剪
- 照相机捕获图片裁剪
裁剪的效果,是调用系统的裁剪,效果比图感觉要好看好多。
三:设计
- 主布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#346561" > <pushsummary.jzs.com.presonalsetting.CustomImageView android:id="@+id/icon" android:layout_width="100dp" android:layout_height="100dp" android:layout_centerHorizontal="true" android:layout_marginTop="30dp" android:src="@drawable/name" /></RelativeLayout>
主要显示了一个圆形图片
- 自定义圆角图片
package pushsummary.jzs.com.presonalsetting;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.NinePatchDrawable;import android.util.AttributeSet;import android.widget.ImageView;public class CustomImageView extends ImageView { private int mBorderThickness = 0; private Context mContext; private int defaultColor = 0xFFFFFFFF; // 如果只有其中一个有值,则只画一个圆形边框 private int mBorderOutsideColor = 0; private int mBorderInsideColor = 0; // 控件默认长、宽 private int defaultWidth = 0; private int defaultHeight = 0; private boolean isCircle = true; public CustomImageView(Context context) { super(context); mContext = context; } public CustomImageView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setCustomAttributes(attrs); } public CustomImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; setCustomAttributes(attrs); } public void setIsCircle(boolean isCircle) { this.isCircle = isCircle; } private void setCustomAttributes(AttributeSet attrs) { TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview); mBorderThickness = a.getDimensionPixelSize( R.styleable.roundedimageview_border_thickness, 0); mBorderOutsideColor = a .getColor(R.styleable.roundedimageview_border_outside_color, defaultColor); mBorderInsideColor = a.getColor( R.styleable.roundedimageview_border_inside_color, defaultColor); } @Override protected void onDraw(Canvas canvas) { if (!isCircle) { super.onDraw(canvas); } Drawable drawable = getDrawable(); if (drawable == null) { return; } if (getWidth() == 0 || getHeight() == 0) { return; } this.measure(0, 0); if (drawable.getClass() == NinePatchDrawable.class) return; Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Config.ARGB_8888, true); if (defaultWidth == 0) { defaultWidth = getWidth(); } if (defaultHeight == 0) { defaultHeight = getHeight(); } // 保证重新读取 图片后不会因为图片大小而改变控件宽、高的大小(针对宽、高为wrap_content布局的imageview,但会导致margin无效) // if (defaultWidth != 0 && defaultHeight != 0) { // LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( // defaultWidth, defaultHeight); // setLayoutParams(params); // } int radius = 0; if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - 2 * mBorderThickness; // 画内圆 drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); // 画外圆 drawCircleBorder(canvas, radius + mBorderThickness + mBorderThickness / 2, mBorderOutsideColor); } else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) {// 定义画一个边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); } else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) {// 定义画一个边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderOutsideColor); } else {// 没有边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2; } Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius); canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null); } /** * 获取裁剪后的圆形图片 * * @param radius 半径 */ public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) { Bitmap scaledSrcBmp; int diameter = radius * 2; // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片 int bmpWidth = bmp.getWidth(); int bmpHeight = bmp.getHeight(); int squareWidth = 0, squareHeight = 0; int x = 0, y = 0; Bitmap squareBitmap; if (bmpHeight > bmpWidth) {// 高大于宽 squareWidth = squareHeight = bmpWidth; x = 0; y = (bmpHeight - bmpWidth) / 2; // 截取正方形图片 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else if (bmpHeight < bmpWidth) {// 宽大于高 squareWidth = squareHeight = bmpHeight; x = (bmpWidth - bmpHeight) / 2; y = 0; squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else { squareBitmap = bmp; } if (squareBitmap.getWidth() != diameter || squareBitmap.getHeight() != diameter) { scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, true); } else { scaledSrcBmp = squareBitmap; } Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); Paint paint = new Paint(); Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight()); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); canvas.drawARGB(0, 0, 0, 0); canvas.drawCircle(scaledSrcBmp.getWidth() / 2, scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(scaledSrcBmp, rect, rect, paint); // bitmap回收(recycle导致在布局文件XML看不到效果) // bmp.recycle(); // squareBitmap.recycle(); // scaledSrcBmp.recycle(); bmp = null; squareBitmap = null; scaledSrcBmp = null; return output; } /** * 边缘画圆 */ private void drawCircleBorder(Canvas canvas, int radius, int color) { Paint paint = new Paint(); /* 去锯齿 */ paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(color); /* 设置paint的 style 为STROKE:空心 */ paint.setStyle(Paint.Style.STROKE); /* 设置paint的外框宽度 */ paint.setStrokeWidth(mBorderThickness); canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint); }}
以上主要是自定义圆角图片功能,这里暂时不做详细讲解,等有时间,我再专门做个笔记。
- PopupWindow的设计显示
private void ShowPopuWindow() { if (popupWindow == null) { View view = View.inflate(MainActivity.this, R.layout.popwindow_get_img, null); popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); //设置属性 popupWindow.setTouchable(true); popupWindow.setOutsideTouchable(true); popupWindow.setBackgroundDrawable(new BitmapDrawable()); popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); //设置点击事件 cancelBtn = (Button) view.findViewById(R.id.btn_cancel); cancelBtn.setOnClickListener(this); photoBtn = (Button) view.findViewById(R.id.btn_photo); photoBtn.setOnClickListener(this); pictureBtn = (Button) view.findViewById(R.id.btn_picture); pictureBtn.setOnClickListener(this); } //在固定位置显示窗口 View root = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0); if (root != null) { popupWindow.showAtLocation(root, Gravity.BOTTOM, 0, 0); } setActivityTransparent(0.5f); //监听popuwinds消失 popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { setActivityTransparent(1f); } }); }
- 在弹出popu的时候显示一层遮罩
private void setActivityTransparent(float transparent) { WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); layoutParams.alpha = transparent; layoutParams.dimAmount = 1 - transparent; getWindow().setAttributes(layoutParams); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); }
在调用系统的popu时候,不会有层遮罩的效果,利用设置窗口的透明度度来实现是,遮罩的效果。
- 调用系统相册选中图片后,并且把图片给携带回来,就好比你女朋友说,出去挣钱,你出去一圈,不把钱给带回来,能让你好过?这里使用 startActivityForResult();这个方法去启动activity
/** * 从相册取图片 */ public void doPickPhotoFromGallery() { Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED); startActivityForResult(intent, PHOTOZOOM); }
- 调用系统相机,和相册同理。
protected void doTakePhoto() { if (!DeviceTool.hasSDCard()) { showToast("sd卡不存在,暂时无法拍照", Toast.LENGTH_SHORT); return; } File imgPath = MainActivity.this.getExternalFilesDir(null); try { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = new File(imgPath.toString() + "/" + photoCacheFile); Uri uri = Uri.fromFile(file); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, PHOTOHRAPH); } catch (Exception e) { } }
这里调用系统照相的时候,将照片存放发data/data/xxxx
- 获取到照片进行操作
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case PHOTOHRAPH: if (resultCode != Activity.RESULT_OK) { super.onActivityResult(requestCode, resultCode, data); return; } // 设置文件保存路径这里放在跟目录下 try { File imgPath = MainActivity.this.getExternalFilesDir(null); if (TextUtils.isEmpty(imgPath.toString())) { showToast("抱歉,照片存储失败", 0); return; } File picture = new File(imgPath.toString() + "/" + photoCacheFile); Uri uri = Uri.fromFile(picture); startPhotoZoom(uri); } catch (Exception e) { } break; case PHOTOZOOM: if (data == null) { super.onActivityResult(requestCode, resultCode, data); return; } startPhotoZoom(data.getData()); break; case PHOTORESOULT: if (data == null) { super.onActivityResult(requestCode, resultCode, data); return; } Bundle extras = data.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); if (photo == null) { super.onActivityResult(requestCode, resultCode, data); return; } else { ByteArrayOutputStream stream = new ByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.JPEG, 75, stream); } icon.setImageBitmap(photo); String imgFile = null;// 上传图片 try { imgFile = ImageTools.saveFile(photo, "g" + System.currentTimeMillis(), MainActivity.this.getExternalFilesDir(null).toString()); } catch (IOException e) { e.printStackTrace(); } if (imgFile != null) { //上传到服务器 } } break; } super.onActivityResult(requestCode, resultCode, data); }
重写系统的onActivityResult方法,根据请求码或这返回码都能进行相关的处理。
- 调用系统api进行图片的裁剪。
public void startPhotoZoom(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, IMAGE_UNSPECIFIED); intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // outputX outputY 是裁剪图片宽高 intent.putExtra("outputX", 200); intent.putExtra("outputY", 200); intent.putExtra("return-data", true); startActivityForResult(intent, PHOTORESOULT); }
这些真没必要记清楚。主要用的时候,可以用就行,如果没事也可以研究一下。
项目的源码地址:https://github.com/sdsjk/PresonalSeting
知识点
以上内容就是,实修改用户图片的所有代码。虽然看这功能简单,但是实际上,代码和知识点真不少,领导那里知道,代码多少,在他眼里,或许这很简单,哈哈,所以我们也要做好笔记,用的时候,直接copy。
圆形图片控件
在android的开发中,系统并没有给我们提供这样的控件,然而我们对于系统没有提供的,我们只能通过自定义View去实现,对与自定义圆形控件可以参考:http://blog.csdn.net/lmj623565791/article/details/24555655底部的popuWindow显示
点击图片显示选择框,这里我选择的是popu来实现这个功能。
popu的参考文档:http://blog.csdn.net/harvic880925/article/details/49272285调用系统相册
调用系统相册,是通过隐士意图的方法去调用系统相册,在选中系统图片的时候,携带数据返回给调用者。
参考文章:http://blog.csdn.net/w18756901575/article/details/52085157调用照相机功能
参考文章:http://blog.csdn.net/bill_ming/article/details/7730305
这是涉及到的知识点,在我们没事的时候也可以去看看,也有助于提高自己。如果对你有帮助了,点个赞呗^_^
- Android 修改用户图像笔记
- android开机图像的修改
- Android开发学习笔记之通过反射技术修改listview的快速滑块图像
- Android 利用JSON异步修改用户个人资料
- OpenCV学习笔记(六):使用查找表修改图像外观
- opencv学习笔记之读取,修改,保存图像
- Android修改ramdisk.img笔记
- android--笔记--修改CheckBox样式
- Android桌面Launcher2修改笔记
- 修改用户
- Android 用户圆形图像的设置与上传
- android学习笔记之图像像素操作
- 购物网第二阶段总结笔记5:用户个人资料修改页面、密码修改页面、用户积分页面、用户统计信息页面
- Oracle学习笔记 之 授权与修改用户状态
- mybatis学习笔记-实现添加修改删除用户功能
- ORacle学习笔记(四) 用户解锁,修改密码
- Android Service学习笔记--用户通知
- Android黑科技,读取用户短信+修改系统短信数据库
- javascript中apply、call和bind的区别
- LoadLibrary无法加载DLL解决思路
- 斐波那契数列的递归实现和非递归实现
- 108. Convert Sorted Array to Binary Search Tree
- 链表的操作
- Android 修改用户图像笔记
- 重载_,“+, -, --, ++”运算符
- 模式识别四--最大似然估计与贝叶斯估计方法
- 关于3D-HEVC中的SDC编码方式
- Spring mvc4 + ActiveMQ 整合
- Spark MLlib聚类clustering:KMeans K均值 ---原理及实战
- 伯乐在线
- 信息隐藏课程之索引图像的隐写
- 确定字符互异