一个关于 imageView 设置 scaleType 的问题。

  就在刚才 晚上9 点多的时候,我的一个外包伙伴发一个工程代码我,叫我去看下这样一个"bug",说折腾了很久,图片选择器在选择完图片后,就要显示图片到界面上,大家可以想象下 微信 发表图片,因为我们相机的图片肯定是 长宽都不一致的,为了统一格式,一般都是把要显示出来的 imageView 设置成 scaleType = centerCrop 或者 center。

  问题就是:他在设置了上面的属性后,宛然无效!imageView 设置成 scaleType = centerCrop 或者 center,对图片没效果。

  先上事例图:

  理想效果 和 问题效果(左->右):

    

  公用的 xml:

 <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <LinearLayout
android:id="@+id/images_container"
android:paddingLeft="10dp"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"> </LinearLayout> </RelativeLayout>

  我们来看看出问题的代码:

  imageView 的 xml:

 <?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image_one"
android:scaleType="centerCrop"
android:layout_width="30dp"
android:layout_height="30dp" />

  他设置了动态 addView() 的方法 添加用户选中的 图片,java 代码,为了避免长篇大论,我已做简化,事例效果一样:

 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
final ImageView image = (ImageView) LayoutInflater.from(this).inflate(R.layout.send_post_image, null, false);
LinearLayout images_container = (LinearLayout) findViewById(R.id.images_container);
image.setImageResource(R.drawable.beni);
images_container.addView(image);
}

这样的代码,貌似没什么问题,通过 LayoutInflater.from(this).inflate(...) 来事例化一个 View,而最为之关键的是,这个View 就是上面的 imageView的xml,里面明确设置了 width 和 height 是 30dp,显示方式是 centerCrop,最后通过 addView 添加到一个 linearLayout 中。但是,这份代码显示出来的效果是 右图,非 理想效果!!哈哈,感觉恍然大悟吧。

  你可能会有这样一个印象,我们绝大多项目或者是练习中的 imageVIew 使用都是直接 findViewById, 一样的 imageView 设置,却没问题, 没错,的确没问题,你可以把上面的代码替换为这个试试:

   test.xml 换为:

 <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <LinearLayout
android:id="@+id/images_container"
android:paddingLeft="10dp"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:scaleType="centerCrop"
android:layout_width="30dp"
android:layout_height="30dp" /> </LinearLayout> </RelativeLayout>

  java 换为

 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
final ImageView image = (ImageView)findViewById(R.id.image);
image.setImageResource(R.drawable.beni);
}

  这样显示出来的 效果 就是我们所 期望的。

   为什么通过 addView() 的方法却败了呢?

   问题的原因是这样的:任何使用 addView(...) 的方法,无论你所实例化的 View 本身的 xml 的 width 和 height 设置了什么,都是没效果的,请看清楚,是 width height 失效,上面的 scaleType 是有效的, 问题 java 代码中调用 addView 的时候并没有传入 LayoutParam 布局参数,好了,我们来 粘下 源码,见证真相只有一个。

 /**
* <p>Adds a child view. If no layout parameters are already set on the child, the
* default parameters for this ViewGroup are set on the child.</p>
*
* <p><strong>Note:</strong> do not invoke this method from
* {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},
* {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
*
* @param child the child view to add
*
* @see #generateDefaultLayoutParams()
*/
public void addView(View child) {
addView(child, -1);
} public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
} protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}

  因为没有自己传入 LayoutParam 而 get 的又是 null ,为什么 get 的会是null,请在上面的事例代码中加入这句 log ,Log.d("zzzzz",""+image.getLayoutParams()); ,就会看到输出 null 了,而最终调用源码的:

protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
直接使用了 Wrap_parent,所以啊,导致了失效。那我就是要使用 addView 怎么办?自己加个宽高限制即可。
 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
final ImageView image = (ImageView) LayoutInflater.from(this).inflate(R.layout.send_post_image, null, false);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(50,50); /** 这里 */
LinearLayout images_container = (LinearLayout) findViewById(R.id.images_container);
image.setLayoutParams(lp); /** 添加 */
image.setImageResource(R.drawable.beni);
Log.d("zzzzz", "" + image.getLayoutParams());
images_container.addView(image);
}

