編輯:關於Android編程
最近在做畢業設計,想有一個功能和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設置圖形頭像裁剪功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對本站網站的支持!
本篇主要是LineChart實戰相關知識和簡單的源碼剖析,相關源碼沒有,自己動手實踐學習才是最有效的方法。LineChart Simple運行效果圖個人感官覺得某些屬性設
概述:項目地址:https://github.com/nostra13/Android-Universal-Image-Loader UIL(Universal-Imag
1.介紹首先看下支付寶上芝麻信用分的效果圖:2.思路確定雷達圖中心點坐標 繪制多邊形及連接線 根據維度值繪制覆蓋區域 繪制分數 繪制每個維度的標題文字和圖標3.實現獲取布
Android的控件有很多種,其中就有一個Spinner的控件,這個控件其實就是一個下拉顯示列表。Spinner是位於 android.widget包下的,每