Android仿微信QQ设置图形头像裁剪功能

最近在做毕业设计,想有一个功能和QQ一样可以裁剪头像并设置圆形头像,额,这是设计狮的一种潮流。

而纵观现在主流的APP,只要有用户系统这个功能,这个需求一般都是在(bu)劫(de)难(bu)逃(xue)!

图片裁剪实现方式有两种,一种是利用系统自带的裁剪工具,一种是使用开源工具Cropper。本节就为大家带来如何使用系统自带的裁剪工具进行图片裁剪~

还是先来个简单的运行图。

额,简单说下,我待会会把代码写成小demo分享给大家,在文章末尾会附上github链接,需要的可以自行下载~

下面来简单分析一下实现思路,我们首先照片肯定可以通过拍照和从相册选取,这个都可以向系统发送特定的Intent,响应对应的系统程序,然后在onActivityResult里面,获取我们的数据即可。而在onActivityResult里面,我们可以获取到两种形式的数据,Bitmap and uri。一般情况下我们是不会选择Bitmap的,因为大家都知道我们的手机里面的照片都太大了~强行使用bitmap,我只能说你,屌屌屌,sorry,我说的不是666,是傻屌的意思!

哈哈哈,让我爆粗口,我原本是拒绝的~只是希望警醒在看文章的你,那么就用uri吧~

那么然后呢?当然是对它做裁剪,完成后把这个裁剪后的bitmap对象设置给ImageView,保存起来,上传到服务器即可。

大致了解了流程,那么我们直接看代码吧~

先看看我们的圆形Image吧,我这个有点乱,因为考虑了很多我毕设的逻辑,所以做了一些修正,这个圆形Image相信网上会很多。

package com.example.nanchen.cropimagetest;
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.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
/**
* @author nanchen
* @fileName CropImageTest
* @packageName com.example.nanchen.cropimagetest
* @date 2016/10/13 15:09
*/
public class RoundImageView extends ImageView {
/**
* 圆形ImageView,可设置最多两个宽度不同且颜色不同的圆形边框。
*
* @author Alan
*/
private static class imageview_level {
public final static int level0 = 0;
public final static int level1 = 1;
public final static int level2 = 2;
public final static int level3 = 3;
public final static int level4 = 4;
}
private Context mContext;
private int circleColor = Color.WHITE;
private int circleWidth = 0;
private int mLevel = imageview_level.level1;
public void setLevel(int level) {
mLevel = level;
}
public RoundImageView(Context context) {
super(context);
mContext = context;
}
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setCustomAttributes(attrs);
}
public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
setCustomAttributes(attrs);
}
private void setCustomAttributes(AttributeSet attrs) {
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview);
int width = a.getDimensionPixelSize(R.styleable.roundedimageview_border_thickness, 0);
setPadding(width, width, width, width);
mLevel = a.getInt(R.styleable.roundedimageview_image_mode, imageview_level.level1);
circleColor = a.getColor(R.styleable.roundedimageview_border_color, circleColor);
}
@Override
public void setImageBitmap(Bitmap bm) {
switch (this.mLevel) {
case imageview_level.level1 :
bm = RoundBitmap(bm);
case imageview_level.level2 :
if ((getPaddingLeft() == getPaddingRight()) && (getPaddingLeft() == getPaddingBottom())
&& (getPaddingLeft() == getPaddingTop())) {
this.circleWidth = getPaddingLeft();
bm = RoundBitmap(bm);
}
break;
case imageview_level.level3 :
bm = ChamferBitmap(bm);
break;
case imageview_level.level4:
if ((getPaddingLeft() == getPaddingRight()) && (getPaddingLeft() == getPaddingBottom())
&& (getPaddingLeft() == getPaddingTop())) {
this.circleWidth = getPaddingLeft();
bm = RoundBitmap(bm);
}
break;
default :
break;
}
super.setImageBitmap(bm);
}
@Override
protected void onDraw(Canvas canvas) {
switch (this.mLevel) {
case imageview_level.level2:
if (circleWidth > 0) {
drawCircleBorder(canvas, (getWidth() - this.circleWidth*2 + circleWidth) / 2, this.circleColor, getWidth(),
getHeight(), this.circleWidth);
}
break;
case imageview_level.level4:
if (circleWidth > 0){
int paddingwidth = circleWidth;
drawCircleBorder(canvas, (getWidth()-paddingwidth*2 +circleWidth /2) / 2, this.circleColor, getWidth(),
getHeight(), this.circleWidth /2,Color.DKGRAY);
int tempwidth = circleWidth /2;
drawCircleBorder(canvas, (getWidth()-paddingwidth*2 +tempwidth) / 2, this.circleColor, getWidth(),
getHeight(), tempwidth,Color.DKGRAY);
}
break;
default:
break;
}
super.onDraw(canvas);
}
/**
* bitmap切成圆形
*
* @param bitmap 传入Bitmap对象
* @return
*/
private Bitmap RoundBitmap(Bitmap bitmap) {
Bitmap resultBitmap = null;
Canvas canvas = null;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float roundPx;
float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
if (width <= height) {
roundPx = width / 2;
top = 0;
bottom = width;
left = 0;
right = width;
height = width;
dst_left = 0;
dst_top = 0;
dst_right = width;
dst_bottom = width;
} else {
roundPx = height / 2;
float clip = (width - height) / 2;
left = clip;
right = width - clip;
top = 0;
bottom = height;
width = height;
dst_left = 0;
dst_top = 0;
dst_right = height;
dst_bottom = height;
}
if (width <= 0) {
width = 1;
}
if (height <= 0) {
height = 1;
}
try {
resultBitmap = Bitmap.createBitmap(width, height, Config.ARGB_4444);
} catch (Throwable e) {
e.printStackTrace();
}
try {
canvas = new Canvas(resultBitmap);
} catch (Throwable e) {
e.printStackTrace();
}
final int color = Color.RED;
final Paint paint = new Paint();
final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom);
final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom);
final RectF rectF = new RectF(dst);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
// paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, src, dst, paint);
return resultBitmap;
}
/**
* bitmap倒角
*
* @param bitmap 传入Bitmap对象
* @return
*/
private Bitmap ChamferBitmap(Bitmap bitmap) {
Bitmap resultBitmap = null;
Canvas canvas = null;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float roundPx;
float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
if (width <= height) {
roundPx = dip2px(this.mContext, 4); // 8像素倒角 4是dp值
top = 0;
bottom = width;
left = 0;
right = width;
height = width;
dst_left = 0;
dst_top = 0;
dst_right = width;
dst_bottom = width;
} else {
roundPx = dip2px(this.mContext, 4); // 8像素倒角 4是dp值
float clip = (width - height) / 2;
left = clip;
right = width - clip;
top = 0;
bottom = height;
width = height;
dst_left = 0;
dst_top = 0;
dst_right = height;
dst_bottom = height;
}
if (width <= 0) {
width = 1;
}
if (height <= 0) {
height = 1;
}
try {
resultBitmap = Bitmap.createBitmap(width, height, Config.ARGB_4444);
} catch (Throwable e) {
e.printStackTrace();
}
try {
canvas = new Canvas(resultBitmap);
} catch (Throwable e) {
e.printStackTrace();
}
final int color = Color.RED;
final Paint paint = new Paint();
final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom);
final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom);
final RectF rectF = new RectF(dst);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
// paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, src, dst, paint);
return resultBitmap;
}
/**
* 画布画圆
*/
private void drawCircleBorder(Canvas canvas, int radius, int color, int width, int height, int circleWidth) {
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(circleWidth);
canvas.drawCircle(width / 2, height / 2, radius, paint);
}
private void drawCircleBorder(Canvas canvas, int radius, int color, int width, int height, int circleWidth,int shadowcolor){
canvas.save(); //保存画布当前状态
canvas.rotate(45,width / 2, height / 2); //右下角45度阴影投射
Paint paint = new Paint();
paint.setColor(0x09ffffff & shadowcolor ); //设置alpha值
for(int i=0;i<circleWidth*2;i++) //向下角角偏移投射多少次阴影层
{
canvas.drawCircle(width/2+i, height / 2, radius+2, paint);
}
canvas.restore();
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(circleWidth); //二分之一实体
canvas.drawCircle(width / 2, height / 2, radius, paint);
}
public void setCircleWidth(int padding) {
setPadding(padding, padding, padding, padding);
}
public int getCircleColor() {
return circleColor;
}
public void setCircleColor(int circleColor) {
this.circleColor = circleColor;
}
// 执行完setImageBitmap后才能获得;
public int getCircleWidth() {
return this.circleWidth;
}
public OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
changeLight((ImageView) view, 0);
// onclick
break;
case MotionEvent.ACTION_DOWN:
changeLight((ImageView) view, -60);
break;
case MotionEvent.ACTION_MOVE:
// changeLight((ImageView) view, 0);
break;
case MotionEvent.ACTION_CANCEL:
changeLight((ImageView) view, 0);
break;
default:
break;
}
return false;
}
};
public void setColorFilter(boolean value){
if(value){
setOnTouchListener(onTouchListener);
}else{
setOnTouchListener(null);
}
}
private void changeLight(ImageView imageview, int brightness) {
ColorMatrix matrix = new ColorMatrix();
matrix.set(new float[] { 1, 0, 0, 0, brightness, 0, 1, 0, 0, brightness, 0, 0, 1, 0, brightness, 0, 0, 0, 1, 0 });
imageview.setColorFilter(new ColorMatrixColorFilter(matrix));
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
private int dip2px(Context context, float dpValue) {
final float scale = context.getApplicationContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}

自定义一个仿IOS的弹出框

package com.example.nanchen.cropimagetest;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import java.util.List;
/**
* dialog
*
*/
public class SelectDialog extends Dialog implements OnClickListener,OnItemClickListener {
private SelectDialogListener mListener;
private Activity mActivity;
private Button mMBtn_Cancel;
private TextView mTv_Title;
private List<String> mName;
private String mTitle;
private boolean mUseCustomColor = false;
private int mFirstItemColor;
private int mOtherItemColor;
public interface SelectDialogListener {
public void onItemClick(AdapterView<?> parent, View view, int position, long id);
}
private SelectDialogCancelListener mCancelListener;
public interface SelectDialogCancelListener {
public void onCancelClick(View v);
}
public SelectDialog(Activity activity, int theme,
SelectDialogListener listener,List<String> names) {
super(activity, theme);
mActivity = activity;
mListener = listener;
this.mName=names;
// 设置是否点击外围解散
setCanceledOnTouchOutside(true);
}
/**
* @param activity 调用弹出菜单的activity
* @param theme 主题
* @param listener 菜单项单击事件
* @param cancelListener 取消事件
* @param names 菜单项名称
*
*/
public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener ,List<String> names) {
super(activity, theme);
mActivity = activity;
mListener = listener;
mCancelListener = cancelListener;
this.mName=names;
// 设置是否点击外围不解散
setCanceledOnTouchOutside(false);
}
/**
* @param activity 调用弹出菜单的activity
* @param theme 主题
* @param listener 菜单项单击事件
* @param names 菜单项名称
* @param title 菜单标题文字
*
*/
public SelectDialog(Activity activity, int theme,SelectDialogListener listener,List<String> names,String title) {
super(activity, theme);
mActivity = activity;
mListener = listener;
this.mName=names;
mTitle = title;
// 设置是否点击外围可解散
setCanceledOnTouchOutside(true);
}
public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener,List<String> names,String title) {
super(activity, theme);
mActivity = activity;
mListener = listener;
mCancelListener = cancelListener;
this.mName=names;
mTitle = title;
// 设置是否点击外围可解散
setCanceledOnTouchOutside(true);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = getLayoutInflater().inflate(R.layout.view_dialog_select,
null);
setContentView(view, new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
Window window = getWindow();
// 设置显示动画
window.setWindowAnimations(R.style.main_menu_animstyle);
WindowManager.LayoutParams wl = window.getAttributes();
wl.x = 0;
wl.y = mActivity.getWindowManager().getDefaultDisplay().getHeight();
// 以下这两句是为了保证按钮可以水平满屏
wl.width = LayoutParams.MATCH_PARENT;
wl.height = LayoutParams.WRAP_CONTENT;
// 设置显示位置
onWindowAttributesChanged(wl);
//setCanceledOnTouchOutside(false);
initViews();
}
private void initViews() {
DialogAdapter dialogAdapter=new DialogAdapter(mName);
ListView dialogList=(ListView) findViewById(R.id.dialog_list);
dialogList.setOnItemClickListener(this);
dialogList.setAdapter(dialogAdapter);
mMBtn_Cancel = (Button) findViewById(R.id.mBtn_Cancel);
mTv_Title = (TextView) findViewById(R.id.mTv_Title);
//mMBtn_Cancel.setOnClickListener(this);
mMBtn_Cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(mCancelListener != null){
mCancelListener.onCancelClick(v);
}
dismiss();
}
});
if(!TextUtils.isEmpty(mTitle) && mTv_Title != null){
mTv_Title.setVisibility(View.VISIBLE);
mTv_Title.setText(mTitle);
}else{
mTv_Title.setVisibility(View.GONE);
}
}
@Override
public void onClick(View v) {
dismiss();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
mListener.onItemClick(parent, view, position, id);
dismiss();
}
private class DialogAdapter extends BaseAdapter {
private List<String> mStrings;
private Viewholder viewholder;
private LayoutInflater layoutInflater;
public DialogAdapter(List<String> strings) {
this.mStrings = strings;
this.layoutInflater=mActivity.getLayoutInflater();
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mStrings.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mStrings.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == convertView) {
viewholder=new Viewholder();
convertView=layoutInflater.inflate(R.layout.view_dialog_item, null);
viewholder.dialogItemButton=(TextView) convertView.findViewById(R.id.dialog_item_bt);
convertView.setTag(viewholder);
}else{
viewholder=(Viewholder) convertView.getTag();
}
viewholder.dialogItemButton.setText(mStrings.get(position));
if (!mUseCustomColor) {
mFirstItemColor = mActivity.getResources().getColor(R.color.dialog_blue);
mOtherItemColor = mActivity.getResources().getColor(R.color.dialog_blue);
}
if (1 == mStrings.size()) {
viewholder.dialogItemButton.setTextColor(mFirstItemColor);
viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_only);
} else if (position == 0) {
viewholder.dialogItemButton.setTextColor(mFirstItemColor);
viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_top);
} else if (position == mStrings.size() - 1) {
viewholder.dialogItemButton.setTextColor(mOtherItemColor);
viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_buttom);
} else {
viewholder.dialogItemButton.setTextColor(mOtherItemColor);
viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_center);
}
return convertView;
}
}
public static class Viewholder {
public TextView dialogItemButton;
}
/**
* 设置列表项的文本颜色
*/
public void setItemColor(int firstItemColor, int otherItemColor) {
mFirstItemColor = firstItemColor;
mOtherItemColor = otherItemColor;
mUseCustomColor = true;
}
}

