最近,小灵狐得知了一种能够加快修炼速度的绝世秘法,那便是修炼android神功。小灵狐打算用android神功做一个app,今天他的修炼内容就是头像功能。可是小灵狐是个android小白啊,所以修炼过程也是困难重重。下面我们来看看他的修炼过程吧。

控件

小灵狐想要能够拥有头像,那么首先就要有显示头像的地方,也就是控件。首先可以采用ImageView来,但是小灵狐不喜欢用ImageView来,他选择了另一种控件——CircleImageView。这是一种能够将图片圆形化的控件,用法和ImageView是完全一样的,就是会自动把头像转化成圆形的。要使用这个控件,首先要引入第三方库de.hdodenhof:circleimageview:2.2.0,剩下的就和ImageView一样了。比如他在布局中加入了如下的样式:

<de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/civ_my_avatar"            // 控件id,唯一表示控件android:layout_width="100dp"              // 设置宽为100dpandroid:layout_height="100dp"             // 设置高为100dpandroid:layout_gravity="center"           // 设置在布局中的显示位置为中间/>

之后小灵狐发现这样子如果没有图片的话,就看不见这个控件,他就想要在控件外围显示一个圈,在这样就算没有头像,那么这个圈也会显示出来,让人一看就知道这里是要显示头像的。于是,他就在上面的代码中加入了以下的设置

app:civ_border_width="1dp"            // 设置边框宽度,默认为0,这样就看不到那个圈了
app:civ_border_overlay="true"         // 设置边框是否覆盖在图片上,默认为false
app:civ_border_color="@color/silver"  // 设置边框的颜色,默认为黑色,这里用了一种自定义的颜色——银色
app:civ_fill_color="@color/whiteSmoke"// 设置填充底色,默认为透明,这里用了自定义的颜色——白烟色

加上了上面的设置,便可以显示出一个头像的圈圈了。这样,基本的东西就准备好了,但是还是没有图片。如果想要显示某张图片(假设图片为drawable文件夹下的一张名为“fox”的图片),只要再加上下面的设置就好了。

android:src="@drawable/fox"

如果想要了解更多的关于CircleImageView的内容,可以参考
CircleImageView的项目源码链接的项目源码链接

修改头像

现在已经能够成功显示出头像了,但是小灵狐喜欢用头像来表达自己的心情,所以他经常会换头像,这可怎么办呢?不急,在更换头像之前,我们需要能够选择一张用来替换的图片。小灵狐想要点击头像就可以选择系统相册里面的图片并把它设为头像。我们一步步来。

设置头像框监听事件

我们给头像框设置一个监听事件,使得点击它后会调用系统相册。这就要先给头像框设置监听事件了。给控件设置监听事件只要两步就好啦,首先创建一个对应控件类型的对象,并通过findViewById(int id)函数找到控件id将对象与空间进行绑定。然后就可以通过对象来调用setOnClickListener()函数,从而达到监听的效果,代码如下:

// 根据上面指定的控件id创建CircleImageView控件对象
CircleImageView circleImageView = (CircleImageView) findViewById(R.id.civ_my_avatar);
// 调用监听函数
circleImageView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 相关操作}
});

调用系统相册

设置好监听事件后,就可以在“相关操作”的地方添加响应事件,这里我们需要的是能够调用系统相册。但是小灵狐发现要调用系统相册,需要先申请SD卡读写权限。申请读写权限主要分为两个步骤:一是在注册文件(AndroidManifest.xml)里声明所需权限,这里需要的是SD卡读写权限,所以应该添加如下声明:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

WRITE_EXTERNAL_STORAGE权限是同时授予对SD卡读和写的能力。二是在Activity中查看权限,如果没有授予,需要动态申请,代码如下:

