Android开发之裁切(拍照+相冊)图像并设置头像小结
Posted wzjhoutai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发之裁切(拍照+相冊)图像并设置头像小结相关的知识,希望对你有一定的参考价值。
先看效果:
再贴代码:
自己定义选择照片底部弹出对话框布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical" > <LinearLayout android:id="@+id/pop_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="#312E3F" android:gravity="center_horizontal" android:orientation="vertical" > <Button android:id="@+id/takePhotoBtn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:layout_marginTop="10dp" android:background="@drawable/btn_bg_blue" android:padding="10dp" android:text="拍照" android:textColor="@color/colorwhite" android:textSize="18sp" android:textStyle="bold" /> <Button android:id="@+id/pickPhotoBtn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:layout_marginTop="5dp" android:background="@drawable/btn_bg_blue" android:padding="10dp" android:text="从相冊选择" android:textColor="@color/colorwhite" android:textSize="18sp" android:textStyle="bold" /> <Button android:id="@+id/cancelBtn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dip" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:layout_marginTop="20dp" android:background="@android:color/white" android:padding="10dp" android:text="取消" android:textColor="#373447" android:textSize="18sp" android:textStyle="bold" /> </LinearLayout> </RelativeLayout>
设备连接界面NavigationView header部分布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/nav_headerView" android:layout_width="match_parent" android:layout_height="@dimen/nav_header_height" android:background="@drawable/drawer_background" android:gravity="bottom" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:theme="@style/ThemeOverlay.AppCompat.Dark"> <com.aiofm.eminem.aiofmbgp.views.controls.CircleImage android:id="@+id/imageView" android:layout_width="80dp" android:layout_height="80dp" android:layout_centerHorizontal="true" android:paddingTop="@dimen/nav_header_vertical_spacing" android:src="@android:drawable/sym_def_app_icon" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/nav_header_vertical_spacing" android:text="鲍光普" android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[email protected]" /> </LinearLayout>
文件操作工具类代码:
package com.aiofm.eminem.aiofmbgp.common; /** * 文件工具类 * Created by eminem on 2016/4/10 */ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.os.Environment; public class FileUtil { /** * 将Bitmap 图片保存到本地路径。并返回路径 * @param c 上下文 * @param fileName 文件名 * @param bitmap 图片资源 * @return * Added by Bao guangpu on 2016/4/10 */ public static String saveFile(Context c, String fileName, Bitmap bitmap) { return saveFile(c, "", fileName, bitmap); } /** * 保存位图文件 * @param c 上下文 * @param filePath 保存文件路径 * @param fileName 文件名 * @param bitmap 图片资源 * @return * Added by Bao guangpu on 2016/4/10 */ public static String saveFile(Context c, String filePath, String fileName, Bitmap bitmap) { byte[] bytes = bitmapToBytes(bitmap); return saveFile(c, filePath, fileName, bytes); } /** * 将位图转换为字节数组 * @param bm 图片资源 * @return * Added by Bao guangpu on 2016/4/10 */ public static byte[] bitmapToBytes(Bitmap bm) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(CompressFormat.JPEG, 100, baos); return baos.toByteArray(); } /** * 保存字节数组文件 * @param c 上下文 * @param filePath 保存文件路径 * @param fileName 文件名 * @param bytes 字节数组 * @return * Added by Bao guangpu on 2016/4/10 */ public static String saveFile(Context c, String filePath, String fileName, byte[] bytes) { String fileFullName = ""; FileOutputStream fos = null; String dateFolder = new SimpleDateFormat("yyyyMMdd", Locale.CHINA) .format(new Date()); try { String suffix = ""; if (filePath == null || filePath.trim().length() == 0) { filePath = Environment.getExternalStorageDirectory() + "/JiaXT/" + dateFolder + "/"; } File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } File fullFile = new File(filePath, fileName + suffix); fileFullName = fullFile.getPath(); fos = new FileOutputStream(new File(filePath, fileName + suffix)); fos.write(bytes); } catch (Exception e) { fileFullName = ""; } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { fileFullName = ""; } } } return fileFullName; } }
自己定义ImageView代码:
package com.aiofm.eminem.aiofmbgp.views.controls; /** * 自己定义ImageView * Created by eminem on 2016/4/11. */ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; import com.aiofm.eminem.aiofmbgp.R; public class CircleImage extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; private static final int COLORDRAWABLE_DIMENSION = 1; private static final int DEFAULT_BORDER_WIDTH = 0; private static final int DEFAULT_BORDER_COLOR = Color.BLACK; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius; private boolean mReady; private boolean mSetupPending; public CircleImage(Context context) { super(context); } public CircleImage(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImage(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); super.setScaleType(SCALE_TYPE); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR); a.recycle(); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); } } @Override protected void onDraw(Canvas canvas) { if (getDrawable() == null) { return; } canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public void setBorderColor(int borderColor) { if (borderColor == mBorderColor) { return; } mBorderColor = borderColor; mBorderPaint.setColor(mBorderColor); invalidate(); } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); mBitmap = bm; setup(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); mBitmap = getBitmapFromDrawable(drawable); setup(); } @Override public void setImageResource(int resId) { super.setImageResource(resId); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } private Bitmap getBitmapFromDrawable(Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (OutOfMemoryError e) { return null; } } private void setup() { if (!mReady) { mSetupPending = true; return; } if (mBitmap == null) { return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight()); mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / (float) mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / (float) mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth); mBitmapShader.setLocalMatrix(mShaderMatrix); } }
自己定义选择照片底部弹出对话框代码:
package com.aiofm.eminem.aiofmbgp.views.controls; /** * Created by eminem on 2016/4/11. */ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.PopupWindow; import com.aiofm.eminem.aiofmbgp.R; public class SelectPicPopupWindow extends PopupWindow { private Button takePhotoBtn, pickPhotoBtn, cancelBtn; private View mMenuView; @SuppressLint("InflateParams") public SelectPicPopupWindow(Context context, OnClickListener itemsOnClick) { super(context); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mMenuView = inflater.inflate(R.layout.layout_dialog_pic, null); takePhotoBtn = (Button) mMenuView.findViewById(R.id.takePhotoBtn); pickPhotoBtn = (Button) mMenuView.findViewById(R.id.pickPhotoBtn); cancelBtn = (Button) mMenuView.findViewById(R.id.cancelBtn); cancelBtn.setOnClickListener(itemsOnClick); pickPhotoBtn.setOnClickListener(itemsOnClick); takePhotoBtn.setOnClickListener(itemsOnClick); this.setContentView(mMenuView); this.setWidth(LayoutParams.MATCH_PARENT); this.setHeight(LayoutParams.WRAP_CONTENT); this.setFocusable(true); this.setAnimationStyle(R.style.PopupAnimation); ColorDrawable dw = new ColorDrawable(0x80000000); this.setBackgroundDrawable(dw); mMenuView.setOnTouchListener(new OnTouchListener() { @Override @SuppressLint("ClickableViewAccessibility") public boolean onTouch(View v, MotionEvent event) { int height = mMenuView.findViewById(R.id.pop_layout).getTop(); int y = (int) event.getY(); if (event.getAction() == MotionEvent.ACTION_UP) { if (y < height) { dismiss(); } } return true; } }); } }
设备连接界面部分相关代码:
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_mainview); navigationView.setNavigationItemSelectedListener(this); View headerView = navigationView.getHeaderView(0); avatarImg = (CircleImage) headerView.findViewById(R.id.imageView); avatarImg.setOnClickListener(this);
@Override public void onClick(View v) { switch (v.getId()) { case R.id.imageView: menuWindow = new SelectPicPopupWindow(mContext, itemsOnClick); menuWindow.showAtLocation(findViewById(R.id.drawer_layout), Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0); break; } }
private View.OnClickListener itemsOnClick = new View.OnClickListener() { @Override public void onClick(View v) { menuWindow.dismiss(); switch (v.getId()) { case R.id.takePhotoBtn: Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME))); startActivityForResult(takeIntent, REQUESTCODE_TAKE); break; case R.id.pickPhotoBtn: Intent pickIntent = new Intent(Intent.ACTION_PICK, null); pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(pickIntent, REQUESTCODE_PICK); break; default: break; } } }; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUESTCODE_PICK: try { startPhotoZoom(data.getData()); } catch (NullPointerException e) { e.printStackTrace(); } break; case REQUESTCODE_TAKE: File temp = new File(Environment.getExternalStorageDirectory() + "/" + IMAGE_FILE_NAME); startPhotoZoom(Uri.fromFile(temp)); break; case REQUESTCODE_CUTTING: if (data != null) { setPicToView(data); } break; } super.onActivityResult(requestCode, resultCode, data); } public 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("return-data", true); startActivityForResult(intent, REQUESTCODE_CUTTING); } private void setPicToView(Intent picdata) { Bundle extras = picdata.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); Drawable drawable = new BitmapDrawable(null, photo); urlpath = FileUtil.saveFile(mContext, "temphead.jpg", photo); avatarImg.setImageDrawable(drawable); } }
以上是关于Android开发之裁切(拍照+相冊)图像并设置头像小结的主要内容,如果未能解决你的问题,请参考以下文章
Android实现批量照片上传至server,拍照或者从相冊选择