自定义ImageView完成圆形头像自定义
来源:互联网 发布:deepin linux 安装jdk 编辑:程序博客网 时间:2024/05/02 14:16
前言
我们可以看到现在的好多app的头像都是圆形的,记得应该是一年之前吧,具体的时间也不记得了,那个时候更新飞信,那次改版挺大,头像是圆形的,感觉挺不错的。那么今天也来实现以下吧。
我们来分析一下,怎么去实现
- 第一步:我们应该知道显示的头像是一个imageview,那么我们就继承ImageView
- 第二步:它有自己的自定义属性(外部有一个大小可以变的圆,颜色也可以变化)
接下来我们来实现吧
- 首先要来看看他有的自定义属性
attrs.xml:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="CircleImageView"> <attr name="outCircleColor" format="color"/> <attr name="outCircleWidth" format="dimension"/> </declare-styleable></resources>
- 来实现自定义的ImageView:
这里面也没有多少的代码,在这里用到的测量宽高,绘制圆,代码里面都有了注释。
package com.example.headimage;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.widget.ImageView;/** * Created by 若兰 on 2016/2/13. * 一个懂得了编程乐趣的小白,希望自己 * 能够在这个道路上走的很远,也希望自己学习到的 * 知识可以帮助更多的人,分享就是学习的一种乐趣 * QQ:1069584784 * csdn:http://blog.csdn.net/wuyinlei */public class CircleImageView extends ImageView { //外圆的宽度 private int outCircleWidth; //外圆的颜色 private int outCircleColor = Color.WHITE; //画笔 private Paint paint; //view的宽度和高度 private int viewWidth; private int viewHeigth; private Bitmap image; public CircleImageView(Context context) { this(context, null); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs, defStyleAttr); } /** * 初始化资源文件 * * @param context * @param attrs * @param defStyleAttr */ private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray array = null; if (attrs != null) { array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView); int len = array.length(); for (int i = 0; i < len; i++) { int attr = array.getIndex(i); switch (attr) { //获取到外圆的颜色 case R.styleable.CircleImageView_outCircleColor: this.outCircleColor = array.getColor(attr, Color.WHITE); break; //获取到外圆的半径 case R.styleable.CircleImageView_outCircleWidth: this.outCircleWidth = (int) array.getDimension(attr, 5); break; } } } paint = new Paint(); paint.setColor(outCircleColor);//颜色 paint.setAntiAlias(true);//设置抗锯齿 array.recycle(); //回收 } /** * view的测量 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = measureWith(widthMeasureSpec); int height = measureWith(heightMeasureSpec); viewWidth = width - outCircleWidth * 2; viewHeigth = height - outCircleWidth * 2; //调用该方法将测量后的宽和高设置进去,完成测量工作, setMeasuredDimension(width, height); } /** * 测量宽和高,这一块可以是一个模板代码(Android群英传) * @param widthMeasureSpec * @return */ private int measureWith(int widthMeasureSpec) { int result = 0; //从MeasureSpec对象中提取出来具体的测量模式和大小 int mode = MeasureSpec.getMode(widthMeasureSpec); int size = MeasureSpec.getSize(widthMeasureSpec); if (mode == MeasureSpec.EXACTLY) { //测量的模式,精确 result = size; } else { result = viewWidth; } return result; } /** * 绘制 * @param canvas */ @Override protected void onDraw(Canvas canvas) { //加载图片 loadImage(); if (image != null) { //拿到最小的值(这里我们要去到最小的) int min = Math.min(viewWidth, viewHeigth); int circleCenter = min / 2; image = Bitmap.createScaledBitmap(image, min, min, false); //画圆 canvas.drawCircle(circleCenter + outCircleWidth, circleCenter + outCircleWidth, circleCenter + outCircleColor, paint); //画图像 canvas.drawBitmap(createCircleBitmap(image, min), outCircleWidth, outCircleWidth, null); } } /** * 创建一个圆形的bitmap * * @param image 传入的image * @param min * @return */ private Bitmap createCircleBitmap(Bitmap image, int min) { Bitmap bitmap = null; Paint paint = new Paint(); paint.setAntiAlias(true); bitmap = Bitmap.createBitmap(min, min, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); //画一个和图片大小相等的画布 canvas.drawCircle(min / 2, min / 2, min / 2, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(image, 0, 0, paint); return bitmap; } /** * 加载Image */ private void loadImage() { BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable(); if (bitmapDrawable != null) { image = bitmapDrawable.getBitmap(); } } /** * 对外提供的可以设置外圆的颜色的方法 * @param outCircleColor */ public void setOutCircleColor(int outCircleColor) { if (null != paint) { paint.setColor(outCircleColor); } this.invalidate(); } /** * 对外提供给的设置外圆的宽度大小的方法 * @param outCircleWidth */ public void setOutCircleWidth(int outCircleWidth) { this.outCircleWidth = outCircleWidth; this.invalidate(); }}
我们来看下效果图:
好了,这里我在添加一些功能吧,就是可以选择相册图片,可以调用系统相机,在使用图片的时候可以裁剪。我们点击的时候用到了PopupWindow。这些代码都很简单(我以为还有点知识点,结果被鄙视了。。。)
package com.example.headimage;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.net.Uri;import android.os.Environment;import android.provider.MediaStore;import android.provider.Settings;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.Gravity;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.PopupWindow;import android.widget.RelativeLayout;import android.widget.Toast;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private CircleImageView ivHead; private RelativeLayout layout_choose; private RelativeLayout layout_photo; private RelativeLayout layout_close; private LinearLayout layout_all; protected int mScreenWidth; /** * 定义三种状态 */ private static final int REQUESTCODE_PIC = 1;//相册 private static final int REQUESTCODE_CAM = 2;//相机 private static final int REQUESTCODE_CUT = 3;//图片裁剪 private Bitmap mBitmap; private File mFile; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ivHead = (CircleImageView) findViewById(R.id.iv_head); layout_all = (LinearLayout) findViewById(R.id.layout_all); ivHead.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.iv_head: showMyDialog(); break; } } PopupWindow avatorPop; private void showMyDialog() { View view = LayoutInflater.from(this).inflate(R.layout.pop_show_dialog, null); layout_choose = (RelativeLayout) view.findViewById(R.id.layout_choose); layout_photo = (RelativeLayout) view.findViewById(R.id.layout_photo); layout_close = (RelativeLayout) view.findViewById(R.id.layout_close); layout_choose.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); layout_photo.setBackgroundDrawable(getResources().getDrawable( R.drawable.pop_bg_press)); layout_close.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); layout_photo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub layout_choose.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); layout_photo.setBackgroundDrawable(getResources().getDrawable( R.drawable.pop_bg_press)); layout_close.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); openCamera(); // Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //startActivityForResult(intent,); } }); layout_choose.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub layout_photo.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); layout_choose.setBackgroundDrawable(getResources().getDrawable( R.drawable.pop_bg_press)); layout_close.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); openPic(); } }); layout_close.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { layout_photo.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); layout_close.setBackgroundDrawable(getResources().getDrawable( R.drawable.pop_bg_press)); layout_choose.setBackgroundColor(getResources().getColor( R.color.base_color_text_white)); avatorPop.dismiss(); } }); DisplayMetrics metric = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metric); mScreenWidth = metric.widthPixels; avatorPop = new PopupWindow(view, mScreenWidth, 200); avatorPop.setTouchInterceptor(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { avatorPop.dismiss(); return true; } return false; } }); //设置宽度 avatorPop.setWidth(WindowManager.LayoutParams.MATCH_PARENT); //设置高度 avatorPop.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); //可以点击 avatorPop.setTouchable(true); avatorPop.setFocusable(true); avatorPop.setOutsideTouchable(true); avatorPop.setBackgroundDrawable(new BitmapDrawable()); // 动画效果 从底部弹起 avatorPop.setAnimationStyle(R.style.Animations_GrowFromBottom); avatorPop.showAtLocation(layout_all, Gravity.BOTTOM, 0, 0); } /** * 打开相册 */ private void openPic() { Intent picIntent = new Intent(Intent.ACTION_PICK,null); picIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*"); startActivityForResult(picIntent,REQUESTCODE_PIC); } /** * 调用相机 */ private void openCamera() { String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)){ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); if (!file.exists()){ file.mkdirs(); } mFile = new File(file, System.currentTimeMillis() + ".jpg"); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mFile)); intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1); startActivityForResult(intent,REQUESTCODE_CAM); } else { Toast.makeText(this, "请确认已经插入SD卡", Toast.LENGTH_SHORT).show(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { switch (requestCode) { case REQUESTCODE_CAM: startPhotoZoom(Uri.fromFile(mFile)); break; case REQUESTCODE_PIC: if (data == null || data.getData() == null){ return; } startPhotoZoom(data.getData()); break; case REQUESTCODE_CUT: if (data!= null){ setPicToView(data); } break; } } super.onActivityResult(requestCode, resultCode, data); } private void setPicToView(Intent data) { Bundle bundle = data.getExtras(); if (bundle != null){ //这里也可以做文件上传 mBitmap = bundle.getParcelable("data"); ivHead.setImageBitmap(mBitmap); } } /** * 打开系统图片裁剪功能 * @param uri */ private void startPhotoZoom(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri,"image/*"); intent.putExtra("crop",true); intent.putExtra("aspectX",1); intent.putExtra("aspectY",1); intent.putExtra("outputX",300); intent.putExtra("outputY",300); intent.putExtra("scale",true); //黑边 intent.putExtra("scaleUpIfNeeded",true); //黑边 intent.putExtra("return-data",true); intent.putExtra("noFaceDetection",true); startActivityForResult(intent,REQUESTCODE_CUT); }}
我们来看下效果
裁剪功能:
裁剪后确定:
这里我们对于动画,还有资源属性用到了一些style样式,还有一些动画资源文件,这里我就不上传了,直接给git地址,方便下载,查看更多资源
https://github.com/wuyinlei/CircleImgae
1 0
- 自定义ImageView完成圆形头像自定义
- 自定义ImageView实现圆形头像
- 自定义ImageView实现圆形头像
- android 圆形头像 自定义ImageView
- androidの自定义ImageView圆形头像
- Android 自定义ImageView, 圆形六边形头像
- android自定义圆形头像view,继承imageview
- 自定义圆形ImageView(仿QQ头像)
- Android 简易 自定义ImageView 实现圆形头像
- 【Android】自定义圆形ImageView(圆形头像 可指定大小)
- 自定义带 vip 标识的 圆形头像(圆形ImageView)
- 【Android】自定义圆形ImageView(圆形头像 可指定大小)
- 安卓开发之自定义View------> 圆形头像ImageView
- 圆形头像以及一些常见需求形状自定义ImageView组件
- android 自定义ImageView控件实现圆形图片-适用于用户头像
- 自定义ImageView实现圆形头像 利用Xferomede实现
- Android自定义圆形头像
- android自定义圆形头像
- 清华1207
- angular到react
- 遗传算法(Genetic Algorithm)
- Handler 消息传递机制 AsyncTask 异步任务 小结
- Linux 字符设备驱动结构(三)—— file、inode结构体及chardevs数组等相关知识解析
- 自定义ImageView完成圆形头像自定义
- 面试-今日头条
- Xcode7,消失的pin菜单(Editor->pin)
- hadoop rpc基础
- Android消息推送
- MFC建立模态对话框和非模态对话框
- Android Studio导入系统源码教程
- 虚拟机安装
- linux下vim设置行号跟tab键4个空格