Android自定义组件获取本地图片和相机拍照图片

作者:张小贝_ 时间:2022-07-09 21:54:48 

iOS中有封装好的选择图片后长按出现动画删除效果,效果如下 

Android自定义组件获取本地图片和相机拍照图片 

而Android找了很久都没有找到有这样效果的第三方组件,最后懒得找了还是自己实现这效果吧

选择图片后还可对图片进行剪裁 

Android自定义组件获取本地图片和相机拍照图片

当然,代码中还有很多不完善的地方,我接下来会继续完善这个组件的
已经上传到开源社区,欢迎大家来Star啊~

Demo源码:传送门

设计中的碰到的一些问题和解决思路

1.如何让加号图片显示在GridView最后面

首先在调用GridAdapter构造方法时就加载加号图片


/**
* 图片适配器
* @param context 上下文
* @param imagesum 最大可添加图片数
*/
public GridAdapter(Context context, int imagesum) {
this.context = context;
this.imageSum = imagesum;
// 加号图片
mAddBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_add_image);
}

然后在getCount()方法里对图片数据集合加1,在该位置上添加加号图片


@Override
public int getCount() {
// 数据集合加一,在该位置上添加加号
return imageItemData == null ? 0 : imageItemData.size() + 1;
}

最后在getView()方法中,每次显示图片时都对数据集合中的元素数量进行判断,如果数据集合的数量大于position,则表示需要显示加号图片


if (imageItemData != null && imageItemData.size() > position) {
// 正常图片
} else {
// 加号图片
}

这样就能保证加号图片一直在GridView最后一个item上

2.如何显示出删除按钮

在item布局时,在图片的右上角覆盖一层删除按钮,在Adapter中对这个图片的显示和隐藏进行处理


/** 判断是否显示清除按钮 true=显示 */
private boolean showImageClear = false;
//对外提供显示和隐藏的方法
/**
* 设置图片显示状态
* @param clear 图片状态
*/
public void setClearImgShow(boolean clear) {
showImageClear = clear;
}

/**
* 图片显示状态
* @return 状态 true=显示
*/
public boolean getClearImgShow() {
return showImageClear;
}

删除按钮默认不显示,当用户长按图片时就显示出来


// 长按显示删除按钮
mGridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (!(position == gridAdapter.imageItemData.size())) {
// 如果删除按钮已经显示了则不再设置
if (!gridAdapter.getClearImgShow()) {
gridAdapter.setClearImgShow(true);
gridAdapter.notifyDataSetChanged();
}
}
// 返回true,停止事件向下传播
return true;
}
});

这里需要拦截长按点击事件,把返回值设置为true,因为我们还设置了点击事件的监听,如果不拦截事件,那么长按事件结束后还会同时执行单击事件

最后关键的一点,在GridAdapter类中的getView方法里进行控制,通过getClearImgShow方法获取删除图片是否需要显示,如果返回为true则显示出来,并获取动画实例,让图片开始执行动画效果


if (imageItemData != null && imageItemData.size() > position) {
// 正常显示
// 判断是否需要显示删除按钮 ,为true则显示,并执行动画效果
if (getClearImgShow()) {
holder.imgclear.setVisibility(View.VISIBLE);
CustomRotateAnim anim = CustomRotateAnim.getCustomRotateAnim();
anim.setDuration(300);
anim.setRepeatCount(2);
anim.setInterpolator(new LinearInterpolator()); // 设置为匀速
holder.img.startAnimation(anim);
} else {
// 关闭动画,隐藏删除按钮
holder.img.clearAnimation();
holder.imgclear.setVisibility(View.GONE);
}
holder.img.setImageBitmap(PhotoBitmapUtil.getCompressPhoto(imageItemData.get(position)));
} else {
......省略......
}

3.如何设置当图片达到最大数时,隐藏加号按钮

在使用GridAdapter的时候,调用方需要传入一个最大图片数:


gridAdapter = new GridAdapter(MainActivity.this, 8);
mGridView.setAdapter(gridAdapter);

然后在GridAdapter中接收这个最大图片数,并在getView()方法中对加号图片的显示进行管控