行了,快1点了。。。。

  总结下。 导致这样的事情发生,我觉得还是缺少自己动手踏实编码的问题,现在框架比较泛滥了,又想起了那句老话:我们不生产代码,我们都是 github 的搬运工 ...

 

一个难倒 3年 android开发经验 " 工程师 " 的 "bug"的更多相关文章

  1. 帮朋友急招PHP、Android开发工程师 西安 工资8k-12k

    PHP高级工程师岗位要求: 1. 有两年以上PHP开发经验, 2. 精通PHP+MySQL程序设计及开发,拥有良好的代码习惯,要求结构清晰,命名规范,逻辑性强,代码冗余率低. 3. 熟悉面向对象的软件 ...

  2. 写给 Android 应用工程师的 Binder 原理剖析

    写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...

  3. Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式

    Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式 Fragment FragmentManager frag ...

  4. Android开发工程师文集-Activity生命周期,启动方式,Intent相关介绍,Activity详细讲解

    前言 大家好,给大家带来Android开发工程师文集-Activity生命周期,启动方式,Intent相关介绍,Activity详细讲解的概述,希望你们喜欢 Activity是什么 作为一个Activ ...

  5. Android开发工程师文集-相关控件的讲解,五大布局

    前言 大家好,给大家带来Android开发工程师文集-相关控件的讲解,五大布局的概述,希望你们喜欢 TextView控件 TextView控件有哪些属性: android:id->控件的id a ...

  6. Android开发工程师文集-1 小时学会SQLite

    前言 大家好,给大家带来Android开发工程师文集-1 小时学会SQLite的概述,希望你们喜欢 内容 什么是Sqlite: 效率高,开源,小型,程序驱动,支持事务操作,无数据类型,可嵌入的关系型数 ...

  7. datetimepicker一个不错的日历android特效

    datetimepicker一个不错的日历效,选中和选择日历效果都很不错, 实用的时候直接可以把datetimepicker-library这个引入到项目,调用的地方在实现 TimePickerDia ...

  8. Android进阶笔记09:Android开发经验部分总结

    1. 在Android library中不能使用switch-case语句访问资源ID:在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案 2. 不能 ...

  9. webview之如何设计一个优雅健壮的Android WebView?(下)(转)

    转载:https://iluhcm.com/2018/02/27/design-an-elegant-and-powerful-android-webview-part-two/ (这篇文章写得有点晚 ...

随机推荐

  1. 微信公众号开发之VS远程调试

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 前言 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流 ...

  2. Windows server 2012 添加中文语言包(英文转为中文)(离线)

    Windows server 2012 添加中文语言包(英文转为中文)(离线) 相关资料: 公司环境:亚马孙aws虚拟机 英文版Windows2012 中文SQL Server2012安装包,需要安装 ...

  3. macOS 我的装机

    最近多次配置 Mac 的开发环境,稍微记录一下 1 创建无付费信息的Apple ID 2 Xcode ​ gem 源更改 3 Alfred 4 微信 5 SourceTree 6 Sublime Te ...

  4. Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect)

    Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect) [TOC] 这两个方法的区别 View.ge ...

  5. 一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)

    在目前的软件项目中,都会较多的使用到对文档的操作,用于记录和统计相关业务信息.由于系统自身提供了对文档的相关操作,所以在一定程度上极大的简化了软件使用者的工作量. 在.NET项目中如果用户提出了相关文 ...

  6. 玩转ajax

    1.什么是ajax? Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写. 2.ajax需要什么基础? HTML 用于建立 Web 表单并确定应 ...

  7. Android Studio切换为eclipse的快捷键之后还是有区别的部分快捷键

    Android Studio Eclipse 把代码提示换成了Class Name Completion, 快捷键是Ctrl+Alt+Space(空格键). 代码提示快捷键Alt+/,         ...

  8. Android之SharedPreferences数据存储

    一.SharedPreferences保存数据介绍 如果有想要保存的相对较小键值集合,应使用SharedPreferences API.SharedPreferences对象指向包含键值对的文件并提供 ...

  9. 如何使用dos命令查看MySQL当前使用的数据库?

    1.dos命令安装mysqld --stall.启动net start mysql.进入MySQL数据库mysql -uroot -p后,输入select database(); 如图:

  10. Hibernate 系列 学习笔记 目录 (持续更新...)

    前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...