图片大图预览
在我现在的项目当中,也存在大图预览的功能,但其实现过于繁重,采用一个Activity实现,并且在图片展示的过程中会产生卡顿感,整体感觉很是不好,正巧项目也在重构过程中,所以决定将这一功能写成一个成型的控件。
话不多说,先上图看下效果。
整体实现思路
图片展示:PhotoView(大图支持双击放大)
图片加载:Glide(加载网络图片、本地图片、资源文件)
小图变大图时的实现:动画
图片的下载:插入系统相册
该控件采用自定义View的方式,通过一些基本的控件的组合,来形成一个具有大图预览的控件。上代码
使用方法
(1)在布局文件中引用该view
<com.demo.gallery.view.GalleryView android:id="@+id/photo_gallery_view" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" app:animDuration="300" app:saveText="保存至相册" app:saveTextColor="#987622"/>
(2)具体使用方法
GalleryView galleryView = findViewById(R.id.photo_gallery_view); galleryView.showPhotoGallery(index, List, ImageView);
到这里就结束了,就是这么简单!
具体实现
(1)先从showPhotoGallery(index, List, ImageView)这个方法讲起
int index:我们想要展示的一个图片列表中的第几个
List list: 我们要传入的要展示的图片类型list(支持网络图片、资源图片、本地图片(本地图片与网络图片其实都是一个字符串地址))
public class GalleryPhotoModel { public Object photoSource; public GalleryPhotoModel(@DrawableRes int drawableRes) { this.photoSource = drawableRes; } public GalleryPhotoModel(String path) { this.photoSource = path; } }
ImageView:即你点击想要展示的那个图片
(2)对传入GalleryView的数据进行处理
/** * @param index 想要展示的图片的索引值 * @param photoList 图片集合(URL、Drawable、Bitmap) * @param clickImageView 点击的第一个图片 */ public void showPhotoGallery(int index, List<GalleryPhotoModel> photoList, ImageView clickImageView) { GalleryPhotoParameterModel photoParameter = new GalleryPhotoParameterModel(); //图片 photoParameter.photoObj = photoList.get(index).photoSource; //图片在list中的索引 photoParameter.index = index; int[] locationOnScreen = new int[2]; //图片位置参数 clickImageView.getLocationOnScreen(locationOnScreen); photoParameter.locOnScreen = locationOnScreen; //图片的宽高 int width = clickImageView.getDrawable().getBounds().width(); int height = clickImageView.getDrawable().getBounds().height(); photoParameter.imageWidth = clickImageView.getWidth(); photoParameter.imageHeight = clickImageView.getHeight(); photoParameter.photoHeight = height; photoParameter.photoWidth = width; //scaleType photoParameter.scaleType = clickImageView.getScaleType(); //将第一个点击的图片参数连同整个图片列表传入 this.setVisibility(View.VISIBLE); post(new Runnable() { @Override public void run() { requestFocus(); } }); setGalleryPhotoList(photoList, photoParameter); }
通过传递进来的ImageView,获取被点击View参数,并拼装成参数model,再进行数据的相关处理。
(3)GalleryView的实现机制
该View的实现思路主要是:最外层是一个RelativeLayout,内部有一个充满父布局的ImageView和ViewPager。ImageView用来进行图片的动画缩放,ViewPager用来进行最后的图片的展示。其实该View最主要的地方就是通过点击ImageView到最后ViewPager的展示的动画。接下来主要是讲解一下这个地方。先看一下被点击ImageView的参数Model。GalleryPhotoParameterModel
public class GalleryPhotoParameterModel { //索引 public int index; // 图片的类型 public Object photoObj; // 在屏幕上的位置 public int[] locOnScreen = new int[]{-1, -1}; // 图片的宽 public int photoWidth = 0; // 图片的高 public int photoHeight = 0; // ImageView的宽 public int imageWidth = 0; // ImageView的高 public int imageHeight = 0; // ImageView的缩放类型 public ImageView.ScaleType scaleType; }
3.1图片放大操作
private void handleZoomAnimation() { // 屏幕的宽高 this.mScreenRect = GalleryScreenUtil.getDisplayPixes(getContext()); //将被缩放的图片放在一个单独的ImageView上进行单独的动画处理。 Glide.with(getContext()).load(firstClickItemParameterModel.photoObj).into(mScaleImageView); //开启动画 mScaleImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //开始放大操作 calculateScaleAndStartZoomInAnim(firstClickItemParameterModel); // mScaleImageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); }
/** * 计算放大比例,开启放大动画 * * @param photoData */ private void calculateScaleAndStartZoomInAnim(final GalleryPhotoParameterModel photoData) { mScaleImageView.setVisibility(View.VISIBLE); // 放大动画参数 int translationX = (photoData.locOnScreen[0] + photoData.imageWidth / 2) - (int) (mScreenRect.width() / 2); int translationY = (photoData.locOnScreen[1] + photoData.imageHeight / 2) - (int) ((mScreenRect.height() + GalleryScreenUtil.getStatusBarHeight(getContext())) / 2); float scale = getImageViewScale(photoData); // 开启放大动画 executeZoom(mScaleImageView, translationX, translationY, scale, true, new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { showOtherViews(); tvPhotoSize.setText(String.format("%d/%d", viewPager.getCurrentItem() + 1, photoList.size())); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); }
3.2 图片缩小操作
/** * 计算缩小比例,开启缩小动画 */ private void calculateScaleAndStartZoomOutAnim() { hiedOtherViews(); // 缩小动画参数 int translationX = (firstClickItemParameterModel.locOnScreen[0] + firstClickItemParameterModel.imageWidth / 2) - (int) (mScreenRect.width() / 2); int translationY = (firstClickItemParameterModel.locOnScreen[1] + firstClickItemParameterModel.imageHeight / 2) - (int) ((mScreenRect.height() + GalleryScreenUtil.getStatusBarHeight(getContext())) / 2); float scale = getImageViewScale(firstClickItemParameterModel); // 开启缩小动画 executeZoom(mScaleImageView, translationX, translationY, scale, false, new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { mScaleImageView.setImageDrawable(null); mScaleImageView.setVisibility(GONE); setVisibility(GONE); } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }); }
3.3 计算图片缩放的比例
private float getImageViewScale(GalleryPhotoParameterModel photoData) { float scale; float scaleX = photoData.imageWidth / mScreenRect.width(); float scaleY = photoData.photoHeight * 1.0f / mScaleImageView.getHeight(); // 横向图片 if (photoData.photoWidth > photoData.photoHeight) { // 图片的宽高比 float photoScale = photoData.photoWidth * 1.0f / photoData.photoHeight; // 执行动画的ImageView宽高比 float animationImageScale = mScaleImageView.getWidth() * 1.0f / mScaleImageView.getHeight(); if (animationImageScale > photoScale) { // 动画ImageView宽高比大于图片宽高比的时候,需要用图片的高度除以动画ImageView高度的比例尺 scale = scaleY; } else { scale = scaleX; } } // 正方形图片 else if (photoData.photoWidth == photoData.photoHeight) { if (mScaleImageView.getWidth() > mScaleImageView.getHeight()) { scale = scaleY; } else { scale = scaleX; } } // 纵向图片 else { scale = scaleY; } return scale; }
3.4 执行动画的缩放
/** * 执行缩放动画 * @param scaleImageView * @param translationX * @param translationY * @param scale * @param isEnlarge */ private void executeZoom(final ImageView scaleImageView, int translationX, int translationY, float scale, boolean isEnlarge, Animator.AnimatorListener listener) { float startTranslationX, startTranslationY, endTranslationX, endTranslationY; float startScale, endScale, startAlpha, endAlpha; // 放大 if (isEnlarge) { startTranslationX = translationX; endTranslationX = 0; startTranslationY = translationY; endTranslationY = 0; startScale = scale; endScale = 1; startAlpha = 0f; endAlpha = 0.75f; } // 缩小 else { startTranslationX = 0; endTranslationX = translationX; startTranslationY = 0; endTranslationY = translationY; startScale = 1; endScale = scale; startAlpha = 0.75f; endAlpha = 0f; } //-------缩小动画-------- AnimatorSet set = new AnimatorSet(); set.play( ObjectAnimator.ofFloat(scaleImageView, "translationX", startTranslationX, endTranslationX)) .with(ObjectAnimator.ofFloat(scaleImageView, "translationY", startTranslationY, endTranslationY)) .with(ObjectAnimator.ofFloat(scaleImageView, "scaleX", startScale, endScale)) .with(ObjectAnimator.ofFloat(scaleImageView, "scaleY", startScale, endScale)) // ---Alpha动画--- // mMaskView伴随着一个Alpha减小动画 .with(ObjectAnimator.ofFloat(maskView, "alpha", startAlpha, endAlpha)); set.setDuration(animDuration); if (listener != null) { set.addListener(listener); } set.setInterpolator(new DecelerateInterpolator()); set.start(); }
改View的主要实现如上,在图片进行缩放的时候,要考虑的情况:短边适配、图片原尺寸的宽高、展示图片的ImageView的宽高比、横竖屏时屏幕的尺寸。在此非常感谢震哥的帮助、抱拳了!老铁。如有更多想法的小伙伴。
请移步我的github GalleryView地址
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。
本文向大家介绍Android Kotlin仿微信头像裁剪图片的方法示例,包括了Android Kotlin仿微信头像裁剪图片的方法示例的使用技巧和注意事项,需要的朋友参考一下 0.前言 最近突发了很多事情,又跟康仔跳票了,无可奈何,不好意思了。最近生活上有很多感悟,一个男人的牛逼就在于平衡工作,学习和家庭,这个点很难把握,既要保证家庭和睦,又要保证自己价值的实现从而避免堕入平庸,每个人的状况都是不
本文向大家介绍PHP仿微信多图片预览上传实例代码,包括了PHP仿微信多图片预览上传实例代码的使用技巧和注意事项,需要的朋友参考一下 生产图片区域,上传按钮#btn可替换自己想要的图片 plupload上传 ajax删除上传的图片 本文为原创文章,如需转载,请注明来源sucaihuo.com并保留原文链接:http://www.sucaihuo.com/js/830.html
本文向大家介绍微信小程序wx.previewImage预览图片实例详解,包括了微信小程序wx.previewImage预览图片实例详解的使用技巧和注意事项,需要的朋友参考一下 一.小知识 二.例子 1.wxml 2.wxss 3.js 使用网络的图 使用本地的图片: 所以这个接口, 按照官方示例, 可能只支持 http 或者 https 协议的网络图片地址. 注意: 网上还有说本地图片确实是不可以
本文向大家介绍Android仿微信群聊头像,包括了Android仿微信群聊头像的使用技巧和注意事项,需要的朋友参考一下 工作中需要实现仿钉钉群头像的一个功能,就是个人的头像拼到一起显示,看了一下市场上的APP好像微信的群聊头像是组合的,QQ的头像不是,别的好像也没有了。 给大家分享一下怎么实现的吧。首先我们先看一下效果图: 好了,下面说一下具体怎么实现的: 实现思路 1.首先获取Bitmap图片(
本文向大家介绍Android仿微信微博多图展示效果,包括了Android仿微信微博多图展示效果的使用技巧和注意事项,需要的朋友参考一下 1.简介 这是一个用于实现像微信朋友圈和微博的类似的九宫格图片展示控件,通过自定义viewgroup实现,使用方便。 多图根据屏幕适配,单张图片时需要自己指定图片的宽高; 2.使用方法 引用: compile 'com.w4lle.library:NineLayo
本文向大家介绍Android仿微信QQ设置图形头像裁剪功能,包括了Android仿微信QQ设置图形头像裁剪功能的使用技巧和注意事项,需要的朋友参考一下 最近在做毕业设计,想有一个功能和QQ一样可以裁剪头像并设置圆形头像,额,这是设计狮的一种潮流。 而纵观现在主流的APP,只要有用户系统这个功能,这个需求一般都是在(bu)劫(de)难(bu)逃(xue)! 图片裁剪实现方式有两种,一种是利用系统自带