由于图片文件一定在相册中,有可能你也会在文件系统中其他地方选择,这里我采用之前写的万能适配器!

由于楼主时间的确比较紧,所以代码都是直接copy上来的,有些地方没做完全优化还望大家见谅!

再看看Activity的代码和布局

package com.example.nanchen.cropimagetest;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AlertDialog.Builder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import com.example.nanchen.cropimagetest.SelectDialog.SelectDialogListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RoundImageView mHeadImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHeadImage = (RoundImageView) findViewById(R.id.main_roundImage);
}
private final int PHOTO_PICKED_FROM_CAMERA = 1; // 用来标识头像来自系统拍照
private final int PHOTO_PICKED_FROM_FILE = 2; // 用来标识从相册获取头像
private final int CROP_FROM_CAMERA = 3;
private void getIconFromPhoto(){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult(intent, PHOTO_PICKED_FROM_FILE);
}
private void selectPhoto() {
List<String> list = new ArrayList<>();
list.add("拍照");
list.add("相册");
showDialog(new SelectDialogListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch (position){
case 0:
getIconFromCamera();
break;
case 1:
getIconFromPhoto(); // 从系统相册获取
break;
default:
break;
}
}
},list);
}
private Uri imgUri; // 由于android手机的图片基本都会很大,所以建议用Uri,而不用Bitmap
/**
* 调用系统相机拍照
*/
private void getIconFromCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imgUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
"avatar_"+String.valueOf(System.currentTimeMillis())+".png"));
intent.putExtra(MediaStore.EXTRA_OUTPUT,imgUri);
startActivityForResult(intent,PHOTO_PICKED_FROM_CAMERA);
}
private SelectDialog showDialog(SelectDialogListener listener, List<String> list){
SelectDialog dialog = new SelectDialog(this,
R.style.transparentFrameWindowStyle,listener,list);
dialog.show();
return dialog;
}
/**
* 尝试裁剪图片
*/
private void doCrop(){
final ArrayList<CropOption> cropOptions = new ArrayList<>();
final Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,0);
int size = list.size();
if (size == 0){
UIUtil.showToast(this,"当前不支持裁剪图片!");
return;
}
intent.setData(imgUri);
intent.putExtra("outputX",300);
intent.putExtra("outputY",300);
intent.putExtra("aspectX",1);
intent.putExtra("aspectY",1);
intent.putExtra("scale",true);
intent.putExtra("return-data",true);
// only one
if (size == 1){
Intent intent1 = new Intent(intent);
ResolveInfo res = list.get(0);
intent1.setComponent(new ComponentName(res.activityInfo.packageName,res.activityInfo.name));
startActivityForResult(intent1,CROP_FROM_CAMERA);
}else {
// 很多可支持裁剪的app
for (ResolveInfo res : list) {
CropOption co = new CropOption();
co.title = getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo);
co.icon = getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo);
co.appIntent = new Intent(intent);
co.appIntent.setComponent(new ComponentName(res.activityInfo.packageName,res.activityInfo.name));
cropOptions.add(co);
}
CommonAdapter<CropOption> adapter = new CommonAdapter<CropOption>(this,cropOptions,R.layout.layout_crop_selector) {
@Override
public void convert(ViewHolder holder, CropOption item) {
holder.setImageDrawable(R.id.iv_icon,item.icon);
holder.setText(R.id.tv_name,item.title);
}
};
AlertDialog.Builder builder = new Builder(this);
builder.setTitle("choose a app");
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivityForResult(cropOptions.get(which).appIntent,CROP_FROM_CAMERA);
}
});
builder.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
if (imgUri != null){
getContentResolver().delete(imgUri,null,null);
imgUri = null;
}
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK){
return;
}
switch (requestCode) {
case PHOTO_PICKED_FROM_CAMERA:
doCrop();
break;
case PHOTO_PICKED_FROM_FILE:
imgUri = data.getData();
doCrop();
break;
case CROP_FROM_CAMERA:
if (data != null){
setCropImg(data);
}
break;
default:
break;
}
}
private void setCropImg(Intent picData){
Bundle bundle = picData.getExtras();
if (bundle != null){
Bitmap mBitmap = bundle.getParcelable("data");
mHeadImage.setImageBitmap(mBitmap);
saveBitmap(Environment.getExternalStorageDirectory() + "/crop_"
+System.currentTimeMillis() + ".png",mBitmap);
}
}
private void saveBitmap(String fileName,Bitmap bitmap){
File file = new File(fileName);
FileOutputStream fout = null;
try {
file.createNewFile();
fout = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG,100,fout);
fout.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fout!=null){
fout.close();
}
UIUtil.showToast(MainActivity.this,"保存成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void btnClick(View view) {
selectPhoto();
}
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.nanchen.cropimagetest.MainActivity">
<com.example.nanchen.cropimagetest.RoundImageView
android:id="@+id/main_roundImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:src="@drawable/default_avatar"/>
<Button
android:id="@+id/main_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/main_roundImage"
android:onClick="btnClick"
android:text="设置头像"/>
</RelativeLayout>

