Android拍照+擷取+相簿獲取擷取圖片+水印功能【完整】
1 拍照擷取
原理就是通過intent呼叫系統的相機,拍完照後再回調進行操作,成功獲取到拍完照的圖片根據uri呼叫系統的裁剪頁面,裁剪完也是在回撥中進行處理,顯示在頁面的imageview中。
2 相簿選取圖片擷取
原理也是通過intent開啟系統的圖片,使用者選擇完成以後在回撥中根據圖片的uri呼叫系統的裁剪頁面,裁剪後在回撥中進行處理並顯示在本頁面的控制元件中。
3 下面進行程式碼展示
佳姝1:在Xml佈局檔案中
<LinearLayout android:id="@+id/main_ll" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal"> <!--這個是自定義類CircleImageView它繼承於ImageView--> <com.example.dashixu_day2_a.CircleImageView android:id="@+id/main_icon" android:layout_width="120dp" android:layout_height="120dp" android:layout_marginTop="20dp" android:src="@mipmap/ic_launcher"/> <Button android:id="@+id/main_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="更換頭像"/> </LinearLayout>
佳姝2:在MainActivity中
public class MainActivity extends AppCompatActivity { //定義變數值 private CircleImageView main_icon; private Button main_btn; private PopWindow mpopWindow; private static final int REQUEST_IMAGE_GET = 0; private static final int REQUEST_IMAGE_CAPTURE = 1; private static final int REQUEST_SMALL_IMAGE_CUTTING = 2; private static final int REQUEST_BIG_IMAGE_CUTTING = 3; private static final String IMAGE_FILE_NAME = "icon.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化控制元件及在拍照和相簿選擇的按鈕中處理點選事件 initView(); } //繪製水印監聽關鍵程式碼(在Fragment使用同理) private Bitmap createWatermark(Bitmap bitmap, String mark) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bmp); Paint p = new Paint(); // 水印顏色 p.setColor(Color.parseColor("#c5576370")); // 水印字型大小 p.setTextSize(40); //抗鋸齒 p.setAntiAlias(true); //繪製圖像 canvas.drawBitmap(bitmap, 0, 0, p); //繪製文字 canvas.drawText(mark, 0, h / 2, p); canvas.save(Canvas.ALL_SAVE_FLAG); canvas.restore(); return bmp; } private void initView() { main_icon = (CircleImageView) findViewById(R.id.main_icon); main_btn = (Button) findViewById(R.id.main_btn); main_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mpopWindow = new PopWindow(MainActivity.this, new View.OnClickListener() { @Override public void onClick(View v) { //相簿處理 mpopWindow.dismiss(); Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); // 判斷系統中是否有處理該 Intent 的 Activity if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_IMAGE_GET); } else { Toast.makeText(MainActivity.this, "未找到圖片檢視器", Toast.LENGTH_SHORT).show(); } } }, new View.OnClickListener() { @Override public void onClick(View v) { //拍照處理 mpopWindow.dismiss(); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME))); startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } }); View rootView = LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_main, null); mpopWindow.showAtLocation(rootView, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0); } }); } //處理點選回撥的監聽事件 public void onActivityResult(int requestCode, int resultCode, Intent data) { // 回撥成功 if (resultCode == RESULT_OK) { switch (requestCode) { // 小圖切割 case REQUEST_SMALL_IMAGE_CUTTING: if (data != null) { setPicToView(data); } break; // 相簿選取 case REQUEST_IMAGE_GET: try { startSmallPhotoZoom(data.getData()); } catch (NullPointerException e) { e.printStackTrace(); } break; // 拍照 case REQUEST_IMAGE_CAPTURE: File temp = new File(Environment.getExternalStorageDirectory() + "/" + IMAGE_FILE_NAME); startSmallPhotoZoom(Uri.fromFile(temp)); break; } } } //裁剪圖片的方法 private void startSmallPhotoZoom(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("scale", true); intent.putExtra("return-data", true); startActivityForResult(intent, REQUEST_SMALL_IMAGE_CUTTING); } //顯示裁剪後的圖片 private void setPicToView(Intent data) { Bundle extras = data.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); // 直接獲得記憶體中儲存的 bitmap // 建立 smallIcon 資料夾 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { String storage = Environment.getExternalStorageDirectory().getPath(); File dirFile = new File(storage + "/smallIcon"); if (!dirFile.exists()) { if (!dirFile.mkdirs()) { Log.e("TAG", "資料夾建立失敗"); } else { Log.e("TAG", "資料夾建立成功"); } } File file = new File(dirFile, System.currentTimeMillis() + ".jpg"); // 儲存圖片 FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file); photo.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); outputStream.flush(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } // 在檢視中顯示圖片(原圖顯示) // main_icon.setImageBitmap(photo); // 在檢視中顯示圖片(水印顯示) Bitmap bitmap = createWatermark(photo, "來自四川的小仙女"); main_icon.setImageBitmap(bitmap); } }
佳姝3:自定義類PopoWindow繼承PopupWindow
import android.app.Activity; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.PopupWindow; public class PopWindow extends PopupWindow { private View mView; // PopupWindow 選單佈局 private Context mContext; private View.OnClickListener mSelectListener; // 相簿選取的點選監聽器 private View.OnClickListener mCaptureListener; // 拍照的點選監聽器 private Button icon_btn_camera; private Button icon_btn_select; private Button icon_btn_cancel; public PopWindow(Activity context, View.OnClickListener selectListener, View.OnClickListener captureListener) { super(context); this.mContext = context; this.mSelectListener = selectListener; this.mCaptureListener = captureListener; initView(); } private void initView() { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE); mView = inflater.inflate(R.layout.layout_pop_xml, null); icon_btn_camera = (Button) mView.findViewById(R.id.icon_btn_camera); icon_btn_select = (Button) mView.findViewById(R.id.icon_btn_select); icon_btn_cancel = (Button) mView.findViewById(R.id.icon_btn_cancel); icon_btn_camera.setOnClickListener(mCaptureListener); icon_btn_select.setOnClickListener(mSelectListener); icon_btn_cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); this.setContentView(mView); // 設定動畫 this.setAnimationStyle(R.style.popwindow_anim_style); this.setWidth(WindowManager.LayoutParams.MATCH_PARENT); this.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); // 設定可觸 this.setFocusable(true); ColorDrawable dw = new ColorDrawable(0x0000000); this.setBackgroundDrawable(dw); // 單擊彈出窗以外處 關閉彈出窗 mView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int height = mView.findViewById(R.id.ll_pop).getTop(); int y = (int) event.getY(); if (event.getAction() == MotionEvent.ACTION_UP) { if (y < height) { dismiss(); } } return true; } }); } }
佳姝4:在PupupWindow佈局中layout_pop_xml.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#66000000">
<LinearLayout
android:id="@+id/ll_pop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/icon_btn_camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_item2"
android:textColor="@color/colorMainGreen"
android:text="拍照"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#fff"/>
<Button
android:id="@+id/icon_btn_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_item3"
android:textColor="@color/colorMainGreen"
android:text="從相簿選擇"/>
<Button
android:id="@+id/icon_btn_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="15dp"
android:background="@drawable/shape_item1"
android:textColor="@color/colorMainGreen"
android:text="取消"/>
</LinearLayout>
</RelativeLayout>
@drawable/
shape_item1:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white"/>
<corners android:radius="10dp"/>
<stroke android:width="0dp" android:color="@android:color/white"></stroke></shape>
@drawable/
shape_item2:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp" />/>
<stroke
android:width="0dp"
android:color="@android:color/white"></stroke></shape>
@drawable/
shape_item3:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />/>
<stroke
android:width="0dp"
android:color="@android:color/white"></stroke></shape>
佳姝5:自定義類CircleImageView繼承ImageView
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.ImageView;
@SuppressLint("AppCompatCustomView")
public class CircleImageView extends ImageView {
private Paint mpaint; //畫筆
private int mreadius; //圓形圖片的半徑
private float mscale; //圖片的縮放比例
public CircleImageView(Context context) {
super(context);
}
public CircleImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//圓形圖片的半徑,寬高保持一致
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
int size=Math.min(getMeasuredWidth(),getMeasuredHeight());
mreadius=size/2;
setMeasuredDimension(size,size);
}
//畫筆
@Override
protected void onDraw(Canvas canvas) {
mpaint=new Paint();
Bitmap bitmap=drawableToBitmap(getDrawable());
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mscale=(mreadius * 2.0f)/Math.min(bitmap.getHeight(),bitmap.getWidth());
Matrix matrix = new Matrix();
matrix.setScale(mscale,mscale);
bitmapShader.setLocalMatrix(matrix);
mpaint.setShader(bitmapShader);
canvas.drawCircle(mreadius,mreadius,mreadius,mpaint);
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
}
佳姝6:res/anim/popup_gone.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
res/anim/popup_show.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
佳姝7:values/colors中
<color name="colorMainGreen">#40cab3</color>
values/styles中
<style name="popwindow_anim_style">
<item name="android:windowEnterAnimation">@anim/popup_show</item>
<item name="android:windowExitAnimation">@anim/popup_gone</item>
</style>
程式碼挺全的,這也方便我做筆記嘿嘿,雖然過程比較簡單,但可能會有一些判斷的地方沒有處理,如果有不對的地方希望有高手可以幫忙改進,謝謝~~