一個難倒 3年 android開發經驗 " 工程師 " 的 "bug"

  一個關於 imageView 設置 scaleType 的問題。java

  就在剛纔 晚上9 點多的時候,個人一個外包伙伴發一個工程代碼我,叫我去看下這樣一個"bug",說折騰了好久,圖片選擇器在選擇完圖片後,就要顯示圖片到界面上,你們能夠想象下 微信 發表圖片,由於咱們相機的圖片確定是 長寬都不一致的,爲了統一格式,通常都是把要顯示出來的 imageView 設置成 scaleType = centerCrop 或者 center。android

  問題就是:他在設置了上面的屬性後,宛然無效!imageView 設置成 scaleType = centerCrop 或者 center,對圖片沒效果。git

  先上事例圖:github

  理想效果 和 問題效果(左->右):微信

    

  公用的 xml:框架

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context=".MainActivity" >
10 
11     <LinearLayout
12         android:id="@+id/images_container"
13         android:paddingLeft="10dp"
14         android:orientation="horizontal"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content">
17         
18 
19 
20     </LinearLayout>
21 
22 
23 </RelativeLayout>
View Code

  咱們來看看出問題的代碼:ide

  imageView 的 xml:佈局

1 <?xml version="1.0" encoding="utf-8"?>
2 <ImageView
3     xmlns:android="http://schemas.android.com/apk/res/android"
4     android:id="@+id/image_one"
5     android:scaleType="centerCrop"
6     android:layout_width="30dp"
7     android:layout_height="30dp" />
View Code

  他設置了動態 addView() 的方法 添加用戶選中的 圖片,java 代碼,爲了不長篇大論,我已作簡化,事例效果同樣:post

1 @Override
2     protected void onCreate(Bundle savedInstanceState) {
3         super.onCreate(savedInstanceState);
4         setContentView(R.layout.test);
5         final ImageView image = (ImageView) LayoutInflater.from(this).inflate(R.layout.send_post_image, null, false);
6         LinearLayout images_container = (LinearLayout) findViewById(R.id.images_container);
7         image.setImageResource(R.drawable.beni);
8         images_container.addView(image);
9     }
View Code

     這樣的代碼,貌似沒什麼問題,經過 LayoutInflater.from(this).inflate(...) 來事例化一個 View,而最爲之關鍵的是,這個View 就是上面的 imageView的xml,裏面明確設置了 width 和 height 是 30dp,顯示方式是 centerCrop,最後經過 addView 添加到一個 linearLayout 中。可是,這份代碼顯示出來的效果是 右圖,非 理想效果!!哈哈,感受恍然大悟吧。this

  你可能會有這樣一個印象,咱們絕大多項目或者是練習中的 imageVIew 使用都是直接 findViewById, 同樣的 imageView 設置,卻沒問題, 沒錯,的確沒問題,你能夠把上面的代碼替換爲這個試試:

   test.xml 換爲:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context=".MainActivity" >
10 
11     <LinearLayout
12         android:id="@+id/images_container"
13         android:paddingLeft="10dp"
14         android:orientation="horizontal"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content">
17         <ImageView
18             android:id="@+id/image"
19             android:scaleType="centerCrop"
20             android:layout_width="30dp"
21             android:layout_height="30dp" />
22 
23 
24     </LinearLayout>
25 
26 
27 </RelativeLayout>
View Code

  java 換爲

1 @Override
2     protected void onCreate(Bundle savedInstanceState) {
3         super.onCreate(savedInstanceState);
4         setContentView(R.layout.test);
5         final ImageView image = (ImageView)findViewById(R.id.image);
6         image.setImageResource(R.drawable.beni);
7     }
View Code

  這樣顯示出來的 效果 就是咱們所 指望的。

   爲何經過 addView() 的方法卻敗了呢

   問題的緣由是這樣的:任何使用 addView(...) 的方法,不管你所實例化的 View 自己的 xml 的 width 和 height 設置了什麼,都是沒效果的,請看清楚,是 width height 失效,上面的 scaleType 是有效的, 問題 java 代碼中調用 addView 的時候並無傳入 LayoutParam 佈局參數,好了,咱們來 粘下 源碼,見證真相只有一個。

 1 /**
 2      * <p>Adds a child view. If no layout parameters are already set on the child, the
 3      * default parameters for this ViewGroup are set on the child.</p>
 4      * 
 5      * <p><strong>Note:</strong> do not invoke this method from
 6      * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},
 7      * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
 8      *
 9      * @param child the child view to add
10      *
11      * @see #generateDefaultLayoutParams()
12      */
13     public void addView(View child) {
14         addView(child, -1);
15     }
16 
17 public void addView(View child, int index) {
18         if (child == null) {
19             throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
20         }
21         LayoutParams params = child.getLayoutParams();
22         if (params == null) {
23             params = generateDefaultLayoutParams();
24             if (params == null) {
25                 throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
26             }
27         }
28         addView(child, index, params);
29     }
30 
31 protected LayoutParams generateDefaultLayoutParams() {
32         return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
33     }
View Code

  由於沒有本身傳入 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 怎麼辦?本身加個寬高限制便可。
 1 @Override
 2     protected void onCreate(Bundle savedInstanceState) {
 3         super.onCreate(savedInstanceState);
 4         setContentView(R.layout.test);
 5         final ImageView image = (ImageView) LayoutInflater.from(this).inflate(R.layout.send_post_image, null, false);
 6         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(50,50); /** 這裏 */
 7         LinearLayout images_container = (LinearLayout) findViewById(R.id.images_container);
 8         image.setLayoutParams(lp); /** 添加 */
 9         image.setImageResource(R.drawable.beni);
10         Log.d("zzzzz", "" + image.getLayoutParams());
11         images_container.addView(image);
12     }
View Code

 

行了,快1點了。。。。

  總結下。 致使這樣的事情發生,我以爲仍是缺乏本身動手踏實編碼的問題,如今框架比較氾濫了,又想起了那句老話:咱們不生產代碼,咱們都是 github 的搬運工 ...

相關文章
相關標籤/搜索