if (imageItemData != null && imageItemData.size() > position) {
// 显示选择的图片
......省略......
} else {
// 显示加号按钮
// 图片数达到最大限制时隐藏加号图片
if (imageItemData.size() != imageSum) {
holder.imgclear.setVisibility(View.GONE); // 不显示删除按钮
holder.img.clearAnimation(); // 去除动画
holder.img.setImageBitmap(mAddBitmap);
}
}

“gridAdapter.getCount() - 1”是因为我们在添加加号图片时加了1,所以使用时需要减1


// 点击图片
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 如果单击时删除按钮处在显示状态,则隐藏它
if (gridAdapter.getClearImgShow()) {
 gridAdapter.setClearImgShow(false);
 gridAdapter.notifyDataSetChanged();
} else {
 if (gridAdapter.getCount() - 1 == position) {
 // 判断是否达到了可添加图片最大数
 if (!(gridAdapter.imageItemData.size() == gridAdapter.imageSum)) {
 selectPhoto.showPopupSelect(mGridView);
 }
 } else {
 popupViewGridPhoto(position);
 }
}

}
});

4.如何降低图片加载时的内存消耗量

要在GridView中显示那么多的图片,肯定是需要多图片进行压缩处理的,不然很容易出现OOM错误
这里通过质量压缩,降低加载图片的内存大小


/**
* 把原图按1/5的比例压缩
*
* @param path 原图的路径
* @return 压缩后的图片
*/
public static Bitmap getCompressPhoto(String path) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 5; // 图片的长宽设置为原来的五分之一
Bitmap bmp = BitmapFactory.decodeFile(path, options);
options = null;
return bmp;
}

也可以通过其它的方式,可以参考这篇博客《Android避免内存溢出(Out of Memory)方法总结》

5.如何防止部分手机拍照后图片被旋转的问题

在测试中,部分三星手机拍摄完照片后会把图片旋转90度,这个设计实在是坑,为此还得专门为了这个问题进行处理,每次拍摄完照片后都要获取图片的旋转角度,如果图片被旋转了的话就再旋转回去
可以参考这篇博客
《Android 解决部分手机拍照后获取的图片被旋转的问题》

6.如何让图片左右摇摆

想要实现图片左右摇摆的效果,需要我们自定义Animation
可参看这篇博客
《Android 自定义Animation实现View摇摆效果》

这里就先介绍这么多,详细的解释代码注释中都有的,就不再多说啦

标签:Android,本地图片,拍照图片
0
投稿

猜你喜欢

  • Java设计模式之观察者模式_动力节点Java学院整理

    2022-01-14 12:27:47
  • C# 对象映射的高性能方案

    2021-09-22 08:03:19
  • OpenCV实现直线拟合

    2023-06-22 15:22:37
  • Android开发之绘制平面上的多边形功能分析

    2023-12-13 13:31:57
  • Compose 的 Navigation组件使用示例详解

    2023-02-12 12:43:43
  • SpringBoot注册FilterRegistrationBean相关情况讲解

    2022-04-24 01:22:59
  • Java编程基本概念

    2023-09-07 07:15:50
  • 解决idea每次新建项目都需要重新指定maven目录

    2022-12-25 17:39:52
  • 详解LINQ入门(上篇)

    2023-10-15 05:57:30
  • Android实现带数字的圆形进度条(自定义进度条)

    2023-07-19 21:37:20
  • SpringBoot中自定义注解实现参数非空校验的示例

    2022-04-12 10:55:55
  • Java 高并发的三种实现案例详解

    2023-12-16 10:57:30
  • Android实现沉浸式状态栏功能

    2022-10-25 23:19:36
  • Java数据结构之线性表

    2022-08-21 06:32:28
  • Java中&和&&的区别简单介绍

    2023-02-23 12:12:23
  • Android实现通话自动录音

    2021-08-29 20:33:35
  • C# 位图BitArray的使用

    2022-09-13 23:54:46
  • Android悬浮对话框(即点即关对话框)实现代码

    2023-01-01 04:53:54
  • JVM中的flag设置详解

    2022-08-11 01:37:20
  • Java中this和super的区别及this能否调用到父类使用

    2023-01-05 12:03:13
  • asp之家 软件编程 m.aspxhome.com