前言
這篇博客聊一聊在Android下ImageView的使用,在此篇博客中,會講解到ImageView的一些屬性的使用,以及ImageView展示圖片的放大、縮小、旋轉等操作。最后再講解一下Android4.0項目中最常用的一個功能,從網絡獲取圖片的示例。本文所有講解均會附上示例代碼,並在最后提供源碼下載。
ImageView
ImageView,圖像視圖,直接繼承自View類,它的主要功能是用於顯示圖片,實際上它不僅僅可以用來顯示圖片,任何Drawable對象都可以使用ImageView來顯示。ImageView可以適用於任何布局中,並且Android為其提供了縮放和着色的一些操作。
ImageView的一些常用屬性,並且這些屬性都有與之對應的getter、setter方法:
- android:adjustViewBounds:設置ImageView是否調整自己的邊界來保持所顯示圖片的長寬比。
- android:maxHeight:設置ImageView的最大高度。
- android:maxWidth:設置ImageView的最大寬度。
- android:scaleType:設置所顯示的圖片如何縮放或移動以適應ImageView的大小。
- android:src:設置ImageView所顯示的Drawable對象的ID。
對於android:scaleType屬性,因為關於圖像在ImageView中的顯示效果,所以有如下屬性值可以選擇:
- matrix:使用matrix方式進行縮放。
- fitXY:橫向、縱向獨立縮放,以適應該ImageView。
- fitStart:保持縱橫比縮放圖片,並且將圖片放在ImageView的左上角。
- fitCenter:保持縱橫比縮放圖片,縮放完成后將圖片放在ImageView的中央。
- fitEnd:保持縱橫比縮放圖片,縮放完成后將圖片放在ImageView的右下角。
- center:把圖片放在ImageView的中央,但是不進行任何縮放。
- centerCrop:保持縱橫比縮放圖片,以使圖片能完全覆蓋ImageView。
- centerInside:保持縱橫比縮放圖片,以使得ImageView能完全顯示該圖片。
圖片基本顯示
下面通過一個示例效果,來說明一下ImageView是如何顯示圖片的,再此示例中,需要使用到一個green.png的圖片,需要放到Drawable文件夾下,關於Android的資源文件,以后再進行詳解。
布局代碼:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:text="scaleType:center,未縮放,在ImageView的中心" /> 11 12 <ImageView 13 android:id="@+id/imageview1" 14 android:layout_width="200dp" 15 android:layout_height="100dp" 16 android:background="#F00" 17 android:scaleType="center" 18 android:src="@drawable/green" /> 19 20 <TextView 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:text="scaleType:fitCenter,按比例縮放" /> 24 25 <ImageView 26 android:id="@+id/imageview2" 27 android:layout_width="300dp" 28 android:layout_height="200dp" 29 android:background="#FFF" 30 android:padding="10dp" 31 android:scaleType="fitCenter" 32 android:src="@drawable/green" /> 33 34 </LinearLayout>
效果展示:
縮放與旋轉圖片
因為ImageView繼承自View,所以在代碼中設置其大小,可以使用View.setLayoutParams(new LinearLayout.LayoutParams(newWidth,newHeight))方法,這個方法可以直接設定View下的所有控件的外觀大小,所以這里也適用於ImageView。
而對於ImageView的旋轉,這里涉及到一個Matrix類的使用。它表示一個3x3的坐標變換矩陣,可以在這個矩陣內,對其進行變換、旋轉操作,它需要通過構造函數顯式的初始化之后才可以使用。
下面通過一個示例來說明一下圖片的放大縮小與旋轉的示例,在示例中會提供兩個SeekBar,對於SeekBar如果不了解的話,可以參見我的另外一篇博客,Android—UI之Progress。這兩個SeekBar一個設置ImageView顯示圖片的大小,另一個設置旋轉的角度。對於圖片大小,通過DisplayMetrics設置屏幕的寬度為圖像的最大寬度,具體操作在注釋中已經寫明,這里不在累述。
布局代碼:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <ImageView 8 android:id="@+id/imageview3" 9 android:layout_width="200dp" 10 android:layout_height="150dp" 11 android:scaleType="fitCenter" 12 android:src="@drawable/green" /> 13 14 <TextView 15 android:id="@+id/tv1" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:layout_marginTop="10dp" 19 android:text="圖像寬度:240 圖像高度:150" /> 20 21 <SeekBar 22 android:id="@+id/sbSize" 23 android:layout_width="200dp" 24 android:layout_height="wrap_content" 25 android:layout_marginTop="10dp" 26 android:max="240" 27 android:progress="120" /> 28 29 <TextView 30 android:id="@+id/tv2" 31 android:layout_width="match_parent" 32 android:layout_height="wrap_content" 33 android:layout_marginTop="10dp" 34 android:text="0°" /> 35 36 <SeekBar 37 android:id="@+id/sbRotate" 38 android:layout_width="200dp" 39 android:layout_height="wrap_content" 40 android:layout_marginTop="10dp" 41 android:max="360" /> 42 43 </LinearLayout>
實現代碼:
1 package com.bgxt.imageviewdemo; 2 3 import android.annotation.SuppressLint; 4 import android.app.Activity; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.graphics.Matrix; 8 import android.graphics.drawable.BitmapDrawable; 9 import android.os.Bundle; 10 import android.util.DisplayMetrics; 11 12 import android.widget.ImageView; 13 import android.widget.LinearLayout; 14 import android.widget.SeekBar; 15 import android.widget.SeekBar.OnSeekBarChangeListener; 16 import android.widget.TextView; 17 18 @SuppressLint("NewApi") 19 public class ChangeImageActivity extends Activity implements 20 OnSeekBarChangeListener { 21 private int minWidth = 80; 22 private ImageView imageView; 23 private TextView textview1, textview2; 24 Matrix matrix=new Matrix(); 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 // TODO Auto-generated method stub 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.layout_changeimage); 31 32 imageView = (ImageView) findViewById(R.id.imageview3); 33 SeekBar seekbar1 = (SeekBar) findViewById(R.id.sbSize); 34 SeekBar seekbar2 = (SeekBar) findViewById(R.id.sbRotate); 35 textview1 = (TextView) findViewById(R.id.tv1); 36 textview2 = (TextView) findViewById(R.id.tv2); 37 38 //獲取當前屏幕的尺寸,並設置圖片放大的最大尺寸,不能超過屏幕尺寸 39 DisplayMetrics dm = new DisplayMetrics(); 40 getWindowManager().getDefaultDisplay().getMetrics(dm); 41 seekbar1.setMax(dm.widthPixels - minWidth); 42 43 seekbar1.setOnSeekBarChangeListener(this); 44 seekbar2.setOnSeekBarChangeListener(this); 45 } 46 47 @Override 48 public void onProgressChanged(SeekBar seekBar, int progress, 49 boolean fromUser) { 50 if (seekBar.getId() == R.id.sbSize) { 51 //設置圖片的大小 52 int newWidth=progress+minWidth; 53 int newHeight=(int)(newWidth*3/4); 54 imageView.setLayoutParams(new LinearLayout.LayoutParams(newWidth, newHeight)); 55 textview1.setText("圖像寬度:"+newWidth+"圖像高度:"+newHeight); 56 } else if (seekBar.getId() == R.id.sbRotate){ 57 //獲取當前待旋轉的圖片 58 Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.green); 59 //設置旋轉角度 60 matrix.setRotate(progress,30,60); 61 //通過待旋轉的圖片和角度生成新的圖片 62 bitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true); 63 //綁定圖片到控件上 64 imageView.setImageBitmap(bitmap); 65 textview2.setText(progress+"°"); 66 } 67 } 68 69 @Override 70 public void onStartTrackingTouch(SeekBar seekBar) { 71 // TODO Auto-generated method stub 72 73 } 74 75 @Override 76 public void onStopTrackingTouch(SeekBar seekBar) { 77 // TODO Auto-generated method stub 78 79 } 80 81 }
效果展示:
從互聯網獲取圖片
一個移動的平台開發,很多資源是不可能一直保存在本地的,更多實時性的東西,是需要直接通過網絡及時獲取的。這里通過一個從網上獲取圖片展示到ImageView的例子,來講解一下這個功能的實現。
在Android4.0之后,增加了一些新特性,也增加了一些限制。其中有一個限制就是不能在主線程中訪問網絡,必須另開一條線程訪問。但是這里又存在另外一個問題,在子線程中,無法直接操作UI控件的屬性。如果你們使用的開發平台是Android4.0之下,就不存在這個問題,直接在主線程中訪問網絡操作UI控件即可。
我的解決方案就是,通過Thread類,進行多線程訪問網絡,再通過Handler類,進行消息傳遞。對於Thread類,是Java的知識,不再詳細講解,對於Handler類,這里簡要說明一下。
在Android平台下,不允許Activity新啟動的線程訪問該Activity里的界面UI控件,這樣就會導致新啟動的線程無法動態改變界面UI控件的屬性值。所以就需要借助Handler的消息傳遞機制來實現。Handler類的主要作用有兩個:
- 在新啟動的線程中發送消息。
- 在主線程中獲取、處理消息。
上面描述的兩個作用,發送消息好說,在需要的時候發送,那怎么確定什么時候接收消息呢?為了讓主線程能接受並處理新啟動的線程發送的消息,Android通過回調的方式來實現,開發人員只需要重寫Handler類中處理消息的方法,handleMessage(Message)即可,其中Message封裝了發送過來的消息。
Handler包含如下方法,用於實現發送和處理消息:
- void handleMessage(Message msg):處理消息的方法,用於被重寫。
- final boolean hasMessage(int what):檢查消息隊列中是否包含what屬性為指定值的消息。
- sendEmptyMessage(int what):立即發送空消息。
- final boolean sendEmptyMessageDelayed(int what,long delayMillis):指定delayMillis毫秒之后發送空消息。
- final boolean sendMessage(Message msg):立即發送消息。
- final boolean sendMessageDelayed(Message msg,long delayMillis):指定delayMillis毫秒之后發送消息。
Message封裝了線程中傳遞的消息,如果對於一般的數據,Message提供了getData()和setData()方法來獲取與設置數據,其中操作的數據是一個Bundle對象,這個Bundle對象提供一系列的getXxx()和setXxx()方法用於傳遞基本數據類型,對於基本數據類型,使用起來很簡單,這里不再詳細講解。而對於復雜的數據類型,如一個對象的傳遞就要相對復雜一些。在Bundle中提供了兩個方法,專門用來傳遞對象的,但是這兩個方法也有相應的限制,需要實現特定的接口,當然,一些Android自帶的類,其實已經實現了這兩個接口中的某一個,可以直接使用。方法如下:
- putParcelable(String key,Parcelable value):需要傳遞的對象類實現Parcelable接口。
- pubSerializable(String key,Serializable value):需要傳遞的對象類實現Serializable接口。
還有另外一種方式在Message中傳遞對象,那就是使用Message自帶的obj屬性傳值,它是一個Object類型,所以可以傳遞任意類型的對象,Message自帶的有如下幾個屬性:
- int arg1:參數一,用於傳遞不復雜的數據,復雜數據使用setData()傳遞。
- int arg2:參數二,用於傳遞不復雜的數據,復雜數據使用setData()傳遞。
- Object obj:傳遞一個任意的對象。
- int what:定義的消息碼,一般用於確定消息的來源。
下面這個示例,使用了兩種方式獲取傳遞消息,以一個隨機數確定。在這個示例中,訪問網絡的代碼會附上但是不會詳解,如果對於Android中訪問網絡不熟悉的朋友,可以參見我另外一篇博客,Android--Http協議。
布局代碼:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 8 <Button android:id="@+id/btnInternet" android:layout_width="wrap_content" 9 android:layout_height="wrap_content" android:text="下載網絡圖片"/> 10 <TextView android:id="@+id/tbMsgType" android:layout_width="match_parent" 11 android:layout_height="wrap_content"/> 12 <ImageView android:id="@+id/ivInternet" android:layout_width="wrap_content" 13 android:layout_height="wrap_content"/> 14 </LinearLayout>
實現代碼:
1 package com.bgxt.imageviewdemo; 2 3 import java.io.InputStream; 4 import java.net.HttpURLConnection; 5 import java.util.Random; 6 7 import com.bgxt.httputils.HttpUtils; 8 9 import android.app.Activity; 10 import android.graphics.Bitmap; 11 import android.graphics.BitmapFactory; 12 import android.os.Bundle; 13 import android.os.Handler; 14 import android.os.Message; 15 import android.view.View; 16 import android.widget.Button; 17 import android.widget.ImageView; 18 import android.widget.TextView; 19 import android.widget.Toast; 20 21 public class InternetImageActivity extends Activity { 22 private Button btnInternet; 23 private ImageView ivInternet; 24 private TextView tvMsgType; 25 private Handler handler; 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 // TODO Auto-generated method stub 30 super.onCreate(savedInstanceState); 31 setContentView(R.layout.activity_internetimage); 32 33 btnInternet = (Button) findViewById(R.id.btnInternet); 34 ivInternet = (ImageView) findViewById(R.id.ivInternet); 35 tvMsgType = (TextView) findViewById(R.id.tbMsgType); 36 37 // 定義一個handler,用於接收消息 38 handler = new Handler() { 39 @Override 40 public void handleMessage(Message msg) { 41 Bitmap bmp = null; 42 // 通過消息碼確定使用什么方式傳遞圖片信息 43 if (msg.what == 0) { 44 bmp = (Bitmap) msg.obj; 45 tvMsgType.setText("使用obj傳遞數據"); 46 } else { 47 Bundle ble = msg.getData(); 48 bmp = (Bitmap) ble.get("bmp"); 49 tvMsgType.setText("使用Bundle傳遞數據"); 50 } 51 // 設置圖片到ImageView中 52 ivInternet.setImageBitmap(bmp); 53 } 54 }; 55 56 btnInternet.setOnClickListener(new View.OnClickListener() { 57 @Override 58 public void onClick(View v) { 59 //清空之前獲取的數據 60 tvMsgType.setText(""); 61 ivInternet.setImageBitmap(null); 62 //定義一個線程類 63 new Thread() { 64 @Override 65 public void run() { 66 try { 67 //獲取網絡圖片 68 InputStream inputStream = HttpUtils 69 .getImageViewInputStream(); 70 Bitmap bitmap = BitmapFactory 71 .decodeStream(inputStream); 72 Message msg = new Message(); 73 Random rd = new Random(); 74 int ird = rd.nextInt(10); 75 //通過一個隨機數,隨機選擇通過什么方式傳遞圖片信息到消息中 76 if (ird / 2 == 0) { 77 msg.what = 0; 78 msg.obj = bitmap; 79 } else { 80 Bundle bun = new Bundle(); 81 bun.putParcelable("bmp", bitmap); 82 msg.what = 1; 83 msg.setData(bun); 84 } 85 //發送消息 86 handler.sendMessage(msg); 87 } catch (Exception e) { 88 89 } 90 } 91 }.start(); 92 } 93 }); 94 } 95 }
訪問網絡類,代碼:
1 package com.bgxt.httputils; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.net.HttpURLConnection; 6 import java.net.URL; 7 8 public class HttpUtils { 9 private final static String URL_PATH = "http://ww4.sinaimg.cn/bmiddle/9e58dccejw1e6xow22oc6j20c80gyaav.jpg"; 10 11 public HttpUtils() { 12 } 13 14 public static InputStream getImageViewInputStream() throws IOException { 15 InputStream inputStream = null; 16 URL url = new URL(URL_PATH); 17 if (url != null) { 18 HttpURLConnection httpURLConnection = (HttpURLConnection) url 19 .openConnection(); 20 httpURLConnection.setConnectTimeout(3000); 21 httpURLConnection.setRequestMethod("GET"); 22 httpURLConnection.setDoInput(true); 23 int response_code = httpURLConnection.getResponseCode(); 24 if (response_code == 200) { 25 inputStream = httpURLConnection.getInputStream(); 26 } 27 } 28 return inputStream; 29 } 30 }
效果展示:
總結
以上就講解了ImageView的一些基本使用,對於Android項目而言,一般的用到更多的就是從網絡獲取圖片的功能,所以這里着重講解了一下。
請支持原創,尊重原創,轉載請注明出處。謝謝。