Android 中实现选择图片生成缩略图点击查看大图的功能
2018-08-28 本文已影响10人
追梦小乐
GIF.gif
0、思路分析
image.png image.png基本思路:
就是通过选择图片,生成保存好2种图片,一个是缩略图,一个是大图,点击相对应的图片,把大图传递过去
1、工具类封装
拍照或者获取图片的工具类:TakePhotoUtils
/**
* 拍照或者从相册获取照片、裁剪等操作工具类
*
* @author pangshulian
* @version 1.0
* @date 2016年9月9日 上午11:35:09
* 20180606 修改key值++100
*/
public class TakePhotoUtils {
/** 拍照 */
public static final int TAKE_PHOTO = 100;
/** 从相册取 */
public static final int CHOOSE_PICTURE = 101;
/** 裁剪大图 */
public static final int CROP_BIG_PICTURE = 102;
/** 裁剪小图 */
public static final int CROP_SMALL_PICTURE = 103;
/** 压缩的原图 */
public static final int CROP_ORIGAL_PICTURE = 104;
private static final String FILE_CONTENT_FILEPROVIDER = "tecsun.jx.yt.phone.fileprovider";
private static TakePhotoUtils mInstance;
/** 存放照片uri */
public File mImageFile;
public TakePhotoUtils() {
// 设置图片路径
String _imageDir = "temp.jpg";
mImageFile = new File(Environment.getExternalStorageDirectory(), _imageDir);
}
public static TakePhotoUtils getInstance() {
if (mInstance == null) {
mInstance = new TakePhotoUtils();
}
return mInstance;
}
/**
* 通过uri生成Bitmap
*
* @param context
* @param uri
* @return
*/
public Bitmap decodeUriAsBitmap(Context context, Uri uri) {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return bitmap;
}
/**
* 拍照 TAKE_PHOTO
*/
public void takePhoto(Context context) {
takePhoto(context);
}
/**
* 拍照 TAKE_PHOTO
*/
public void takePhoto(Context context, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!PermissionsUtils.startRequestPermission((Activity) context, PermissionsUtils.CAMERA_PERMISSIONS, 1)) {
return;
}
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // "android.media.action.IMAGE_CAPTURE"
intent.addCategory("android.intent.category.DEFAULT");
//Android7.0以上URI
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//通过FileProvider创建一个content类型的Uri
Uri uri = FileProvider.getUriForFile(context, FILE_CONTENT_FILEPROVIDER, mImageFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
} else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mImageFile));
}
((Activity) context).startActivityForResult(intent, requestCode);
}
/**
* 拍照
*/
public void takePhoto(Fragment fragment) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!PermissionsUtils.startRequestPermission(fragment.getActivity(), PermissionsUtils.CAMERA_PERMISSIONS, 1)) {
return;
}
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // "android.media.action.IMAGE_CAPTURE"
intent.addCategory("android.intent.category.DEFAULT");
//Android7.0以上URI
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//通过FileProvider创建一个content类型的Uri
Uri uri = FileProvider.getUriForFile(fragment.getContext(), FILE_CONTENT_FILEPROVIDER, mImageFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
} else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mImageFile));
}
fragment.startActivityForResult(intent, TAKE_PHOTO);
}
/**
* 从相册获取
*/
public void pickPhoto(Context context, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!PermissionsUtils.startRequestPermission((Activity) context, PermissionsUtils.WRITE_EXTERNAL_STORAGE_PERMISSIONS, 1)) {
return;
}
}
// 激活系统图库,选择一张图片
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
// 开启一个带有返回值的Activity,请求码为PHOTO_ZOOM
((Activity) context).startActivityForResult(intent, requestCode);
}
/**
* 从相册获取
*/
public void pickPhoto(Context context) {
pickPhoto( context, CHOOSE_PICTURE );
}
/**
* 从相册获取
*/
public void pickPhoto(Fragment fragment) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!PermissionsUtils.startRequestPermission(fragment.getActivity(),
PermissionsUtils.WRITE_EXTERNAL_STORAGE_PERMISSIONS, 1)) {
return;
}
}
// 激活系统图库,选择一张图片
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
// 开启一个带有返回值的Activity,请求码为PHOTO_ZOOM
fragment.startActivityForResult(intent, CHOOSE_PICTURE);
}
/**
* 裁剪图片,使用uri
* 默认高宽比例1:1,自定义高宽尺寸
*/
public void cropImageUri(Context context, Fragment fragment, Uri uri, int outputX, int outputY, int requestCode) {
Intent intent = setCropConfig(context, uri, outputX, outputY);
fragment.startActivityForResult(intent, requestCode);
}
/**
* 设置裁剪配置
*
* @param context
* @param uri
* @param outputX
* @param outputY
* @return
*/
private Intent setCropConfig(Context context, Uri uri, int outputX, int outputY) {
Uri imageUri;
Uri outputUri = null;
Intent intent = new Intent("com.android.camera.action.CROP");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
String url = PhotoUtils.getPath(context, uri);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//通过FileProvider创建一个content类型的Uri
imageUri = FileProvider.getUriForFile(context, FILE_CONTENT_FILEPROVIDER, new File(url));
outputUri = Uri.fromFile(mImageFile);
//TODO:outputUri不需要ContentUri,否则失败
//outputUri = FileProvider.getUriForFile(activity, "com.solux.furniture.fileprovider", new File(crop_image));
} else
{
imageUri = uri;
outputUri = Uri.fromFile(mImageFile);
}
intent.setDataAndType(imageUri, "image/*");
} else {
intent.setDataAndType(uri, "image/*");
outputUri = Uri.fromFile(mImageFile);
}
// intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// 裁剪框的比例,1:1
intent.putExtra("aspectX", 4);
intent.putExtra("aspectY", 5);
// 裁剪后输出图片的尺寸大小
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", true);
// 切图大小不足输出,无黑框
intent.putExtra("scaleUpIfNeeded", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
intent.putExtra("return-data", false);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); // no face detection
return intent;
}
/**
* 裁剪图片,使用uri
* 默认高宽比例1:1,自定义高宽尺寸
*/
public void cropImageUri(Context context, Uri uri, int outputX, int outputY, int requestCode) {
Intent intent = setCropConfig(context, uri, outputX, outputY);
((Activity) context).startActivityForResult(intent, requestCode);
}
/**
* 从相册获取后裁剪小图,不使用uri
* 默认比例1:1,自定义高宽尺寸
*/
public void cropSmallPicture(Context context, int outputX, int outputY) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
intent.putExtra("crop", "true");
// 裁剪框的比例,1:1
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// 裁剪后输出图片的尺寸大小
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());// 图片格式
intent.putExtra("noFaceDetection", true);// 取消人脸识别
intent.putExtra("return-data", true); // 小图不返回数据
// 开启一个带有返回值的Activity,请求码为CROP_SMALL_PICTURE
((Activity) context).startActivityForResult(intent, CROP_SMALL_PICTURE);
}
}
2、选择图片生成缩略图页面
UploadPicGridAdapter
/**
* Created by Administrator on 2018/7/27.
*/
public class UploadPicGridAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater inflater; // 视图容器
public static List<Bitmap> bmp = new ArrayList<Bitmap>();
public UploadPicGridAdapter(Context context,List<Bitmap> bmp) {
inflater = LayoutInflater.from(context);
mContext = context;
this.bmp = bmp;
}
public int getCount() {
return (bmp.size() + 1);
}
public Object getItem(int arg0) {
return null;
}
public long getItemId(int arg0) {
return 0;
}
public void update(){
}
/**
* ListView Item设置
*/
public View getView(final int position, View convertView, ViewGroup parent) {
final int coord = position;
UploadPicGridAdapter.ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_published_grida, parent, false);
holder = new UploadPicGridAdapter.ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.iv_item);
holder.iv_del = (ImageView) convertView.findViewById(R.id.iiv_del);
convertView.setTag(holder);
} else {
holder = (UploadPicGridAdapter.ViewHolder) convertView.getTag();
}
if (position == bmp.size()) {
holder.image.setImageBitmap(BitmapFactory.decodeResource(mContext.getResources(),
R.drawable.icon_addpic_upload));
holder.iv_del.setVisibility(View.GONE);
if (position == 3)
{
holder.image.setVisibility(View.GONE);
}
} else {
holder.image.setImageBitmap(bmp.get(position));
holder.iv_del.setVisibility(View.VISIBLE);
holder.iv_del.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnDelItemPhotoClickListener != null){
mOnDelItemPhotoClickListener.onDelItemPhotoClick(position);
}
}
});
}
return convertView;
}
public interface OnDelItemPhotoClickListener{
void onDelItemPhotoClick(int position);
}
public OnDelItemPhotoClickListener mOnDelItemPhotoClickListener;
public void setOnDelItemPhotoClickListener(OnDelItemPhotoClickListener mOnDelItemPhotoClickListener){
this.mOnDelItemPhotoClickListener = mOnDelItemPhotoClickListener;
}
public class ViewHolder {
public ImageView image;
public ImageView iv_del;
}
}
主逻辑核心代码
//绑定点击事件
mGvPhoto.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
//判断点击的是否是图片
if (arg2 == bmp.size()) {
//显示选择提示窗
TakePhotoUtils.getInstance().pickPhoto(context);
} else {
//进入图片预览页面
EventBus.getDefault().postSticky(new EventMessage(1,origalBmp));
Intent intent = new Intent(context, ShowImageActivity.class);
intent.putExtra("id", arg2); //将当前点击的位置传递过去
context.startActivity(intent); //启动Activity
}
}
});
adapter.setOnDelItemPhotoClickListener(new UploadPicGridAdapter.OnDelItemPhotoClickListener() {
@Override
public void onDelItemPhotoClick(int position) {
if (bmp != null && bmp.size() > 0){
bmp.remove(position);
adapter.notifyDataSetChanged();
}
if (origalBmp != null && origalBmp.size() > 0){
origalBmp.remove(position);
}
}
});
......
@Override
public void onActivityResult(int pRequestCode, int pResultCode, Intent pData) {
Uri uri;
if (pResultCode == Activity.RESULT_OK) {
switch (pRequestCode) {
// 从相册取
case TakePhotoUtils.CHOOSE_PICTURE:
origalUri = pData.getData();
file = BitmapUtils.getFileFromMediaUri(context, origalUri);
newFile = CompressHelper.getDefault(getApplicationContext()).compressToFile(file);
Bitmap photoBmp = null;
try {
// photoBmp = BitmapUtils.getBitmapFormUri(UserFeedbackActivity.this, Uri.fromFile(file));
photoBmp = BitmapFactory.decodeFile(newFile.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
int degree = BitmapUtils.getBitmapDegree(newFile.getAbsolutePath());
/**
* 把图片旋转为正的方向
*/
Bitmap newbitmap = BitmapUtils.rotateBitmapByDegree(photoBmp, degree);
origalBmp.add(newbitmap);
zoomImage(newbitmap,width,width);
// TakePhotoUtils.getInstance().cropImageUri(context, origalUri, width, width, TakePhotoUtils.CROP_BIG_PICTURE);
break;
case TakePhotoUtils.CROP_BIG_PICTURE:
// 剪大图用uri
if (TakePhotoUtils.getInstance().mImageFile != null) {
Bitmap bitmap = TakePhotoUtils.getInstance().decodeUriAsBitmap(context, Uri.fromFile
(TakePhotoUtils.getInstance().mImageFile));
Bitmap image = ImageFactory.ratio(bitmap, width, width);
if (image != null) {
// spath:生成图片取个名字和路径包含类型
String fileName = "image" + System.currentTimeMillis()
+ ".png";
String outPath = context.getFilesDir().getAbsolutePath() + fileName;
try {
ImageFactory.compressAndGenImage(image, outPath, 140);
} catch (IOException e) {
e.printStackTrace();
}
File file = new File(outPath);
bmp.add(image);
adapter.notifyDataSetChanged();
}
}
break;
}
}
super.onActivityResult(pRequestCode, pResultCode, pData);
}
/**
* 缩放图片
* @param bitmap
* @param width
* @param height
*/
private void zoomImage(Bitmap bitmap,int width,int height){
zoomImageBitmap = BitmapUtils.zoomImage(bitmap, width, height);
bmp.add(zoomImageBitmap);
adapter.notifyDataSetChanged();
}
/**
* 让图片按照屏幕3等分
*/
public void Init() {
//初始化控件
mGvPhoto = (GridView) findViewById(R.id.gv_photo);
//设置gridview分割线为透明
mGvPhoto.setSelector(new ColorDrawable(Color.TRANSPARENT));
//初始化适配器
adapter = new UploadPicGridAdapter(UserFeedbackActivity.this,bmp);
//绑定图片数据
mGvPhoto.setAdapter(adapter);
int screenWidth = WindowManagerUtils.getScreenWidth(context);
width = screenWidth/3;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (zoomImageBitmap != null && !zoomImageBitmap.isRecycled()){
zoomImageBitmap.recycle();
}
}
3、ShowImageActivity 大图片展示页面
show_image_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/show_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
MyPagerAdapter .java
public class MyPagerAdapter extends PagerAdapter {
private List<View> list;
public MyPagerAdapter(List<View> list) {
this.list = list;
}
@Override
public int getCount() {
if (list != null && list.size() > 0) {
return list.size();
} else {
return 0;
}
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
container.addView(list.get(position));
return list.get(position);
}
//
// @Override
// public int getItemPosition(Object object) {
// return POSITION_NONE;
// }
}
ShowImageActivity .java
public class ShowImageActivity extends AppCompatActivity {
private ViewPager viewPager; //声明viewpage
private List<View> listViews = null; //用于获取图片资源
private int index = 0; //获取当前点击的图片位置
private MyPagerAdapter adapter; //ViewPager的适配器
private ArrayList<Bitmap> bmp = null;
private int position;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //去除标题栏
setContentView(R.layout.show_image_layout); //绑定布局
inigView();
initData();
}
private void inigView() {
viewPager = (ViewPager) findViewById(R.id.show_view_pager); //绑定viewpager的id
}
private void initData() {
listViews = new ArrayList<View>(); //初始化list
position = getIntent().getIntExtra("id",0);
LogUtils.d("position====================="+position);
}
private void inint() {
if (bmp != null && bmp.size() > 0){
for (int i = 0; i < bmp.size(); i++) { //for循环将试图添加到list中
View view = LayoutInflater.from(getApplicationContext()).inflate(
R.layout.view_pager_item, null); //绑定viewpager的item布局文件
// ImageView iv = (ImageView) view.findViewById(R.id.view_image); //绑定布局中的id
// iv.setImageBitmap(bmp.get(i)); //设置当前点击的图片
SubsamplingScaleImageView iv = (SubsamplingScaleImageView) view.findViewById(R.id.view_image); //绑定布局中的id
iv.setImage(ImageSource.bitmap(bmp.get(i)));
listViews.add(view);
/**
* 图片的长按监听
* */
iv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//弹出提示,提示内容为当前的图片位置
Toast.makeText(ShowImageActivity.this, "这是第" + (index + 1) + "图片", Toast.LENGTH_SHORT).show();
return false;
}
});
}
adapter = new MyPagerAdapter(listViews);
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new PageChangeListener()); //设置viewpager的改变监听
//截取intent获取传递的值
viewPager.setCurrentItem(position); //viewpager显示指定的位置
}
}
/**
* pager的滑动监听
* */
private class PageChangeListener implements OnPageChangeListener {
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int arg0) {
index = arg0;
}
}
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onEventMainThread(EventMessage em) {
LogUtils.d("onEventMainThread=====================");
bmp = (ArrayList<Bitmap>)em.obj;
LogUtils.d("bmp====================="+bmp.size());
int byteCount = bmp.get(0).getByteCount();
LogUtils.d("byteCount====================="+byteCount);
inint(); //初始化
}
@Override
protected void onResume() {
super.onResume();
if (!EventBus.getDefault().isRegistered(this)){
LogUtils.d("EventBus.getDefault().register=====================");
EventBus.getDefault().register(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
view_pager_item.xml
<?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="match_parent"
android:background="@android:color/black">
<!--<ImageView-->
<!--android:layout_centerInParent="true"-->
<!--android:id="@+id/view_image"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--/>-->
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:layout_centerInParent="true"
android:id="@+id/view_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
大图容易引用OOM,引用了一个开源库
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'