最近由于项目的需要,要求用户可以上传自己拍的照片和图库中的已有照片,这是一个App比较基础性的功能,就索性将整个功能抽出来写成一个组件,以方面其它的App再实现此功能时可直接拿来使用.
话不多说,先看一下效果图,弹出选择方式window :
点击:Select from gallery,从本地机册中选择图片,如图:
点击:Take a photot就不再上传截图了.
下面将实现的主要代码出,如有需要可稍做修改即可做为一个组件使用,以下没布局文件.
public class TakePhoto
{
protected Activity mActivity;
protected Intent mIntent = null;
protected static final int PHOTO_REQUEST_TAKEPHOTO = 0x00000001;
protected static final int PHOTO_REQUEST_CUT = 0x00000002;
protected Uri currentUri = null;
protected TakePhotoListener mTakePhotoListener;
protected View mDisplayView;
private String sdcardPath = null;
private String fileBasePath = null;
private int aspectX = 1;
private int aspectY = 1;
private int outputX = 480;
private int outputY = 480;
public TakePhoto(Activity activity, View displayView, TakePhotoListener takePhotoListener)
{
this.mActivity = activity;
this.mDisplayView = displayView;
this.mTakePhotoListener = takePhotoListener;
initLocalFilePath(mActivity);
startSelectImage();
}
public TakePhoto(Activity activity, View displayView, int aspectX, int aspectY, int outputX, int outputY,
TakePhotoListener takePhotoListener)
{
this.mActivity = activity;
this.mDisplayView = displayView;
this.aspectX = aspectX;
this.aspectY = aspectY;
this.outputX = outputX;
this.outputY = outputY;
this.mTakePhotoListener = takePhotoListener;
initLocalFilePath(mActivity);
startSelectImage();
}
private void initLocalFilePath(Activity activity)
{
sdcardPath = activity.getExternalCacheDir().toString() + "/capturePicture/";
fileBasePath = "file://" + sdcardPath;
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch (requestCode)
{
case PHOTO_REQUEST_CUT:
try
{
setDisplayViewImage();
}
catch (FileNotFoundException e)
{
mTakePhotoListener.onFail(TakePhotoFailReason.FileNotFound);
}
catch (OutOfMemoryError e)
{
mTakePhotoListener.onFail(TakePhotoFailReason.OutOfMemory);
}
break;
}
}
protected void startSelectImage()
{
}
protected Uri getCurrentUri()
{
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat("'IMG'_yyyyMMdd_HHmmss");
Log.i("------currentImageUri--------", fileBasePath + dateFormat.format(date) + ".jpg");
return Uri.parse(fileBasePath + dateFormat.format(date) + ".jpg");
}
protected void cropImageUri(Uri uri)
{
try
{
// ���òü�
mIntent.putExtra("crop", "true");
// aspectX aspectY �ǿ�ߵı���
mIntent.putExtra("aspectX", aspectX);
mIntent.putExtra("aspectY", aspectY);
// outputX outputY �Dzü�ͼƬ���
mIntent.putExtra("outputX", outputX);
mIntent.putExtra("outputY", outputY);
mIntent.putExtra("scale", true);
mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
mIntent.putExtra("return-data", false);
mIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
mIntent.putExtra("noFaceDetection", true); // no face detection
mActivity.startActivityForResult(mIntent, PHOTO_REQUEST_CUT);
}
catch (ActivityNotFoundException e)
{
mTakePhotoListener.onFail(TakePhotoFailReason.ActivityNotFound);
}
}
protected void setDisplayViewImage() throws FileNotFoundException
{
if (currentUri != null)
{
Bitmap bitmap = BitmapFactory.decodeFile(currentUri.getPath());
if (bitmap == null)
{
throw new FileNotFoundException();
}
if (mDisplayView instanceof ImageView)
{
((ImageView) mDisplayView).setImageBitmap(bitmap);
}
else
{
Drawable drawable = new BitmapDrawable(mActivity.getResources(), bitmap);
mDisplayView.setBackgroundDrawable(drawable);
}
mTakePhotoListener.onSuccess(currentUri.getPath(), mDisplayView, bitmap);
}
}
protected boolean existSDCard()
{
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
return true;
}
else return false;
}
protected void createPhotoDir()
{
File file = new File(sdcardPath);
if (!file.exists())
{
file.mkdirs();
}
}
public interface TakePhotoListener
{
public void onSuccess(String imagePath, View displayView, Bitmap bitmap);
public void onFail(TakePhotoFailReason failReason);
}
public enum TakePhotoFailReason
{
ActivityNotFound, FileNotFound, OutOfMemory, SDCardNotFound
}
}
//TakePhoto子类,实现从相机拍照生成图片
package com.focustech.capturepicture;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
import android.view.View;
public class CameraTakePhoto extends TakePhoto
{
/**
* 构造方法
* @param activity 页面对象
* @param displayView 图片显示对象
* @param takePhotoListener 图片回调
*/
public CameraTakePhoto(Activity activity, View displayView, TakePhotoListener takePhotoListener)
{
super(activity, displayView, takePhotoListener);
}
/**
* 构造方法
* @param activity 页面对象
* @param displayView 图片显示对象
* @param aspectX 裁剪宽比例
* @param aspectY 裁剪高比例
* @param outputX 裁剪宽度
* @param outputY 裁剪高度
* @param takePhotoListener 图片回调
*/
public CameraTakePhoto(Activity activity, View displayView, int aspectX, int aspectY, int outputX, int outputY,
TakePhotoListener takePhotoListener)
{
super(activity, displayView, aspectX, aspectY, outputX, outputY, takePhotoListener);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode != Activity.RESULT_OK)
{
return;
}
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode)
{
case PHOTO_REQUEST_TAKEPHOTO:
cropCurrentImage(currentUri);
break;
}
}
private void cropCurrentImage(Uri currentUri)
{
mIntent = new Intent("com.android.camera.action.CROP");
mIntent.setDataAndType(currentUri, "image/*");
cropImageUri(currentUri);
}
@Override
protected void startSelectImage()
{
try
{
if (existSDCard())
{
createPhotoDir();
currentUri = getCurrentUri();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, currentUri);
mActivity.startActivityForResult(intent, PHOTO_REQUEST_TAKEPHOTO);
}
else
{
mTakePhotoListener.onFail(TakePhotoFailReason.SDCardNotFound);
}
}
catch (ActivityNotFoundException e)
{
mTakePhotoListener.onFail(TakePhotoFailReason.ActivityNotFound);
}
}
}
//TakePhoto子类,实现从本地图册中选择图片
public class GalleryTakePhoto extends TakePhoto
{
/**
* 构造方法
* @param activity 页面对象
* @param displayView 图片显示对象
* @param takePhotoListener 图片回调
*/
public GalleryTakePhoto(Activity activity, View displayView, TakePhotoListener takePhotoListener)
{
super(activity, displayView, takePhotoListener);
}
/**
* 构造方法
* @param activity 页面对象
* @param displayView 图片显示对象
* @param aspectX 裁剪宽比例
* @param aspectY 裁剪高比例
* @param outputX 裁剪宽度
* @param outputY 裁剪高度
* @param takePhotoListener 图片回调
*/
public GalleryTakePhoto(Activity activity, View displayView, int aspectX, int aspectY, int outputX, int outputY,
TakePhotoListener takePhotoListener)
{
super(activity, displayView, aspectX, aspectY, outputX, outputY, takePhotoListener);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode != Activity.RESULT_OK)
{
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void startSelectImage()
{
if (existSDCard())
{
createPhotoDir();
currentUri = getCurrentUri();
mIntent = new Intent(Intent.ACTION_GET_CONTENT);
mIntent.setType("image/*");
cropImageUri(currentUri);
}
else
{
mTakePhotoListener.onFail(TakePhotoFailReason.SDCardNotFound);
}
}
}
测试Activity...
package com.focustech.capturepicture;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RelativeLayout;
import com.focustech.capturepicture.TakePhoto.TakePhotoFailReason;
import com.focustech.capturepicture.TakePhoto.TakePhotoListener;
public class TestActivity extends Activity implements OnClickListener
{
private RelativeLayout img_btn;
private Button btn1;
private Button btn2;
private TakePhoto takePhoto;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
// ��ʼ���ؼ�
private void init()
{
img_btn = (RelativeLayout) findViewById(R.id.img_btn);
btn1 = (Button) findViewById(R.id.btn1);
btn2 = (Button) findViewById(R.id.btn2);
// ΪImageButton��Button��Ӽ����¼�
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
}
// ����¼�
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.btn1:
// ������õ�Activity,��ʾ�ؼ�����,��ȡͼƬ�ص�
takePhoto = new CameraTakePhoto(this, img_btn, listener);
break;
case R.id.btn2:
takePhoto = new GalleryTakePhoto(this, img_btn, listener);
break;
}
}
private TakePhotoListener listener = new TakePhotoListener()
{
@Override
public void onSuccess(String imagePath, View displayView, Bitmap bitmap)
{
//���ݴ���Ŀؼ�ID����
switch (displayView.getId())
{
case R.id.img_btn:
Log.e("==========onSuccess=============", imagePath);
break;
}
}
@Override
public void onFail(TakePhotoFailReason failReason)
{
Log.e("=======onFail===========", failReason.toString());
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (takePhoto != null)
{
takePhoto.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
}
}
思路:其实功能是没有什么复杂的,就是调用系统功能去实现自己想要的功能,主要想表达的一点就是组件化的编程,好处是非常之多的,只要一次编写,以后就可以直接拿来用了,也正是体现了Java封装的强大之处.组件整个工程上传到了我的资源里,有需要的请下载。