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

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

而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摇摆效果》

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义照相机详解

    几乎每个APP都会用的相机功能,下面小编把内容整理分享到我们平台,供大家参考,感兴趣的朋友一起学习吧! 启动相机的两种方式 1.直接启动系统相机 <code class="hljs avrasm"> Intent intent = new Intent(); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); startActivity(intent);</code> 或者指定返回图片的名称mCurrentPho

  • Android实用控件自定义逼真相机光圈View

    最近手机界开始流行双摄像头,大光圈功能也应用而生.所谓大光圈功能就是能够对照片进行后期重新对焦,其实现的原理主要是对拍照期间获取的深度图片与对焦无穷远的图像通过算法来实现重新对焦的效果. 在某双摄手机的大光圈操作界面有个光圈的操作图标,能够模拟光圈调节时的真实效果,感觉还不错,于是想着实现该效果.现在把我的实现方法贡献给大家,万一你们公司也要做双摄手机呢?( ̄┰ ̄*) 首先,百度一下光圈图片,观察观察,就可以发现其关键在于计算不同的光圈值时各个光圈叶片的位置.为了计算简便,我以六个直边叶片的光圈

  • Android中关于自定义相机预览界面拉伸问题

    关于自定义相机预览界面拉伸问题 1.导致主要变形的原因是Camera预览界面旋转的角度和摄像头挂载的角度不同导致的 2.我们的Activity设置的方向是竖屏,这是手机的自然方向 所以宽比高短 3.角度:所谓屏幕和摄像头的角度,指的是相对于自然方向旋转过的角度,根据旋转角度即可获知当前的方向 4.假如说:手机是竖屏的情况下, 自然角度为0,但是Camera逆时针旋转90度,那咱们设置顺时针旋转90度,就正常 .手机是横屏的情况下Camera返回为0度 ,如果设置顺时针旋转90度,就回旋转 怎么设

  • Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="m

  • Android 自定义相机及分析源码

    Android 自定义相机及分析源码 使用Android 系统相机的方法: 要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下 <intent-filter> <action android:name="android.intent.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" />

  • Android自定义相机实现自动对焦和手动对焦

    Android自定义相机实现自动对焦和手动对焦: 不调用系统相机,因为不同的机器打开相机呈现的界面不统一也不能满足需求. 所以为了让程序在不同的机器上呈现出统一的界面,并且可以根据需求进行布局,做了此demo. 程序实现代码如下: import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.la

  • Android自定义相机界面的实现代码

    我们先实现拍照按钮的圆形效果哈,Android开发中,当然可以找美工人员设计图片,然后直接拿进来,不过我们可以自己写代码实现这个效果哈,最常用的的是用layout-list实现图片的叠加,我们这个layout命名为btn_take_photo.xml,这是一个自定义的drawable文件,所以按照规范,我们要将它放在drawable文件夹里. 注意:drawable文件夹一般是来放自定义的drawable文件的,可以将它看成自己写的背景样式等等哦 解释代码: layer-list里面放3个ite

  • Android自定义照相机倒计时拍照

    自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: 两个TextView是用来显示提示信息和倒计时的秒数的 相关教程:Android开发从相机或相册获取图片裁剪 Android启动相机拍照并返回图片 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools&qu

  • Android自定义照相机Camera出现黑屏的解决方法

    本文实例讲述了Android自定义照相机Camera出现黑屏的解决方法.分享给大家供大家参考,具体如下: 对于一些手机,像HTC,当自定义Camera时,调用Camera.Parameters的 parameters.setPreviewSize(width, height)方法时,如果width和height为奇数情况下,则会出现黑屏现象,解决办法可参考SDK提供的ApiDemos中关于Camera的 例子: List<Size> sizes = parameters.getSupporte

  • Android 用 camera2 API 自定义相机

    前言 笔者因为项目需要自定义相机,所以了解了一下 Android 关于 camera 这块的 API.Android SDK 21(LOLLIPOP) 开始已经弃用了之前的 Camera 类,提供了 camera2 相关 API,目前网上关于 camera2 API 介绍的资料比较少,笔者搜集网上资料,结合自己的实践,在这里做一个总结. 流程 因为 camera2 提供的接口比较多,虽然很灵活,但是也增加了使用的复杂度.首先来大致了解一下调用 camera2 的流程,方便我们理清思路. 要显示相

随机推荐