长图的展开与收起(Android)
前言:
在app的文章中,经常会夹杂着一些特别长的长图。在阅读的时候需要滑动很久才能看图片下方的文字,因此对于长图只展示图片上面一部分,并且可以展开这个功能是很重要的。
效果:
基本思路:
利用scaleType的matrix属性以及直接改变图片的高度来实现图片的收起与展开。
过程:
开始尝试:
scaleType属性介绍:
- center:保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size,超过部分裁剪处理;
- centerInside:以原图完全显示为目的,将图片的内容完整居中显示,通过按比例缩小原图的size宽(高)等于或小于ImageView的宽(高)。如果原图的size本身就小于ImageView的size,则原图的size不作任何处理,居中显示在ImageView;
- centerCrop:以填满整个ImageView为目的,将原图的中心对准ImageView的中心,等比例放大原图,直到填满ImageView为止(指的是ImageView的宽和高都要填满),原图超过ImageView的部分作裁剪处理;
- matrix:不改变原图的大小,从ImageView的左上角开始绘制原图,原图超过ImageView的部分作裁剪处理;
- fitCenter:把原图按比例扩大或缩小到ImageView的高度,居中显示;
- fitEnd:把原图按比例扩大(缩小)到ImageView的高度,显示在ImageView的下部分位置;
- fitStart:把原图按比例扩大(缩小)到ImageView的高度,显示在ImageView的上部分位置;
- fitXY:把原图按照指定的大小在View中显示,拉伸显示图片,不保持原比例,填满ImageView
根据以上属性介绍,可以知道matrix属性是我们要的。
基本布局:
<ImageView
android:id="@+id/iv_long_picture"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_146"
android:layout_below="@id/tv_main_content_question"
android:adjustViewBounds="true"
android:scaleType="matrix"
android:src="@color/color_333333" />
<TextView
android:id="@+id/tv_expand_collapse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/iv_long_picture"
android:layout_marginBottom="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_10"
android:drawableEnd="@drawable/down_icon"
android:drawablePadding="@dimen/dp_7"
android:text="@string/expand_all"
android:textColor="@color/color_99"
android:textSize="@dimen/sp_14"
android:textStyle="bold"
android:visibility="gone" />
加载图片:
使用Glide加载的图片,
Glide.with(this)
.load(mainContentBean.getAccessory().get(0))
.into(ivLongPicture);
点击事件:
直接通过设置imageView的高度来实现图片的展开与收起,
tvExpandCollapse.setOnClickListener(new View.OnClickListener() {
boolean expanded = false;
@Override
public void onClick(View v) {
if (expanded) {
// 收起
ViewGroup.LayoutParams params = ivLongPicture.getLayoutParams();
params.width = RelativeLayout.LayoutParams.MATCH_PARENT;
params.height = DensityUtil.dip2px(MainContentActivity.this, 146);
ivLongPicture.setLayoutParams(params);
expanded = false;
tvExpandCollapse.setText(R.string.expand_all);
tvExpandCollapse.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.down_icon, 0);
scMainContent.smoothScrollTo(0, 0);
} else {
// 展开
ViewGroup.LayoutParams params = ivLongPicture.getLayoutParams();
params.width = RelativeLayout.LayoutParams.MATCH_PARENT;
params.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
ivLongPicture.setLayoutParams(params);
expanded = true;
tvExpandCollapse.setText(R.string.collapse_all);
tvExpandCollapse.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.upper_icon, 0);
}
}
});
遇到问题:
根据以上的思路以及代码实现,普通的长图确实能够做到“展开”和“收起”功能。
但是对于原图宽度超过手机宽度的图片来说,宽度并没有显示完全!
对于Glide版本4.0以上,如果宽度过大,会等比例缩放至宽度等于ImageView的宽度,因此并不会有问题,但是我们的项目用Glide版本是3.7的,而且不容易升级,故此方法不可行。
解决:
查阅了Glide的文档,了解了Glide可以在图片下载完成后对图片进行一些操作,操作完成之后的图片自然就成了ImageView认为的原图了。
因此,可以在加载之前将宽度过大的图片等比例缩放,缩放完成后再加载到ImageView中去。
加载图片改进:
Glide.with(this)
.load(mainContentBean.getAccessory().get(0))
.asBitmap()
.listener(new RequestListener<String, Bitmap>() {
@Override
public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
return false;
} @Override
public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
int imageWidth = resource.getWidth();
int imageHeight = resource.getHeight(); WindowManager manager = (WindowManager) MainContentActivity.this
.getSystemService(Context.WINDOW_SERVICE); // 屏幕宽度减去margin值
int width = manager.getDefaultDisplay().getWidth() - DensityUtil.dip2px(MainContentActivity.this, 32); float scaleRate = width * 1.0f / imageWidth; //设置matrix
Matrix matrix = new Matrix(); //设置放缩比例
matrix.setScale(scaleRate, scaleRate); ivLongPicture.setImageMatrix(matrix); if (imageHeight * scaleRate > DensityUtil.dip2px(MainContentActivity.this, 146)) {
tvExpandCollapse.setVisibility(View.VISIBLE);
} else {
tvExpandCollapse.setVisibility(View.GONE);
} return false;
}
})
.into(ivLongPicture);
总结:
- ImageView的scaleType属性的各个属性值需要了解;
- Glide版本之间的差异需要了解;
- ImageView如何根据scaleType进行图片切割的需要了解(之后有时间阅读源码);
- Glide是一个庞然大物,也是一个很值得学习的框架,需要熟悉掌握(之后有时间阅读源码)
Android的优势在于开源,开源的好处在于易于学习,容易更改。对于开源的框架,仅仅是掌握是不够的,还需要好好的了解框架设计的一些设计模式,框架的优缺点等。
大家如果有什么疑问或者建议可以通过评论或者邮件的方式联系我,欢迎大家的评论~
长图的展开与收起(Android)的更多相关文章
- 【Android】键盘的展开和收起
键盘的展开和收起主要使用到类InputMethodManager:http://developer.android.com/reference/android/view/inputmethod/Inp ...
- Android 截屏与 WebView 长图分享经验总结
最近在做新业务需求的同时,我们在 Android 上遇到了一些之前没有碰到过的问题,截屏分享. WebView 生成长图以及长图在各个分享渠道分享时图片模糊甚至分享失败等问题,在这过程中踩了很多坑,到 ...
- Android 生成分享长图并且添加全图水印
转载自 : http://blog.csdn.net/gengqiquan/article/details/65938021 领导最近觉得携程的截屏生成长图分享效果比较好,所以我们也加了个:产品觉得分 ...
- android生成分享长图而且加入全图水印
尊重他人的劳动成果.转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/65938021. 本文出自:[gengqiquan的博客] 领导近 ...
- Android内存优化————加载长图
项目中总会遇到加载长图的需求,图片的长度可能是手机长度的很多倍,也就是需要通过滑动来查看图片.比较简单的实现方式就是使用ScrollView来加载长图,但是这样做有一个很严重的问题,就是内存消耗严重. ...
- Silverlight自定义控件系列 – TreeView (3) 添加展开和收起事件
由于Writer嫌我文章过长,只能把上篇拆开两半了.以下是接着上篇的. 准备工作做完了,现在就要完成点击事件. 定义Expander和单击事件: 1: /// <summary> 2: / ...
- jQuery实现画面的展开、收起和停止
主要用到动画效果中的三个操作 ("#id").slideDown(3000): // 后面的数字表示效果的时长 ("#id").stop(); ("# ...
- ImageView加载长图(适用不需要缩放的情况)
此案例适用于加载网络长图且图片的宽和高已知的情况.由于ImageView加载图片有一个4096*4096的限制,所以对于巨长图的加载比较麻烦,需要我们自己去手动处理. 有两种解决方案:第一种就是比较l ...
- SurfaceView加载长图
1:SurfaceView加载长图,移到.可以充当背景 效果截图 2:View (淡入淡出动画没实现:记录下) package com.guoxw.surfaceviewimage; import a ...
随机推荐
- Git版本控制 —— IDE工具(IDEA)
本文介绍使用IDEA控制Git操作 关联本地Git客户端 首先要根据系统环境安装Git客户端 然后使用File --> Settings --> Version Control --&g ...
- Springboot 系列(六)Spring Boot web 开发之拦截器和三大组件
1. 拦截器 Springboot 中的 Interceptor 拦截器也就是 mvc 中的拦截器,只是省去了 xml 配置部分.并没有本质的不同,都是通过实现 HandlerInterceptor ...
- docker(4)docker的网络,自定义网桥
Docker 的网络 运行 ifconfig 找到 docker0 : 虚拟网卡默认网卡名称为docker0 查看docker 的网桥: 我这里默认们没有进行安装 网桥管理设备:进行安装一下: yum ...
- USB总线标准
1.USB总线类型: OHCI(Open Host Controller Interface)是支持USB1.1的标准,但它不仅仅是针对USB,UHCI(Universal Host Controll ...
- QQ登录界面布局
简单的qq登录界面布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmln ...
- 如何优雅的使用 参数 is null而不导致全表扫描(破坏索引)
相信大家在很多实际业务中(特别是后台系统)会使用到各种筛选条件来筛选结果集 首先添加测试数据 ), Age INT) go CREATE INDEX idx_age ON TempList (Age) ...
- 数据库 【redis】 命令大全
以下纯属搬砖,我用Python抓取的redis命令列表页内容 如果想看命令的具体使用可查去官网查看,以下整理为个人查找方便而已 地理位置GEOADD 将指定的地理空间位置(纬度.经度.名称)添加到指定 ...
- 4年前端、2年CTO:一个非科班程序员的真实奋斗史
1.引言 我,Scott,一家创业公司的 CTO. 从业6年却很少写文章,近一年来接触了几十个刚毕业的前端新人,也面试了100多个前端工程师和Nodejs工程师,对于前端发展的这个职业算是有些感触 ...
- PHP内核之旅-6.垃圾回收机制
回收PHP 内核之旅系列 PHP内核之旅-1.生命周期 PHP内核之旅-2.SAPI中的Cli PHP内核之旅-3.变量 PHP内核之旅-4.字符串 PHP内核之旅-5.强大的数组 PHP内核之旅-6 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十六 ║Vue基础:ES6初体验 & 模块化编程
缘起 昨天说到了<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十五 ║ Vue前篇:JS对象&字面量&this>,通过总体来看,好像大家对这一块不是很 ...