以上所述是小编给大家介绍的Android仿微信QQ设置图形头像裁剪功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

时间: 2016-10-12

Android实现带头像的用户注册页面

1.首先是注册页面的布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"

Android实现用户头像更换操作

你以为头像更换很容易?或许对于用户来讲,在微信上更换一个头像只是点击头像,选择拍照或相册,裁剪返回而已.但是对于程序员来说,要实现其实也挺吃力的(小火柴花了一个下午整理~_~). 正如用户使用那样,代码的实现也是按照操作的顺序而逐步展开.如下图: 接下来主要来讲解一下代码: 1. 弹框选择相册或拍照 比较简单的方式就是直接使用AlertDialog弹出选项供用户进行选择 public static void showImagePickDialog(final Activity activity)

Android仿微信群聊头像

工作中需要实现仿钉钉群头像的一个功能,就是个人的头像拼到一起显示,看了一下市场上的APP好像微信的群聊头像是组合的,QQ的头像不是,别的好像也没有了. 给大家分享一下怎么实现的吧.首先我们先看一下效果图: 好了,下面说一下具体怎么实现的: 实现思路 1.首先获取Bitmap图片(本地.网络) 2.创建一个指定大小的缩略图 3.组合Bitmap图片 很简单,本地图片需要我们从本地读取,如果是网络图片我们也可以根据URL来获取bitmap进行组合 具体实现过程 1.布局文件: <LinearLayo

