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

來源:互聯網
上載者:User

標籤:

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

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

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

  先上案例圖:

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

    

  公用的 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     <LinearLayout12         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

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

  imageView 的 xml:

1 <?xml version="1.0" encoding="utf-8"?>2 <ImageView3     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 代碼,為了避免長篇大論,我已做簡化,案例效果一樣:

1 @Override2     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 中。但是,這份代碼顯示出來的效果是 右圖,非 理想效果!!哈哈,感覺恍然大悟吧。

  你可能會有這樣一個印象,我們絕大多項目或者是練習中的 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     <LinearLayout12         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         <ImageView18             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 @Override2     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 add10      *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 的搬運工 ...

 

 

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.