if (ContextCompat.checkSelfPermission(InfoSettingActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) !=PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(InfoSettingActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);} else {// 调用系统相册}

对于上面的代码,小灵狐给出了解释:ContexCompat.checkSelfPermission()函数用来查看权限,该函数的第一个参数是一个上下文context,第二个参数就是刚才我们在注册文件中声明的权限,若该函数返回的值等于PackageManager.PERMISSION_GRANTED,说明用户已经授权,我们可以直接进行后续操作。如果不是,就需要动态申请权限,ActivityCompat.requestPermissions()函数用来动态申请权限,并且需要重写onRequestPermissionsResult()函数,重写代码如下:

@Override// 申请用户权限public void onRequestPermissionsResult(int requestCode, String[] permissions,int[] grantResults) {switch (requestCode) {case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 用户允许授权/* ————调用系统相册————*/} else {// 用户拒绝授权Toast.makeText(this, "You denied the permission",Toast.LENGTH_SHORT).show();}break;default:}}

动态申请权限的时候会弹出一个权限申请框,询问是否授权,对于这样的弹框,用过安卓手机的人应该都不陌生吧。这时候如果用户点击允许,那么便成功获得对SD卡的读写权限,可以开开心心的进行后续操作了,如果被用户拒绝,那么就不能成功的执行后续操作了。

做了这一切,还是没有说怎么调用系统相册,不急,我们继续看看小灵狐是怎么做的吧。其实调用系统相册很简单,只有三句代码,我们把它们用函数openAlbum()进行封装,这样只要把上面出现“调用系统相册”的注释全部改为openAlbum(),就可以成功的执行调用系统相册的操作了。

 private void openAlbum() {// 使用Intent来跳转Intent intent = new Intent("android.intent.action.GET_CONTENT");// setType是设置类型,只要系统中满足该类型的应用都会被调用,这里需要的是图片intent.setType("image/*");// 打开满足条件的程序,CHOOSE_PHOTO是一个常量,用于后续进行判断,下面会说startActivityForResult(intent, CHOOSE_PHOTO);}

选择图片

我们知道开启一个活动直接用startActivity()就可以,但上面使用startActivityForResult()来开启活动而不直接用startActivity(),这是为什么呢?注意到多了'forResult',顾名思义,不难想象出原因。是因为我们不仅仅是要打开系统相册,更重要的是能够在系统相册中选择一张图片并且返回图片的url,所以要'forResult'。为了这个'result',我们需要重写onActivityResult()方法:

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {// 上面的CHOOSE_PHOTO就是在这里用于判断case CHOOSE_PHOTO:// 判断手机系统版本号if (resultCode == RESULT_OK) {if (Build.VERSION.SDK_INT >= 19) {// 手机系统在4.4及以上的才能使用这个方法处理图片handleImageOnKitKat(data);} else {// 手机系统在4.4以下的使用这个方法处理图片handleImageBeforeKitKat(data);}}break;default:break;}}

上面的代码还是很好理解的,但是可能会感到奇怪,为什么要判断Build.VERSION.SDK_INT的值呢?自习观察两个函数的命名,差了一个before,所以大概能猜出点什么了吧。没错,这两个函数都是用来处理图片的,那他们的区别是什么呢?Android系统从4.4版本开始,选取相册中的图片不再返回图片真实的Uri了,而是一个分装过的Uri,因此如果是4.4版本以上的系统要对这个Uri进行解析才行。handleImageOnKitKat()函数包含了对Uri的解析,4.4版本以后的就要用这个函数,而4.4版本之前的就要用handleImageBeforeKitKat()函数了,现在明白了before是指什么了吧。因为要区分手机系统版本,所以我们加了对Build.VERSION.SDK_INT的判断。好了,现在我们明白了要用到这两个函数来处理图片,可是这两个函数到底是什么啊,我们继续往下看。

@TargetApi(19)private void handleImageOnKitKat(Intent data) {Uri uri = data.getData();String imagePath = null;// 如果是document类型的Uri,,则通过document id处理if (DocumentsContract.isDocumentUri(this, uri)) {String docId = DocumentsContract.getDocumentId(uri);if ("com.android.providers.media.documents".equals(uri.getAuthority())) {// 解析出数字格式的idString id = docId.split(":")[1];String selection = MediaStore.Images.Media._ID + "=" + id;imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);}else if("com.android.providers.downloads.documents".equals(uri.getAuthority())){Uri contentUri = ContentUris.withAppendedId(Uri.parse("content:" +"//downloads/public_downloads"), Long.valueOf(docId));imagePath = getImagePath(contentUri, null);}} else if ("file".equalsIgnoreCase(uri.getScheme())) {// 如果是file类型的Uri,直接获取图片路径imagePath = uri.getPath();} else if ("content".equalsIgnoreCase(uri.getScheme())) {// 如果是content类型的Uri,使用普通方式处理imagePath = getImagePath(uri, null);}// 根据得到的图片路径显示图片}private void handleImageBeforeKitKat(Intent data) {Uri uri = data.getData();String imagePath = getImagePath(uri, null);// 根据得到的图片路径显示图片}

从上面的代码我们也可以看出这两个函数的差别。

显示图片

现在我们就差最后一步了,就是把图片显示出来。安卓中常用的显示图片的函数有两个setImageResource()setImageBitmap() ,前者的参数只能是 int id ,也就是说它只能显示在drawable文件夹下的图片,但是我们要从相册里面获得,显然要用后者,我们可以把显示图片的过程分装成一个函数:

private void displayImage(String imagePath){if(imagePath!=null){Bitmap bitmap= BitmapFactory.decodeFile(imagePath);circleImageView.setImageBitmap(bitmap);}else{Toast.makeText(this,"failed to get image",Toast.LENGTH_SHORT).show();}}

做到这里,我们就完成了用户头像的功能啦。小灵狐迫不及待的从相册中随便找了一张表情包试用,成功的把表情包显示在了头像框内。但是,事情真的就这么简单吗?太天真了。

图片压缩

小灵狐实现了用户头像,非常开心。赶紧拿出手机,拍了一张高清图片,准备作为自己的头像。但是,当他选择该图片之后,却惊讶的发现竟然没有显示出来,而且程序还会崩溃,这可把小灵狐急坏了。经过研究学习,他发现,原来是图片太大了,直接加载进去,会导致内存泄漏,从而使得图片无法正常显示,甚至是程序奔溃。所以在显示图片之前,要经过一定的压缩,然后再加载进去。Bitmap压缩都是围绕这个来做文章:Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数。3个参数,任意减少一个的值,就达到了压缩的效果。所以,根据这个,小灵狐修改了displayImage() 函数,采用了如下的压缩方式:

//显示图片private void displayImage(String imagePath){if(imagePath!=null){BitmapFactory.Options options = new BitmapFactory.Options();// 解析位图的附加条件options.inJustDecodeBounds = true;    // 不去解析位图,只获取位图头文件信息Bitmap bitmap= BitmapFactory.decodeFile(imagePath,options);circleImageView.setImageBitmap(bitmap);int btwidth = options.outWidth;     // 获取图片的宽度int btheight = options.outHeight;   //获取图片的高度int dx = btwidth/100;    // 获取水平方向的缩放比例int dy = btheight/100;    // 获取垂直方向的缩放比例int sampleSize = 1; // 设置默认缩放比例// 如果是水平方向if (dx>dy&&dy>1) {sampleSize = dx;}//如果是垂直方向if (dy>dx&&dx>1) {sampleSize = dy;}options.inSampleSize = sampleSize;       // 设置图片缩放比例options.inJustDecodeBounds = false;     // 真正解析位图// 把图片的解析条件options在创建的时候带上bitmap = BitmapFactory.decodeFile(imagePath, options);circleImageView.setImageBitmap(bitmap); // 设置图片}else{Toast.makeText(this,"failed to get image",Toast.LENGTH_SHORT).show();}}

关于图片压缩的方式网上有很多种方式方法,其实内容和原理都是大同小异,如果想要了解更多的方法,这里有几个参考链接可以看一看:

bitmap的六种压缩方式,Android图片压缩

Android应用开发中三种常见的图片压缩方法

Android图片压缩(质量压缩和尺寸压缩)&Bitmap转成字符串上传

黑科技

小灵狐学习了图片的压缩,也自己写了一种压缩方式,但是他发现到底要把图片压缩到什么程度很难把握,而且不同的屏幕,不同的手机效果也不同。有没有其他的方法来加载图片,能够有效的避免因图片太大而导致内存泄漏的问题呢?经过不断地探索发现,小灵狐发现了一个很好用的加载图片方式——glide。这是一种神奇的黑科技,关于它的使用方法,可以参考以下博客,讲的非常清楚,非常好,我就不再啰嗦啦。

Glide的基本用法

从源码的角度理解Glide的执行流程

总结

到此,用户头像功能算是全部实现了。小灵狐从零开始,一步步摸索出来,经历了很多的困难,当然也学到了很多。现在,小灵狐终于可以把自己的高清图片作为自己的头像啦。这部分的修炼暂告一段落,敬请期待以后的修炼。

转载于:https://www.cnblogs.com/jiuweilinghu/p/7845320.html

android开发——用户头像相关推荐

  1. 分分钟带你搞定Android开发圆形头像

    转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50573326 分分钟带你搞定Android开发圆形头像 目前在应用开发中,矩形的头像基 ...

  2. Android 更换用户头像(拍照、相册选取)

    Android 更换头像 前言 正文 一.新建项目 二.配置项目 三.布局.样式改动 四.权限请求 五.底部弹窗显示 六.工具类 七.打开相机.相册 八.页面返回显示图片 九.本地缓存 十.后台获取 ...

  3. Android开发——用户在屏幕上的手势识别

    0. 前言   转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52462493 Android开发中,我们常常需要获取用户的手势操作事 ...

  4. android 制作用户头像,Android实现带头像的用户注册页面

    1.首先是注册页面的布局: android:layout_width="fill_parent" android:layout_height="fill_parent&q ...

  5. Android开发--用户定位服务--UserLocation

    用户定位介绍: User Location的作用: 1.获取用户的位置 2.追踪用户的移动 User Location的关键API 1.Location Manager:用于管理Android的用户定 ...

  6. android开发实现头像上传功能

    刚进公司领导要求做个app头像上传功能,要求从相册或者相机拍照上传头像.网上参考了一些demo,整理了一下. 效果如图:         流程其实挺简单:对按钮进行监听,点击后弹出AlertDialo ...

  7. android 制作用户头像,android 切换头像功能实现

    接到一个新需求,用户可以自己跟换自己的头像 1.可以使用相机或是选择照片 2.剪切头像 3.保存头像到本地 实现步骤: 1.我们首先提供用户选择是相机还是相册: 使用alterDialog让用户选择, ...

  8. Android更换用户头像实现

    使用 BitmapFactory.Options options2 = new BitmapFactory.Options();options2.inPreferredConfig = Bitmap. ...

  9. Android开发之用户头像上传

    一,概述 本篇博客总结一下自己在开发过程中应用到的一些知识,在本篇博客中带领大家完成用户头像选择或者拍照上传,并对图片进行大小的压缩,和形状的控制,可以将用户选择到的图片裁剪成圆形上传. ok,我们开 ...

最新文章

  1. 【iOS官方文档翻译】UICollectionView与UICollectionViewFlowLayout
  2. HDU-4483 Lattice triangle 数论
  3. Nginx+lua 实现调用.so文件方法
  4. python中keyboardinterrupt_如何防止代码块在Python中被KeyboardInterrupt中断?
  5. ImportError: No module named 'keras.utils.visualize_util'
  6. 爬虫之数据解析的三种方式
  7. c++ primer 6.5.1节练习答案
  8. 可视化卷积神经网络的过滤器
  9. 三、Oracle学习笔记:DDL数据定义语句
  10. C盘空间丢失30G,怎么也找不到
  11. 服务器显示器分辨率,屏幕分辨率修改
  12. c语言 sd卡编程,嵌入式系统基础 嵌入式系统中的C语言编程基础 烧写Superboot到SD卡.docx...
  13. 利用格拉布斯准则,剔除异常数据
  14. js播放Amr音频_Mp3转Amr
  15. 服务器虚拟化有什么好处
  16. arp-scan使用
  17. [转帖]谨防(练拳时)膝关节损伤十一要
  18. 任正非评华为HR胡玲事件,元芳你怎么看?
  19. 银行排队系统的设计与实现(源代码)
  20. java日期格式化为json字符串,看这个就够了

热门文章

  1. 测试员都是背锅侠?测试人员避“锅”攻略,拿走不谢
  2. 2022年2月halcon licenses
  3. 中国古代经典(汉英双语对照)
  4. 麒麟软件开始菜单消失v10-sp1
  5. Simulink仿真入门到精通(五) Simulink模型的仿真
  6. 驱寒药不妨试试这几种食物
  7. 电脑端如何访问手机SD卡中的文件
  8. 程序员成长的四个简单技巧,你 get 了吗?
  9. ZedGraph保存图片的两种方式
  10. VFP 二维数组声明和ALEN() ASCAN() AFIELD() ADEL()函数