Android实现动态圆环的图片头像控件

先看效果图: 现在大部分的app上难免会使用到圆形头像,所以今天我给大家分享一个单独使用的,并且周围带有圆环动画的花哨圆形头像控件,本控件是在圆形头像控件基础上实现的,只是在其周围再画一些不同大小的圆而已,就可以实现如图的效果. 圆形头像的基本原理是将设置的资源文件转化成Bitmap,然后通过BitmapShader类将Bitmap成为Paint的渲染器,然后在onDraw()中通过canvas.drawCircle(rx,ry,radius,paint);画布上画圆,而这个圆就是形成了圆形头像

Android手机拍照或选取图库图片作为头像

package zhangpgil.photo; import java.io.File; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import android.content.Intent; import

Android中通过访问本地相册或者相机设置用户头像实例

目前几乎所有的APP在用户注册时都会有设置头像的需求,大致分为三种情况: (1)通过获取本地相册的图片,经过裁剪后作为头像. (2)通过启动手机相机,现拍图片然后裁剪作为头像. (3)在APP中添加一些自带的头像资源,供用户选择(不够人性化,目前很少使用). 这次我们简单介绍下通过获取本地相册以及相机拍摄的方法设置头像,实现思路如下: (1)通过startActivityForResult方法,分别传递调用系统相册的Intent和调用相机拍照的Intent来做选择 (2)调用Android系统中

