安卓用户头像设置

转载请注明出处:http://blog.csdn.net/qq_35372900/article/details/60957378

许多多项目都有用户设置头像的功能。本篇文章就带大家学习一下如何实现用户头像设置。

首先看一下效果。


项目源码:https://github.com/moonfollower/SetHeadPortraitDemo


如上图所示,我们要实现让用户点击 ”更换头像“ 按钮时弹出一个窗口,用户可选择使用相机拍照或从手机相册中选择图片作为头像,并对用户确认图片进行截图。最后让切图完成的图片显示在我们的控件上并上传到服务器。

圆形图片的显示有两种方法,一是自定义圆形ImageView(本文采用此方法),二是将用户截图完成后的图片裁剪成圆形。

自定义CircleImageView网上有很多文章了,这里就不做解释了。感兴趣的同学可以参考我的Github,网址如下:

https://github.com/moonfollower/CircleImageView

弹出框这里是自定义的弹出框,可以根据项目需求进行更改。下面是我的弹出框代码。

public class ChangeHeadImagePop extends PopupWindow implements View.OnClickListener {

    private Activity activity;
    private View popView;

    private View v_item1;
    private View v_item2;
    private View v_item3;


    private OnItemClickListener onItemClickListener;

    /**
     *
     * @author moonfolower枚举,用于区分选择了哪个选项
     */
    public enum MENUITEM {
        ITEM1, ITEM2, ITEM3
    }

    public ChangeHeadImagePop(final Activity activity) {
        super(activity);
        this.activity = activity;
        LayoutInflater inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        popView = inflater.inflate(R.layout.chose_headimage_popwind, null);// 加载菜单布局文件
        this.setContentView(popView);// 把布局文件添加到popupwindow中
        this.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);// 设置菜单的宽度(需要和菜单于右边距的距离搭配,可以自己调到合适的位置)
        this.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
        this.setFocusable(true);// 获取焦点
        this.setTouchable(true); // 设置PopupWindow可触摸
        this.setOutsideTouchable(true); // 设置非PopupWindow区域可触摸
        ColorDrawable dw = new ColorDrawable(0x00000000);
        this.setBackgroundDrawable(dw);
        this.setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss() {
                /*setBackgroundAlpha(activity,1f);*/
            }
        });

        /*setBackgroundAlpha(activity,0.7f);*/

        // 获取选项卡
        v_item1 = popView.findViewById(R.id.camera);
        v_item2 = popView.findViewById(R.id.photoAlbum);
        v_item3 = popView.findViewById(R.id.cancel);

        // 添加监听
        v_item1.setOnClickListener(this);
        v_item2.setOnClickListener(this);
        v_item3.setOnClickListener(this);
    }

    /**
     * 设置显示的位置
     */
    public void showLocation(View anchorView) {
        /*int windowPos[] = PopupWindowUtil.calculatePopWindowPos(anchorView, popView);
        int xOff = 20; // 可以自己调整偏移
        windowPos[0] -= xOff;*/
        this.showAtLocation(anchorView, Gravity.BOTTOM , 0, 0);
    }

    /**
     * 设置背景色
     */
    private void setBackgroundAlpha(Activity context, float bgAlpha) {
        WindowManager.LayoutParams lp = context.getWindow().getAttributes();
        lp.alpha = bgAlpha;
        context.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        context.getWindow().setAttributes(lp);
    }

    // 点击监听接口
    public interface OnItemClickListener {
         void onClick(MENUITEM item, String str);
    }

    // 设置监听
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @Override
    public void onClick(View v) {
        MENUITEM menuitem = null;
        String str = "";
        if (v == v_item1) {
            menuitem = MENUITEM.ITEM1;
            str = "选项卡一";
        } else if (v == v_item2) {
            menuitem = MENUITEM.ITEM2;
            str = "选项卡二";
        } else if (v == v_item3) {
            menuitem = MENUITEM.ITEM3;
            str = "选项卡三";
        }
        if (onItemClickListener != null) {
            onItemClickListener.onClick(menuitem, str);
        }
        dismiss();
    }
}

XML布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:divider="@drawable/divider"
    android:showDividers = "middle"
    android:background="#fff"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Button
        android:id="@+id/camera"
        android:text="拍照"
        android:textSize="14sp"
        android:background="@null"
        android:layout_width="match_parent"
        android:layout_height="42dp" />
    <Button
        android:id="@+id/photoAlbum"
        android:background="@null"
        android:text="从手机上获取"
        android:textSize="14sp"
        android:layout_width="match_parent"
        android:layout_height="42dp" />
    <Button
        android:id="@+id/cancel"
        android:background="@null"
        android:text="取消"
        android:textSize="14sp"
        android:layout_width="match_parent"
        android:layout_height="42dp" />
</LinearLayout>

LinearLayout分割线,主要加上size属性

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#f00" />
    <size android:height="1px" />
</shape>

有人要说了,讲了半天还没说到头像设置呢?简直是个坑货。别急别急,准备工作必不可少,下面就进入正题。

1、点击拍照按钮启动相机进行拍照

首先给我们拍得的照片设置一个地址,方便截图使用。然后打开相机进行拍照。

注意这里有个坑,某些手机不支持直接修改SD子目录,如果你直接使用


 Environment.getExternalStorageDirectory();这个目录,选择相机进行拍照时,拍照完成时,因照片保存失败,导致不能从相机跳转回我们的项目。所以,
为适配所有手机,建议大家不要把图片保存地址放在SD卡直接子目录中,多写两层文件目录。



File dir = new File(imageDirPath);
    if(!dir.exists()){
            dir.mkdirs();
      }
File file = new File(dir,takePhotoImageName);//指定拍照后相片保存地址,以覆盖方式保存。
 Log.e("相机存放图片地址",file.getAbsolutePath());
 iconUri = Uri.fromFile(file);
  // 启动相机
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  // 设置输出路径
 intent.putExtra(MediaStore.EXTRA_OUTPUT, iconUri);
 startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);


2、选择手机相册中的图片。

Intent intent2 = new Intent(Intent.ACTION_PICK, null);
intent2.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent2, REQUEST_CODE_CHOOSE_IMAGE);

3、对获取到的图片进行截图(更改图片大小,设置图片位置等)。


/**
     * 裁剪图片
     * @param uri
     */
    public void startCropImage(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        // 图片处于可裁剪状态
        intent.putExtra("crop", "true");
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        // 是否之处缩放
        intent.putExtra("scale", true);
        // 设置图片的输出大小, 对于普通的头像,应该设置一下,可提高头像的上传速度
        intent.putExtra("outputX", 300);
        intent.putExtra("outputY", 300);
        // 以Uri的方式传递照片
        File dir = new File(imageDirPath);
        if(!dir.exists()){
            dir.mkdirs();
        }
        File crop_image = new File(dir,crop_ImageName);
        cropImageUri = Uri.fromFile(crop_image);

        intent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri);
        // 设置图片输出格式
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("return-data", false);
        // 关闭人脸识别
        intent.putExtra("noFaceDetection", false);
        startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
    }


在onActivityResult方法中进行操作

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // 用户没有进行有效的设置操作,返回
        if (resultCode == RESULT_CANCELED) {
            Toast.makeText(MainActivity.this,"取消",Toast.LENGTH_SHORT).show();
            return;
        }

            switch (requestCode){
                case REQUEST_CODE_TAKE_PHOTO:
                    if(null != iconUri){
                        File file = new File(iconUri.getPath());

                        Log.e("文件是否存在",file.exists()+"");
                        // 打开相机页面后,如果按返回键也会回调,所以需要判断是否拍摄了照片
                        if (file.exists()) {
                            // 裁剪图片
                            startCropImage(iconUri);
                        }
                    }

                    break;
                case REQUEST_CODE_CHOOSE_IMAGE:
                    Log.e("相册选择",data.getData()+"");
                    if (data.getData() != null) {
                        iconUri = data.getData();
                        startCropImage(iconUri);
                    }
                    break;
                case REQUEST_CODE_CROP_IMAGE:
                    Toast.makeText(MainActivity.this,"剪切完毕",Toast.LENGTH_SHORT).show();
                    //上传图片,然后设置图片,这里不上传图片。
                    if(null !=cropImageUri){
                        Log.e("剪切图片地址",cropImageUri.getPath());
                        Bitmap bitmap = BitmapFactory.decodeFile(imageDirPath+File.separator+crop_ImageName);
                        circleImageView.setImageBitmap(bitmap);
                        bitmap.recycle();
                    }
                    break;
            }
    }

最后是自定义的一些常量,包括图片存放地址,图片文件名和请求码等。

public static final String imageDirPath = Environment.getExternalStorageDirectory()+"/moon/images";
public static final String takePhotoImageName = "take_photo.jpg";
public static final String crop_ImageName = "crop_image.jpg";
 //照相
private static final int REQUEST_CODE_TAKE_PHOTO = 0;
 //选择图片
 private static final int REQUEST_CODE_CHOOSE_IMAGE = 1;
 //剪切图片
  private static final int REQUEST_CODE_CROP_IMAGE = 2;


到这里就完成了,是不是很easy,如果不太明白,可以下载源码。

项目源码:https://github.com/moonfollower/SetHeadPortraitDemo







  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值