A requirement that almost every single application has is "I want to scale up an ImageView proportio
来源:互联网 发布:上传小说的软件 编辑:程序博客网 时间:2024/05/22 03:41
A requirement that almost every single application has is "I want to scale up an ImageView proportionally to fit its parent. How can I do that?" Like this:
Actually ImageView has already come with this capability. You can just simply setandroid:adjustViewBounds
to true
and that's all.
<
ImageView
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:adjustViewBounds
=
"true"
android:src
=
"@mipmap/ic_launcher"
/>
Here is the result.
Everything looks fine? Actually not. If you switch your preview version to API Level 17 or below, you will see that ImageView doesn't scale up anymore.
It is not a bug but a correct behaviour that is officially noted in the documentation.
Note: If the application targets API level 17 or lower, adjustViewBounds will allow the drawable to shrink the view bounds, but not grow to fill available measured space in all cases. This is for compatibility with legacyMeasureSpec
andRelativeLayout
behavior.
It means that in API Level 17 and below, the maximum width and maximum height are bounded to the size of image defined in android:src
. As a result, it happens like picture above.
Have a small look at Market Share of Android Platform Versions. It appears that Android phone running API Level 17 and below takes almost 50% share.
It is not a good solution to set minSdkVersion to 18 just to avoid this problem.
It is far better to modify some ImageView's source code to give it an API Level 18+'s behavior and use it instead of a normal ImageView. Here it comes, a Custom ImageView that does the job !
import
android.content.Context;
import
android.graphics.drawable.Drawable;
import
android.util.AttributeSet;
import
android.view.ViewGroup;
import
android.view.ViewParent;
import
android.widget.ImageView;
/**
* Created by nuuneoi on 2/17/15 AD.
*/
public
class
AdjustableImageView
extends
ImageView {
boolean
mAdjustViewBounds;
public
AdjustableImageView(Context context) {
super
(context);
}
public
AdjustableImageView(Context context, AttributeSet attrs) {
super
(context, attrs);
}
public
AdjustableImageView(Context context, AttributeSet attrs,
int
defStyleAttr) {
super
(context, attrs, defStyleAttr);
}
@Override
public
void
setAdjustViewBounds(
boolean
adjustViewBounds) {
mAdjustViewBounds = adjustViewBounds;
super
.setAdjustViewBounds(adjustViewBounds);
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
Drawable mDrawable = getDrawable();
if
(mDrawable ==
null
) {
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
return
;
}
if
(mAdjustViewBounds) {
int
mDrawableWidth = mDrawable.getIntrinsicWidth();
int
mDrawableHeight = mDrawable.getIntrinsicHeight();
int
heightSize = MeasureSpec.getSize(heightMeasureSpec);
int
widthSize = MeasureSpec.getSize(widthMeasureSpec);
int
heightMode = MeasureSpec.getMode(heightMeasureSpec);
int
widthMode = MeasureSpec.getMode(widthMeasureSpec);
if
(heightMode == MeasureSpec.EXACTLY && widthMode != MeasureSpec.EXACTLY) {
// Fixed Height & Adjustable Width
int
height = heightSize;
int
width = height * mDrawableWidth / mDrawableHeight;
if
(isInScrollingContainer())
setMeasuredDimension(width, height);
else
setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
}
else
if
(widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
// Fixed Width & Adjustable Height
int
width = widthSize;
int
height = width * mDrawableHeight / mDrawableWidth;
if
(isInScrollingContainer())
setMeasuredDimension(width, height);
else
setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
}
else
{
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
else
{
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
private
boolean
isInScrollingContainer() {
ViewParent p = getParent();
while
(p !=
null
&& p
instanceof
ViewGroup) {
if
(((ViewGroup) p).shouldDelayChildPressedState()) {
return
true
;
}
p = p.getParent();
}
return
false
;
}
}
The way these codes work is straightforward. It would calculate the height proportionally in case the width is fixed and vice versa inside onMeasure
. In case this AdjustableImageView
object is placed inside non-scrollable container, width and height would be limited to the space left in parent. Otherwise, it would be scaled up without any restriction.
To use it, simply change ImageView
tocom.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
in the layout xml.
<
com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:adjustViewBounds
=
"true"
android:src
=
"@mipmap/ic_launcher"
/>
And it is now done !
Make it easy with AdjustableImageView Library
We know that it is such a boring task creating a file, copy the code, paste it, reformat, check if everything is right, blah blah blah.
Your life is now 10 times easier with the library dependency we prepared for you. It is now live on jcenter. Once you add the dependency to your project, AdjustableImageView
and AdjustableImageButton
will be ready to make your day. Source codes of this library are hosted on GitHub. Please feel free to have a look.
Here is the gradle dependency. Just simply add this line to yourbuild.gradle
dependencies {
compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.0'
}
AdjustableImageView
and AdjustableImageButton
are now ready to use inside com.inthecheesefactory.thecheeselibrary.widget.*
package.
Simply replace ImageView and ImageButton with those classes provided by the library.
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:tools
=
"http://schemas.android.com/tools"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"vertical"
tools:context
=
".MainActivity"
>
<
ScrollView
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:fillViewport
=
"true"
>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"vertical"
>
<
com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:adjustViewBounds
=
"true"
android:src
=
"@mipmap/ic_launcher"
/>
<
com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:adjustViewBounds
=
"true"
android:src
=
"@mipmap/ic_launcher"
/>
</
LinearLayout
>
</
ScrollView
>
</
LinearLayout
>
As a result, ImageView is now scaled up perfectly no matter which Android version the application is running on.
This is a good example why we should install multiple SDK Platforms in the machine and not just the latest one. Since if you want to let Android Studio preview your layout with specific Android version, you need to install SDK Platform for that version or it wouldn't be listed as a choice in preview pane. Per my suggestion, you should install every single SDK Platform from API Level 14 on. Loss some disk space but what that you get back is worthy.
Author: nuuneoi (Android GDE, CTO & CEO at The Cheese Factory)- A requirement that almost every single application has is "I want to scale up an ImageView proportio
- How to Create an Application that has Office Style
- I want to say that to myself
- I have a custom view that I want to be able to initialize both in-code and in nib.
- I want to be a teacher when I grow up ——长大后我想当老师
- Every 300th Row has Corrupt or Merged Cell Values When an Analysis is Exported to Excel
- I want to be a good person
- I want to be a learner
- when I want to have a rest
- I Want to Be a PM
- I want to be a nice man
- I want to make a website
- I want to be a 程序猿
- CareerCup Given an array A[], find (i, j) such that A[i] < A[j] and (j - i) is maximum.
- I want to do that you feel proud of me.
- 警告处理 A C3P0Registry mbean is already registered. This probably means that an application using c3p.
- 警告处理 A C3P0Registry mbean is already registered. This probably means that an application using c3p.
- 警告: A C3P0Registry mbean is already registered. This probably means that an application...
- Xshell5 注册码 ,Xftp5 注册码,Xmanager5注册码
- Android 中RelativeLayout 中的scrollview无法滑动
- OKHttp(1)——基本使用
- PHP计划任务:如何使用Linux的Crontab执行PHP脚本
- JAVA冒泡排序
- A requirement that almost every single application has is "I want to scale up an ImageView proportio
- python-mongodb存储文件
- java 多线程深入浅出的分析
- HOG特征向量的代码
- AppleScript 笔记
- Android Intent Standard Actions
- HOG特征
- File类的常用方法
- 查找某个目录下的所有文件(包括子目录)