Android 大图查看器
请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/50742628
在项目里自己写了个大图查看效果,感觉还行,打包成了库,分享给大家,先看效果图:
源码地址:https://github.com/mabeijianxi/ViewLargerImageUtil
使用方法:
Usage
Step-1
导入并且添加依赖:
Gradle: compile project(':lib')
Step-2
配置AndriodManifest:
权限配置
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
配置Activity
<activityandroid:name="com.mabeijianxi.lookbigpicutils.activty.LookBigPicActivity"android:theme="@android:style/Theme.Translucent.NoTitleBar"android:launchMode="singleTop" />
Step-3
初始化ImageLoader
private void initImageLoader(Context context) {{ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);config.threadPriority(Thread.NORM_PRIORITY - 2); // config.denyCacheImageMultipleSizesInMemory();//不会在内存中缓存多个大小的图片config.diskCacheFileNameGenerator(new Md5FileNameGenerator());//为了保证图片名称唯一//内存缓存大小默认是:app可用内存的1/8config.tasksProcessingOrder(QueueProcessingType.LIFO);config.writeDebugLogs(); // Remove for release app// Initialize ImageLoader with configuration.ImageLoader.getInstance().init(config.build());}
Step-4
在合适的地方使用,可参照samples
你只需要封装一个包含大图url与小图url即可:
ArrayList<PicUrlBean> picUrlList = new ArrayList<>();for(int i=0;i<UrlData.getSmallList().size();i++){PicUrlBean picUrlBean = new PicUrlBean();picUrlBean.imageBigUrl=UrlData.getBigUrlList().get(i);picUrlBean.smallImageUrl=UrlData.getSmallList().get(i);picUrlList.add(picUrlBean);}
然后直接跳转就完成了:
ViewLargerImageUtil.lookBigPic(MainActivity.this,view,picUrlList,position,4,4,3);
原理:
查看大图是实际开发中比较常见的,假设你是查看的一组的中的一张,如果要实现上面的效果首先你需要指定你查看的是第几张,并且你需要知道这张图的大小和坐标,并且你需要计算出这张图所在的组图里面所有的位置坐标,这样后续的动画才有办法进行。下面将一步一步分析。
1、获取组图中每张图片的信息并且封装:
都是搬砖的,都懂的,就直接上代码和注释了
int xn = currentItem % maxRow + 1;//当前点击的图片x方向是第几个(currentItem从0开始,xn从1开始,都是数学小原理,就不解释了)int yn = currentItem / maxRow + 1;//当前点击的图片y方向是第几个(currentItem从0开始,yn从1开始,都是数学小原理,就不解释了)int h = (xn - 1) * CommonUtils.dip2px(context, horizontalPadding);//当前点击的图片距离最左边的总Paddingint v = (yn - 1) * CommonUtils.dip2px(context, verticalPadding);//当前点击的图片距离最上边的总Padding//接着先获取组图中第一张图片宽高与在屏幕上的坐标int height = image.getHeight();int width = image.getWidth();int[] points = new int[2];image.getLocationInWindow(points);int x0 = points[0] - (width + h) * (xn - 1);//组图中第一张图片的x坐标int y0 = points[1] - (height + v) * (yn - 1);//组图中第一张图片的y坐标//由于是规则的有了第一张图片的信息一切都变得简单了,接着就可以得到所有图片的信息for (int i = 0; i < picUrlDataList.size(); i++) {PicDataBean picDataBean =new PicDataBean();PicUrlBean picUrlBean = picUrlDataList.get(i);picDataBean.setUrl(picUrlBean);picDataBean.width = width;picDataBean.height = height;picDataBean.x = x0 + (i % maxRow) * (width + CommonUtils.dip2px(context, horizontalPadding));//依次为每张图赋值,其实就累加而已picDataBean.y = y0 + (i / maxRow) * (height + CommonUtils.dip2px(context, verticalPadding)) - CommonUtils.getStatusBarHeight(image);//picDataList.add(picDataBean);}
2、在合适的时候开始Activity的出场动画:
那么问题来了,什么时候合适?我这里选择为imageview设置OnPreDrawListener,其回调时机顾名思义。接下来分析这个动画执行过程。这个动画是让图片从其在组图中的大小慢慢变为高充满全屏或者宽充满全屏(后面会说到计算规则),其位置也会从原来组图中所在的位置变到屏幕正中心,当然为了更酷可以可以为北京设置透明度的变化。大概流程就是这样,接着代码实践:
public boolean onPreDraw() {viewPager.getViewTreeObserver().removeOnPreDrawListener(this);//只需要执行一次出场动画final View view = imageScaleAdapter.getPrimaryItem();final PhotoView imageView = (PhotoView) ((ViewGroup) view).getChildAt(0);//这个用了谷歌工程师Chris Banes写的PhotoView控件来显示图片Drawable drawable = imageView.getDrawable();int intrinsicHeight = drawable.getIntrinsicHeight();//获得图片实际的高度(可能是大图的,也可能是小图的,不重要)int intrinsicWidth = drawable.getIntrinsicWidth();//获得图片实际的宽度(可能是大图的,也可能是小图的,不重要)float h = CommonUtils.getScreenSizeHeight(this) * 1.0f / intrinsicHeight;float w = CommonUtils.getScreenSizeWidth(this) * 1.0f / intrinsicWidth;//这里是要比较屏幕高与图片高的比例与屏幕高=宽与图片宽的比例,用于比较以宽的比例为准还是高的比例为准,因为很多时候不是高度没充满屏幕,就是宽度没充满屏幕if (h > w) {h = w;} else {w = h;}height = (int) (intrinsicHeight * h);//得到做完动画后显示到屏幕上的图片高width = (int) (intrinsicWidth * w);//得到做完动画后显示到屏幕上的图片宽final PicDataBean picBean = picDataList.get(mPositon);final float vx = picBean.width * 1.0f / width;//计算出做动画前的图片(小图)与做动画前的图片(大图)的比例final float vy = picBean.height * 1.0f / height;//计算出做动画前的图片(小图)与做动画前的图片(大图)的比例final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float animatedFraction = animation.getAnimatedFraction();view.setTranslationX(EvaluateUtil.evaluateInt(animatedFraction, picBean.x + picBean.width / 2 - imageView.getWidth() / 2, 0));//这个平移动画也很简单,确定三个东西即可完成一帧,就跟初中的指定起点与终点位置,求此路程1/2的位置一直,这里也是。x方向起点是 picBean.x + picBean.width / 2 - imageView.getWidth() / 2,至于终点这里也就是不偏移的时候,具体偏移值就是0了(对坐标计算不太敏感的童鞋可以画图看下)view.setTranslationY(EvaluateUtil.evaluateInt(animatedFraction, picBean.y + picBean.height / 2 - imageView.getHeight() / 2, 0));//Y方向与X方向同理//缩放这个还是比较有意思的,起点缩放比例是vx,终点比例自如是1也就是不缩放。view.setScaleX(EvaluateUtil.evaluateFloat(animatedFraction, vx, 1));view.setScaleY(EvaluateUtil.evaluateFloat(animatedFraction, vy, 1));//背景的透明过度,比较简单ll_root.setBackgroundColor((int) EvaluateUtil.evaluateArgb(animatedFraction, 0x0, 0xff000000));}});valueAnimator.setDuration(300);valueAnimator.start();return true;}
于是整个出场动画过程就完成了。
3、在需要关闭的时候开始Activity的退场动画:
有了出场动画退场动画就非常简单了,反过来就ok了
final View view = imageScaleAdapter.getPrimaryItem();//得到当看到的Viewfinal PhotoView imageView = (PhotoView) ((ViewGroup) view).getChildAt(0);//得到当看到的PhotoViewimageView.setZoomable(false);// 当图片被放大时,需要把其缩放回原来大小再做动画Drawable drawable = imageView.getDrawable();int intrinsicHeight = drawable.getIntrinsicHeight();//获得图片实际的高度(可能是大图的,也可能是小图的,不重要)int intrinsicWidth = drawable.getIntrinsicWidth();//获得图片实际的宽度(可能是大图的,也可能是小图的,不重要)float h = CommonUtils.getScreenSizeHeight(this) * 1.0f / intrinsicHeight;float w = CommonUtils.getScreenSizeWidth(this) * 1.0f / intrinsicWidth;//这里是要比较屏幕高与图片高的比例与屏幕高=宽与图片宽的比例,用于比较以宽的比例为准还是高的比例为准,因为很多时候不是高度没充满屏幕,就是宽度没充满屏幕if (h > w) {h = w;} else {w = h;}height = (int) (intrinsicHeight * h);//得到做完动画后显示到屏幕上的图片高width = (int) (intrinsicWidth * w);//得到做完动画后显示到屏幕上的图片宽final PicDataBean ealuationPicBean = picDataList.get(mPositon);final float vx = ealuationPicBean.width * 1.0f / width;final float vy = ealuationPicBean.height * 1.0f / height;//退场动画过程只需要把入场对话反向就行了,so easyfinal ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float animatedFraction = animation.getAnimatedFraction();view.setTranslationX(EvaluateUtil.evaluateInt(animatedFraction, 0, ealuationPicBean.x + ealuationPicBean.width / 2 - imageView.getWidth() / 2));view.setTranslationY(EvaluateUtil.evaluateInt(animatedFraction, 0, ealuationPicBean.y + ealuationPicBean.height / 2 - imageView.getHeight() / 2));view.setScaleX(EvaluateUtil.evaluateFloat(animatedFraction, 1, vx));view.setScaleY(EvaluateUtil.evaluateFloat(animatedFraction, 1, vy));ll_root.setBackgroundColor((int) EvaluateUtil.evaluateArgb(animatedFraction, 0xff000000, 0x0));if (animatedFraction > 0.95) {view.setAlpha(1 - animatedFraction);}}});valueAnimator.setDuration(300);valueAnimator.start();
4、优化一些图片加载过程
在图片加载的时候肯定是需要时间的,这个时间的长短是根据网络情况和图片大小等等因素决定的,这个时候界面应该显示什么?进度条吗,我觉得不只是这样。用Fresco的话是支持渐进式的图片加载的,其实自己也能实现个类似的体验。方案很简单,加载大图的时候从内存中取小图的Bigmap,先显示小图和进度条,加载完成后再显示大图,看着就是从模糊慢慢变清晰。这里演示下用universalimageloader时的操作:
private void setupNetImage(final ProgressBar pb, final PicDataBean picBean) {mImageLoader.displayImage(picBean.imageBigUrl, imageView, pager_options, new ImageLoadingListener() {@Overridepublic void onLoadingStarted(String imageUri, View view) {startLoad(pb);//显示进度条 Bitmap bitmap = ImageUtils.getBitmapFromCache(ealuationPicBean.smallImageUrl, mImageLoader);//,不能直接使用:imageLoader.getMemoryCache().get(uri)来获取,因为在加载过程中,key是经过运算的,而不单单是uri,而是: String memoryCacheKey = MemoryCacheUtil.generateKey(uri, targetSize)if (bitmap != null) {imageView.setImageBitmap(bitmap);} else {imageView.setImageResource(R.drawable.defaultPic);}}@Overridepublic void onLoadingFailed(String imageUri, View view, FailReason failReason) {overLoad(pb);//结束进度条}@Overridepublic void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {overLoad(pb);//结束进度条}@Overridepublic void onLoadingCancelled(String imageUri, View view) {overLoad(pb);//结束进度条}});}
到此一个漂亮的大图查看工具就搞定了
不足之处欢迎指出![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
Android 大图查看器相关推荐
- android 图片查看器
android实现的图片查看器 public class MainActivity extends AppCompatActivity {private EditText et_new_path;pr ...
- android网络图片查看器,Android网络应用(图片查看器)
布局: android:id="@+id/widget32" android:layout_width="fill_parent" android:layout ...
- Android图片查看器
/** *本程序由070203110安树峰软件0705倡导,主编,贺鹏,贾飞, *田镇源, 王振兴合作开发,仿冒必究 */ package com.csdn.shufeng1988; impor ...
- Android log查看器
平常工作经常用adb logcat >log.log这个命令抓log,抓出来都是文本文件,logcat又不能重读文件来查看,动辄log都是上万行查个有用的log很是费劲. 今天实在忍不住了,摆弄 ...
- android 变量onchange,Android内容查看器-onChange方法检查上一个呼...
我正在开发一个android应用,我需要增加未接来电. 我注册了ContentObserver.如果呼叫是未接来电,如何检查onChange方法? 我有一个带有以下代码的contentobserver ...
- android 网络图片查看器,Handler的用法
通过网络访问图片,并通过Handler更新主线程的控件. public class MainActivity extends Activity {protected static final Stri ...
- android图片查看器,实现图片加载进度监听,实现保存图片
1.添加依赖 implementation 'com.github.bumptech.glide:glide:4.6.1' compile 'com.github.chrisbanes:PhotoVi ...
- Android 日志自动分析,Android Log Viewer:一个日志查看器工具,可简化实时对Android日志的分析...
作为与Cordova一起工作的移动应用程序开发人员, 我知道调试应用程序的本机部分会很困难, 例如, 当你为应用程序创建本机插件时(在这种情况下, Android Studio无效).在试图找出我的应 ...
- 图片查看器:Android支持图片查看、缩放、滑动的PhotoView
上效果: Android 图片查看器Demo效果 导入PhotoView,导入Glide. maven { url "https://jitpack.io" }implementa ...
最新文章
- 贵州高二会考计算机考试题,20167月贵州普通高中学业水平考试会考试题
- 83篇文献、万字总结开启你的强化学习之路!
- 关于 Deployer 部署结构
- 2019年安徽省模块七满分多少_艺考资讯 | 2021年美术统考考多少分才能通过?过了合格线有什么意义?美术生一定要重视!...
- python交换两列的位置_如何更改 pandas dataframe 中两列的位置
- 线段树/扫描线问卷调查反馈——Rmq Problem / mex(主席树),Boring Queries(二分+st表+主席树),Colorful Squares(扫描线)
- pm2 可视化在线监控平台 介绍 keymetrics
- Android10一直获取IP地址,Android 获取IP地址的实现方法
- 使用方法_防爆配电箱使用方法及使用条件
- java中activiti框架中的排他网关使用方法,多条件判断
- 我弟弟用管理员身份把我和爸妈的WIFI设置了,现在就他能用网,气不过,有办法让我出口气吗?
- 【lucene】入门级
- tensorflow 版本列表,如何找到我的系统中安装了哪个版本的TensorFlow?
- pythoncopy函数_Python的shutil模块中文件的复制操作函数详解
- JSP的执行过程及生命周期
- 最长回文字串--动态规划
- NI VISION视觉安装
- 多商户Saas模式云进销存系统,源码分享
- 文件夹重命名导致软件图标不显示问题解决
- JavaScript里函数中的this
热门文章
- MUR160RLG说明
- 数据结构 查找 静态查找表算法 折半查找 二叉排序树查找算法 实验报告
- LazMall是什么?LazMall与lazada普通店铺有什么区别?怎么加入LazMall
- 刷magisk模块后不能开机_一日一技 | 让过时失效、无法刷入的 Magisk 模块重现生机...
- Java 设置PDF平铺图片背景(水印)
- 我的读书笔记 -《人性的弱点》
- 手游运营者必学:运营的核心、宗旨和目标
- 主要股东近3年净买入排名
- 混合波束成形| 宽带系统基于码本的信道估计 《Channel Estimation for Hybrid Architecture-Based Wideband Millimete
- BZOJ4755: [JSOI2016]扭动的回文串——题解