自定义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
原创粉丝点击