Android自定义控件仿QQ编辑和选取圆形头像

android大家都有很多需要用户上传头像的需求,有的是选方形,有的是圆角矩形,有的是圆形. 首先我们要做一个处理图片的自定义控件,把传入的图片,经过用户选择区域,处理成一定的形状. 有的app是通过在图片上画一个矩形区域表示选中的内容,有的则是通过双指放大缩小,拖动图片来选取图片.圆形头像,还是改变图片比较好 圆形区域可调节大小. 这个自定义View的图像部分分为三个,背景图片,半透明蒙层,和亮色区域--还是直接贴代码得了 package com.example.jjj.widget; imp

Android个人中心的头像上传,图片编码及截取实例

首先需要有网络权限,然后我们这里匹配的网络请求是之前封装好的Okhttp. 非常的简单方便,直接复制进去,依赖一下包,然后调用方法即可. 这里是把图片转换成Base64.decode(imageString, Base64.DEFAULT); 转成Base64编码上传.具体内容也不少,需要完全整明白,还是要花点时间慢慢看的. 先看看简单的效果图: 那么万事具备,只欠东风了.直接上代码: public class MainActivity extends AppCompatActivity imp

Android通过手机拍照或从本地相册选取图片设置头像

像微信.QQ.微博等社交类的APP,通常都有设置头像的功能,设置头像通常有两种方式: 1.让用户通过选择本地相册之类的图片库中已有的图像,裁剪后作为头像. 2.让用户启动手机的相机拍照,拍完照片后裁剪,然后作为头像. 我现在写一个简单的完整代码例子,说明如何在android中实现上述两个头像设置功能. MainActivity.Java文件: package zhangpgil.photo; import java.io.File; import android.support.v7.app.A

