Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 一個難倒 3年 android開發經驗 工程師 的 bug

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

編輯:關於Android編程

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

  就在剛才 晚上9 點多的時候,我的一個外包伙伴發一個工程代碼我,叫我去看下這樣一個"bug",說折騰了很久,圖片選擇器在選擇完圖片後,就要顯示圖片到界面上,大家可以想象下 微信 發表圖片,因為我們相機的圖片肯定是 長寬都不一致的,為了統一格式,一般都是把要顯示出來的 imageView 設置成 scaleType = centerCrop 或者 center。

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

  先上事例圖:

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

   \ \

  公用的 xml:

\
 1 <relativelayout 2="" 3="" 4="" 5="" 6="" 7="" 8="" 9="" 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">
10 
11     <linearlayout 12="" 13="" 14="" 15="" 16="" android:id="@+id/images_container" android:paddingleft="10dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
17         
18 
19 
20     </linearlayout>
21 
22 
23 </relativelayout>

  我們來看看出問題的代碼:

  imageView 的 xml:

\
1 <!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%2D%2D%3E-->
2 <imageview 3="" 4="" 5="" 6="" 7="" 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"></imageview>

  他設置了動態 addView() 的方法 添加用戶選中的 圖片,java 代碼,為了避免長篇大論,我已做簡化,事例效果一樣:

\
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     }

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

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

   test.xml 換為:

\
 1 <relativelayout 2="" 3="" 4="" 5="" 6="" 7="" 8="" 9="" 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">
10 
11     <linearlayout 12="" 13="" 14="" 15="" 16="" android:id="@+id/images_container" android:paddingleft="10dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
17         <imageview 18="" 19="" 20="" 21="" android:id="@+id/image" android:scaletype="centerCrop" android:layout_width="30dp" android:layout_height="30dp">
22 
23 
24     </imageview></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     }

  這樣顯示出來的 效果 就是我們所 期望的。

   為什麼通過 addView() 的方法卻敗了呢?

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

\
 1 /**
 2      * 

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.

4 * 5 *

Note: 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.

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     }

行了,快1點了。。。。

  總結下。 導致這樣的事情發生,我覺得還是缺少自己動手踏實編碼的問題,現在框架比較泛濫了,又想起了那句老話:我們不生產代碼,我們都是 github 的搬運工 ...

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved