刘下记录:ImageView.scaleType 属性全解析(含视频)
0. 译序
ImageView 有一个经常使用场景:ImageView 的宽度固定,高度等比例缩放。且 ImageView 在 padding 所有为 0 的情况下不留白边,即图片全然填充 ImageView。(注意:该方法对“高度固定,宽度等比例缩放”不适用,详细见 例1-2 代码)
这篇文给出了这个场景的答案,翻译过来以背不时之需。
上述需求能够用例如以下属性实现:
例1-1
<ImageView
android:id="@+id/image"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:src="@drawable/image" />
可是,例如以下代码是不行的,显示的图片可能会出现变形,变形的图片宽度为原始图片的宽度,而高度被强制缩放成“30dp”:
例1-2
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:src="@drawable/image" />
或者用 BitmapScaler 这个工具类。相关方法例如以下:
public class BitmapScaler
{
// Scale and maintain aspect ratio given a desired width
// BitmapScaler.scaleToFitWidth(bitmap, 100);
public static Bitmap scaleToFitWidth(Bitmap b, int width)
{
float factor = width / (float) b.getWidth();
return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
}
// Scale and maintain aspect ratio given a desired height
// BitmapScaler.scaleToFitHeight(bitmap, 100);
public static Bitmap scaleToFitHeight(Bitmap b, int height)
{
float factor = height / (float) b.getHeight();
return Bitmap.createScaledBitmap(b, (int) (b.getWidth() * factor), height, true);
}
// ...
}
1. 概述
一般来说,我们使用 SDK 内置的图片控件展示图片。这个图片控件会自己考虑载入和优化问题。使得开发人员很多其它的考虑应用相关的布局和内容等细节。
这篇教程中,我们将逐一解说怎样使用 ImageView,怎样操作 bitmap,各种分辨率的目录以及其它内容。
2. 用法
从最简单的開始,ImageView 是布局文件里的一个控件。用途是在屏幕中展示图片(或 drawable 资源文件)。
用法大概例如以下:
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:src="@drawable/my_image" />
ImageView 会为你处理所有的载入和缩放问题。注意,scaleType 属性决定图片图片怎样缩放以适应你的布局。在上例中,scaleType = “center” 使得图片以原始分辨率和居中的方式展示,而不考虑控件占用多大的空间。
3. 尺寸控制
通常条件下,ImageView 要控制的对象是图片的宽高,即 layout_width 和 layout_height:
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="fitXY" />
样例中的 scaleType=”fitXY” 表示将宽高均缩放到指定的长度“50dp”。
Fixing the width and height however means that the proportions of the width and height of the original image, known as the aspect ratio, will be altered. We can take advantage of the adjustViewBounds parameter to preserve this aspect ratio. However, we must either allow the height and/or width to be adjustable (i.e. by using maxWidth and using wrap_content for the dimension). Otherwise, the dimensions cannot be readjusted to meet the required aspect ratio.
然而,固定的宽高会改变原始图片的宽高比,而使用 adjustViewBounds 參数能够保持宽高比。必须将宽度或高度设置为可调节的(比如使用 maxWidth 和 wrap_content)。否则无法保持原始图片的宽高比。
<ImageView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
通过这样的将各种属性组合使用的方式我们能够控制图片的大致尺寸和宽高比例。
同样我们能够用 Java 代码通过 getLayoutParams() 动态的更改 ImageView 的宽高:
imageView.getLayoutParams().height = 100; // OR
imageView.getLayoutParams().width = 100;
某些场景下,图片须要缩放以适应父view的宽度。同一时候要求图片高度等比例缩放。
我们能够使用链接中的 ResizableImageView 来达到目的。
4. 缩放类型
ImageView 依据 scaleType 的类型来展示图片。
上文中我们探讨了 fitXY 和 adjustViewBounds。以下是经常使用的 scaleType 的一览表:
(注意:
- 以下规则仅符合 layout_width、layout_height、scaleType 三个属性的共同作用,而未考虑 adjustViewBounds 等属性;
- 纸上来的终觉浅,墙裂建议亲手试试,通过 SDK 自带的 layout 实时预览功能来查看不同的 scaleType 属性值与各种 layout_width、layout_height 搭配使用时的效果。便于理解和记忆;
- 尽管 fitXY 能够让图片全然依照 layout 的尺寸来显示,可是假设原始图片和 ImageView 的宽高比不一致则会导致终于显示的图片变形。假设你在开发图片浏览类型的应用,推荐使用 center 或 fitCenter 类型。)
scaleType | 描写叙述 |
---|---|
center | 将图片中心与 ImageView 的中心重合,保持图片的原始尺寸,仅仅显示落在 ImageView 内部的图片部分 |
centerCrop | 将图片中心与 ImageView 的中心重合,然后进行等比例缩放。直到图片宽高均不小于 ImageView 的宽高,位于 ImageView 之外的图片部分不显示,缩放过程中保持图片宽高比 |
centerInside | 将图片中心与 ImageView 的中心重合,假设图片所有位于 ImageView 内部,则完毕,否则对图片等比例缩小直到图片宽高均不大于 ImageView 的宽高 |
fitCenter | 将图片中心与 ImageView 的中心重合。然后等比例进行缩放,直到图片宽高均不大于 ImageView 的宽高;fitCenter 与 centerInside 的差别在于:当图片原始尺寸小于 ImageView 时,后者不正确图片做不论什么处理而前者对图片进行等比例放大直至其宽高至少有一项与 ImageView 相应的宽高相等 |
fitStart | 将图片左上角与 ImageView 的左上角重合。其余和 fitCenter 同样 |
fitEnd | 将图片右下角与 ImageView 的右下角重合,其余和 fitCenter 同样 |
fitXY | 将图片的宽高缩放到与 ImageView 的宽高全然同样;缩放过程全然无视原始图片的宽高比 |
matrix | 依据 setImageMatrix() 方法设置的 Matrix 类来显示图片,Matrix 类能够用来实现图片翻转等效果 |
上图相应的 android:scaleType 值:
第一行(从左至右)依次是 center, centerCrop, centerInside;
第二行(从左至右)依次是 fitCenter, fitStart, fitEnd, fitXY。
由上述图表能够看出,scaleType 可分为 3 大类:center,fit。matrix:
- 以 center 开头的值表示将图片中心和 ImageView 中心重合。然后保持原始尺寸(center)或将图片缩放到圈在 ImageView 内部(centerInside)或将图片放大到覆盖 ImageView(centerCrop);
- 以 fit 开头的值表示将图片的宽高缩放到至少有一项与 ImageView 的宽高同样,依据两方对准的起点分为中心(fitCenter)、左上角(fitStart)、右下角(fitEnd)或无起点(fitXY);
scaleType | 图片和ImageView中心点重合 | 保持图片原始尺寸 | 保持图片宽高比 | 显示图片与 ImageView 大比較 |
---|---|---|---|---|
center | √ | √ | √ | 同图片原始尺寸和 ImageView 大小关系 |
centerCrop | √ | x | √ | >= |
centerInside | √ | x | √ | <= |
fitCenter | √ | x | √ | <= |
fitStart | x | x | √ | <= |
fitEnd | x | x | √ | <= |
fitXY | √ | x | x | = |
还不明确?看下视频解说吧:安卓 ImageView scaleType 属性值解析
5. 支持多种屏幕分辨率
由于安卓设备的屏幕尺寸、分辨率类型繁杂,须要有一个能自己主动为设备匹配合适的资源的强大系统。安卓project目录和安装包中有专门为不同类型的设备准备的资源目录,包含:ldpi(低分辨率)。mdpi(medium dots per inch。中分辨率),hdpi(高分辨率)。xhdpi(超高分辨率)。这些资源目录以 drawable-mdip 的形式命名。
为了适配多种分辨率,我们要依照 3:4:6:8 的比例来为上述资源目录设计图片文件。详细例如以下:
分辨率 | DPI | 演示样例设备 | 换算比例 | 像素 | 备注 |
---|---|---|---|---|---|
ldpi | 120 | Galaxy Y | 0.75x | 1dp = 0.75px | |
mdpi | 160 | Galaxy Tab | 1.0x | 1dp = 1px | |
hdpi | 240 | Galaxy S II | 1.5x | 1dp = 1.5px | |
xhdpi | 320 | Nexus 4 | 2.0x | 1dp = 2px | 720p |
xxhdpi | 480 | Nexus 5 | 3.0x | 1dp = 3px | 1080p |
xxxhdpi | 640 | Nexus 6 | 4.0x | 1dp = 4px |
这意味着。假设你在 drawable-mdpi 目录中有一张 100x100 的图片。那么你要在 drawable-ldpi 文件里放置 75x75 的图片,drawable-hdpi 文件里放置 150x150 的图片,在 drawable-xhdpi 中放置 200x200的。在 drawable-xxhdpi 中放置 300x300 的图片。
Final Android Resizer 能够让你方便的对图片进行缩放:
这个便捷的工具能够让我们选择 drawable-xxhdpi 目录中的一张图片,自己主动的在相应的分辨率的资源目录中生成相应分辨率的图片。
很多其它支持多分辨率的知识请移步安卓支持多屏幕和图标设计官方文档。
6. 纹理和资源
从 4.3 系统開始,安卓提供一个 res/mipmap 的目录,用来存储纹理图片。纹理最大的用处是应用图标,如启动图标等。关于纹理的优点请移步这篇博文:纹理资源文件。
纹理图片资源通过 @mipmap/ic_launcher 的方式引用。将图标放在 res/mipmap 目录(而不是 drawable 目录)是最优的作法,由于这些图标会在与其它分辨率下经常使用。
For example, an xxxhdpi app icon might be used on the launcher for an xxhdpi device. Review this post about preparing for the Nexus 6 which explains in more detail。
7. 使用 Bitmap
我们能够在 Java 代码中设置 ImageView 展示的图片:
ImageView image = (ImageView) findViewById(R.id.test_image);
image.setImageResource(R.drawable.test2);
或者:
ImageView image = (ImageView) findViewById(R.id.test_image);
Bitmap bMap = BitmapFactory.decodeFile("/sdcard/test2.png");
image.setImageBitmap(bMap);
8. 缩放 Bitmap
你能够调用 createScaleBitmap() 方法来调整 Bitmap 的尺寸:
// Load a bitmap from the drawable folder
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
// Resize the bitmap to 150x100 (width x height)
Bitmap bMapScaled = Bitmap.createScaledBitmap(bMap, 150, 100, true);
// Loads the resized Bitmap into an ImageView
ImageView image = (ImageView) findViewById(R.id.test_image);
image.setImageBitmap(bMapScaled);
假设要等比例缩放 Bitmap。能够用 BitmapScaler 这个工具类,代码例如以下:
public class BitmapScaler
{
// Scale and maintain aspect ratio given a desired width
// BitmapScaler.scaleToFitWidth(bitmap, 100);
public static Bitmap scaleToFitWidth(Bitmap b, int width)
{
float factor = width / (float) b.getWidth();
return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
}
// Scale and maintain aspect ratio given a desired height
// BitmapScaler.scaleToFitHeight(bitmap, 100);
public static Bitmap scaleToFitHeight(Bitmap b, int height)
{
float factor = height / (float) b.getHeight();
return Bitmap.createScaledBitmap(b, (int) (b.getWidth() * factor), height, true);
}
// ...
}
其它场景下,你可能想要依据屏幕的高或宽来缩放图片。将 DeviceDimensionsHelper.java 这个工具类复制到你的project中,然后在 Context 中使用例如以下代码:
// Get height or width of screen at runtime
int screenWidth = DeviceDimensionsHelper.getDisplayWidth(this);
// Resize a Bitmap maintaining aspect ratio based on screen width
BitmapScaler.scaleToFitWidth(bitmap, screenWidth);
关于这个工具类的很多其它知识请戳我。
注意:不论什么形式的图片缩放都会造成图片 EXIF 元数据的丢失,包含相机。旋转。拍摄时间等。尽管有解决方式能将这些数据转移,但如今仍然有缺陷。假设你须要这些元数据或者想连同元数据一起上传到server,那么你应该上传原始文件而非处理后的文件。
9. SVG 格式图片
通过 svg-android 这个第三方库我们能够使用屏幕分辨率无关的 SVG 图片。
// Parse an SVG resource from the "raw" resource folder
SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.android);
// Fix issue with renderer on certain devices
myImageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
// Get a drawable from the parsed SVG and set it as the drawable for the ImageView
myImageView.setImageDrawable(svg.createPictureDrawable());
很多其它知识详见官方文档。
10. 參考文献
- http://www.peachpit.com/articles/article.aspx?p=1846580&seqNum=2
- http://code.tutsplus.com/tutorials/android-user-interface-design-basic-image-controls–mobile-6846
- http://developer.android.com/reference/android/widget/ImageView.html
- http://developer.android.com/guide/practices/screens_support.html
- https://code.google.com/p/svg-android/wiki/Tutorial
- https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/ImageView.java#L903-L907
刘下记录:ImageView.scaleType 属性全解析(含视频)的更多相关文章
- <link>标签的rel属性全解析
<link>标签定义了当前文档与 Web 集合中其他文档的关系.link 元素是一个空元素,它仅包含属性.此元素只能存在于 head 部分,不过它可出现任何次数.在 HTML 中,&l ...
- Android ImageView scaleType属性
scaleType属性 文章来源:http://blog.csdn.net/xilibi2003/article/details/6628668 使用ImageView时经常会用到scaleType属 ...
- android ImageView scaleType属性(转)
使用ImageView时经常会用到scaleType属性,如: 1 2 3 4 5 6 7 8 9 <ImageView android:layout_width="50dp&qu ...
- Android ImageView(scaleType属性)(转)
(转自:http://www.open-open.com/lib/view/open1378257991687.html) <ImageView android:id="@+id/im ...
- Android ImageView(scaleType属性)图片按比例缩放
<ImageView android:id="@+id/img" android:src="@drawable/logo" android:scaleTy ...
- 【Android】ImageView ScaleType属性值
ImageView.ScaleType / android:scaleType值的意义区别: CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的 ...
- 【转】ImageView.ScaleType属性
原文网址:https://blog.csdn.net/Buaaroid/article/details/49360779 ImageView的Scaletype决定了图片在View上显示时的样子,如进 ...
- Android中ImageView.ScaleType属性值
1 android:scaleType="center" (1)当图片大于ImageView的宽高:以图片的中心点和ImageView的中心点为基准,按照图片的原大小居中显示,不缩 ...
- Android UI系列-----ImageView的scaleType属性
这篇随笔将会简单的记录下ImageView这个控件的一些使用方法,以及其最重要的一个属性: scaleType ImageView这个控件是用来显示图片用的,例如我们可以通过下面这段xml配置来声明显 ...
随机推荐
- 观数据世界,览类型风骚---Python
一.变量的简介 变量只不过是保留的内存位置用来存储数据.这意味着,当创建一个变量,那么它在内存中保留一些空间. 根据一个变量的数据类型,解释器分配内存,并决定如何可以被存储在所保留的内存中.因此,通过 ...
- ruby 制作自己的gem包
在ruby工程目录下新建一个文件:crowdSystem.gemspec.需要在lib目录下存在同一名称的ruby库文件:crowdSystem.rb
- POJ 2184:Cow Exhibition(01背包变形)
题意:有n个奶牛,每个奶牛有一个smart值和一个fun值,可能为正也可能为负,要求选出n只奶牛使他们smart值的和s与fun值得和f都非负,且s+f值要求最大. 分析: 一道很好的背包DP题,我们 ...
- 【bzoj4012】[HNOI2015]开店 动态点分治+STL-vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题 ...
- 编写可移植的PHP代码
1. 保持配置集中放置. 作为一个通用的准则,建议将大多数信息保存在一个位置(可能是一个文件中),这样在需要修改信息时,就能在同一个位置进行所有必要的修改. 2. 编写可重用的代码: 如果刚刚结束了其 ...
- BZOJ3571 [Hnoi2014]画框 【分治 + KM算法】
题目链接 BZOJ3571 题解 如果知道最小乘积生成树,那么这种双权值乘积最小就是裸题了 将两权值和作为坐标,转化为二维坐标系下凸包上的点,然后不断划分分治就好了 这里求的是最小匹配值,每次找点套一 ...
- idea工具开发注意事项
pom.xml中不需要有包 <dependency> <groupId>javax</groupId> <artifactId>javaee-api&l ...
- 洛谷P3045 [USACO12FEB]牛券Cow Coupons
P3045 [USACO12FEB]牛券Cow Coupons 71通过 248提交 题目提供者洛谷OnlineJudge 标签USACO2012云端 难度提高+/省选- 时空限制1s / 128MB ...
- 【转】 #define用法详解
#define用法详解 1.#define 的作用 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为“宏”.被定义为“宏”的标识符称为“宏名”.在编译预处理时,对程序中所有出现的“宏 ...
- MySql视图笔记(转载)
1. 视图的定义 视图就是从一个或多个表中,导出来的表,是一个虚拟存在的表.视图就像一个窗口(数据展示的窗口),通过这个窗口,可以看到系统专门提供的数据(也可以查看到数据表的全部数据),使 ...