Android实现本地上传图片并设置为圆形头像

先从本地把图片上传到服务器,然后根据URL把头像处理成圆形头像. 因为上传图片用到bmob的平台,所以要到bmob(http://www.bmob.cn)申请密钥. 效果图: 核心代码: 复制代码 代码如下: public class MainActivity extends Activity {         private ImageView iv;         private String appKey="";                //填写你的Applicatio

Android中使用CircleImageView和Cardview制作圆形头像的方法

圆形头像在我们的日常使用的app中很常见,因为圆形的头像比较美观. 使用圆形图片的方法可能有我们直接将图片裁剪成圆形再在app中使用,还有就是使用自定义View对我们设置的任何图片自动裁剪成圆形. 效果图: 这里使用github上CircleImageView github:https://github.com/hdodenhof/CircleImageView CardView顾名思义卡片式的View,CardView继承的是FrameLayout,所以摆放内部控件的时候需要注意一下 可以设置

Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)

Feature: 点击选择拍照或者打开相册,选取图片进行裁剪最后设置为圆形头像. Problem: 拍好照片,点击裁剪,弹Toast"无法加载此图片". Solution: 在裁剪的class里加两行代码 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 主要代码如下: public static final S

利用Android中BitmapShader制作自带边框的圆形头像

效果如下: BitmapShader 的简单介绍 关于 Shader是什么,Shader的种类有哪几种以及如何使用不属于本文范畴,对这方面不是很了解的同学,建议先去学习一下 Shader 的基本使用. BitmapShader主要的作用就是 通过Paint对象,对 画布进行指定的Bitmap填充,实现一系列效果,可以有以下三种模式进行选择 1.CLAMP - 拉伸,这里拉伸的是图片的最后一个元素,不断地重复,这个效果,在图片比较小,而所要画的面积比较大的时候会比较明显. 2.REPEAT - 重

Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码

在Android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦.所以在这里写一个自定义圆形ImageView,直接去加载网络图片,这样的话就特别的方便. 先上效果图 主要的方法 1.让自定义 CircleImageView 继承ImageView /** * 自定义圆形头像 * Created by Dylan on 2015/11/26 0026. */ public class CircleImageView extends ImageView { } 2.在构造方法中

Android自定义View实现QQ音乐中圆形旋转碟子

QQ音乐中圆形旋转碟子 思路分析: 1.在onMeasure中测量整个View的宽和高后,设置宽高 2.获取我们res的图片资源后,在ondraw方法中进行绘制圆形图片 3.通过Handler发送Runnable来启动旋转线程(如果只想做圆形头像的话,这步可以去掉) 4.在布局中使用我们的View 效果图: 贴出我们的变量信息: //view的宽和高 int mHeight = 0; int mWidth = 0; //圆形图片 Bitmap bitmap = null; //圆形图片的真实半径

Android开发使用Drawable绘制圆角与圆形图案功能示例

本文实例讲述了Android开发使用Drawable绘制圆角与圆形图案功能.分享给大家供大家参考,具体如下: 1. 创建类RoundCircleDrawable继承Drawable /** * 圆角矩形 * @Project App_View * @Package com.android.view.drawable * @author chenlin * @version 1.0 * @Date 2016年4月21日 * @Note TODO */ public class RoundCircl

Android 通过Base64上传图片到服务器实现实例

Android 通过Base64上传图片到服务器 之前做上传图片是采用HttpServlet上传,不过用了一下Base64上传图片后,感觉比HttpServlet方便很多,大家也可以跟着尝试一下. 前台图片处理:(传Bitmap对象即可) /** * 通过Base32将Bitmap转换成Base64字符串 * @param bit * @return */ public String Bitmap2StrByBase64(Bitmap bit){ ByteArrayOutputStream bo