最近在做毕业设计,想有一个功能和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设置图形头像裁剪功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
本文向大家介绍Android Kotlin仿微信头像裁剪图片的方法示例,包括了Android Kotlin仿微信头像裁剪图片的方法示例的使用技巧和注意事项,需要的朋友参考一下 0.前言 最近突发了很多事情,又跟康仔跳票了,无可奈何,不好意思了。最近生活上有很多感悟,一个男人的牛逼就在于平衡工作,学习和家庭,这个点很难把握,既要保证家庭和睦,又要保证自己价值的实现从而避免堕入平庸,每个人的状况都是不
本文向大家介绍Android仿微信群聊头像,包括了Android仿微信群聊头像的使用技巧和注意事项,需要的朋友参考一下 工作中需要实现仿钉钉群头像的一个功能,就是个人的头像拼到一起显示,看了一下市场上的APP好像微信的群聊头像是组合的,QQ的头像不是,别的好像也没有了。 给大家分享一下怎么实现的吧。首先我们先看一下效果图: 好了,下面说一下具体怎么实现的: 实现思路 1.首先获取Bitmap图片(
AvatarCropper 头像裁剪 平台差异说明 App H5 微信小程序 支付宝小程序 百度小程序 头条小程序 QQ小程序 √ √ √ √ √ √ √ 基本使用 组件使用流程: 打开头像裁剪页面,同时传递配置基本参数(已默认配置好最优参数) 选取图片,调整图片合适位置和大小,确定裁剪并返回此裁剪结果 在原始页面监听uAvatarCropper事件,获得裁剪结果 <template> <vie
我试图在从图库中选择图像后使用intent来裁剪图像。以下是我的代码片段 在这里,我使用PICK_IMAGE_REQUEST意图句柄调用上面的代码段 由于我在裁剪后使用了相同的意图,即PICK_IMAGE_REQUEST,可能会出现什么问题
我想从矩形照片中制作一个居中的圆形图像。照片的尺寸未知。通常是矩形。我尝试了很多方法: 密码
我将<code>背景 1.back_xml: 2.瓷砖.xml 现在,我将back.xml设置为< code >背景以< code>LinearLayout工作正常。 我需要有一个圆角,以及它的边框。但是我只有圆角的边框,而不是图像,我的代码中有什么问题吗? 这是我的照片: