編輯:Android開發實例
前言
這篇聊一聊在Android下ImageView的使用,在此篇中,會講解到ImageView的一些屬性的使用,以及ImageView展示圖片的放大、縮小、旋轉等操作。最後再講解一下Android4.0項目中最常用的一個功能,從網絡獲取圖片的示例。本文所有講解均會附上示例代碼,並在最後提供源碼下載。
ImageView
ImageView,圖像視圖,直接繼承自View類,它的主要功能是用於顯示圖片,實際上它不僅僅可以用來顯示圖片,任何Drawable對象都可以使用ImageView來顯示。ImageView可以適用於任何布局中,並且Android為其提供了縮放和著色的一些操作。
ImageView的一些常用屬性,並且這些屬性都有與之對應的getter、setter方法:
對於android:scaleType屬性,因為關於圖像在ImageView中的顯示效果,所以有如下屬性值可以選擇:
圖片基本顯示
下面通過一個示例效果,來說明一下ImageView是如何顯示圖片的,再此示例中,需要使用到一個green.png的圖片,需要放到Drawable文件夾下,關於Android的資源文件,以後再進行詳解。
布局代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="scaleType:center,未縮放,在ImageView的中心" />
- <ImageView
- android:id="@+id/imageview1"
- android:layout_width="200dp"
- android:layout_height="100dp"
- android:background="#F00"
- android:scaleType="center"
- android:src="@drawable/green" />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="scaleType:fitCenter,按比例縮放" />
- <ImageView
- android:id="@+id/imageview2"
- android:layout_width="300dp"
- android:layout_height="200dp"
- android:background="#FFF"
- android:padding="10dp"
- android:scaleType="fitCenter"
- android:src="@drawable/green" />
- </LinearLayout>
效果展示:
縮放與旋轉圖片
因為ImageView繼承自View,所以在代碼中設置其大小,可以使用View.setLayoutParams(new LinearLayout.LayoutParams(newWidth,newHeight))方法,這個方法可以直接設定View下的所有控件的外觀大小,所以這裡也適用於ImageView。
而對於ImageView的旋轉,這裡涉及到一個Matrix類的使用。它表示一個3x3的坐標變換矩陣,可以在這個矩陣內,對其進行變換、旋轉操作,它需要通過構造函數顯式的初始化之後才可以使用。
下面通過一個示例來說明一下圖片的放大縮小與旋轉的示例,在示例中會提供兩個SeekBar,對於SeekBar如果不了解的話,可以參見我的另外一篇,http://www.fengfly.com/plus/view-213382-1.html。這兩個SeekBar一個設置ImageView顯示圖片的大小,另一個設置旋轉的角度。對於圖片大小,通過DisplayMetrics設置屏幕的寬度為圖像的最大寬度,具體操作在注釋中已經寫明,這裡不在累述。
布局代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <ImageView
- android:id="@+id/imageview3"
- android:layout_width="200dp"
- android:layout_height="150dp"
- android:scaleType="fitCenter"
- android:src="@drawable/green" />
- <TextView
- android:id="@+id/tv1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:text="圖像寬度:240 圖像高度:150" />
- <SeekBar
- android:id="@+id/sbSize"
- android:layout_width="200dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:max="240"
- android:progress="120" />
- <TextView
- android:id="@+id/tv2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:text="0°" />
- <SeekBar
- android:id="@+id/sbRotate"
- android:layout_width="200dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:max="360" />
- </LinearLayout>
實現代碼:
- package com.bgxt.imageviewdemo;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Matrix;
- import android.graphics.drawable.BitmapDrawable;
- import android.os.Bundle;
- import android.util.DisplayMetrics;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.SeekBar;
- import android.widget.SeekBar.OnSeekBarChangeListener;
- import android.widget.TextView;
- @SuppressLint("NewApi")
- public class ChangeImageActivity extends Activity implements
- OnSeekBarChangeListener {
- private int minWidth = 80;
- private ImageView imageView;
- private TextView textview1, textview2;
- Matrix matrix=new Matrix();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.layout_changeimage);
- imageView = (ImageView) findViewById(R.id.imageview3);
- SeekBar seekbar1 = (SeekBar) findViewById(R.id.sbSize);
- SeekBar seekbar2 = (SeekBar) findViewById(R.id.sbRotate);
- textview1 = (TextView) findViewById(R.id.tv1);
- textview2 = (TextView) findViewById(R.id.tv2);
- //獲取當前屏幕的尺寸,並設置圖片放大的最大尺寸,不能超過屏幕尺寸
- DisplayMetrics dm = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- seekbar1.setMax(dm.widthPixels - minWidth);
- seekbar1.setOnSeekBarChangeListener(this);
- seekbar2.setOnSeekBarChangeListener(this);
- }
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- if (seekBar.getId() == R.id.sbSize) {
- //設置圖片的大小
- int newWidth=progress+minWidth;
- int newHeight=(int)(newWidth*3/4);
- imageView.setLayoutParams(new LinearLayout.LayoutParams(newWidth, newHeight));
- textview1.setText("圖像寬度:"+newWidth+"圖像高度:"+newHeight);
- } else if (seekBar.getId() == R.id.sbRotate){
- //獲取當前待旋轉的圖片
- Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.green);
- //設置旋轉角度
- matrix.setRotate(progress,30,60);
- //通過待旋轉的圖片和角度生成新的圖片
- bitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
- //綁定圖片到控件上
- imageView.setImageBitmap(bitmap);
- textview2.setText(progress+"°");
- }
- }
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- // TODO Auto-generated method stub
- }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // TODO Auto-generated method stub
- }
- }
效果展示:
從互聯網獲取圖片
一個移動的平台開發,很多資源是不可能一直保存在本地的,更多實時性的東西,是需要直接通過網絡及時獲取的。這裡通過一個從網上獲取圖片展示到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包含如下方法,用於實現發送和處理消息:
Message封裝了線程中傳遞的消息,如果對於一般的數據,Message提供了getData()和setData()方法來獲取與設置數據,其中操作的數據是一個Bundle對象,這個Bundle對象提供一系列的getXxx()和setXxx()方法用於傳遞基本數據類型,對於基本數據類型,使用起來很簡單,這裡不再詳細講解。而對於復雜的數據類型,如一個對象的傳遞就要相對復雜一些。在Bundle中提供了兩個方法,專門用來傳遞對象的,但是這兩個方法也有相應的限制,需要實現特定的接口,當然,一些Android自帶的類,其實已經實現了這兩個接口中的某一個,可以直接使用。方法如下:
還有另外一種方式在Message中傳遞對象,那就是使用Message自帶的obj屬性傳值,它是一個Object類型,所以可以傳遞任意類型的對象,Message自帶的有如下幾個屬性:
下面這個示例,使用了兩種方式獲取傳遞消息,以一個隨機數確定。在這個示例中,訪問網絡的代碼會附上但是不會詳解,如果對於Android中訪問網絡不熟悉的朋友,可以參見我另外一篇,http://www.fengfly.com/plus/view-213370-1.html。
布局代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <Button android:id="@+id/btnInternet" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:text="下載網絡圖片"/>
- <TextView android:id="@+id/tbMsgType" android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- <ImageView android:id="@+id/ivInternet" android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
實現代碼:
- package com.bgxt.imageviewdemo;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.util.Random;
- import com.bgxt.httputils.HttpUtils;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.TextView;
- import android.widget.Toast;
- public class InternetImageActivity extends Activity {
- private Button btnInternet;
- private ImageView ivInternet;
- private TextView tvMsgType;
- private Handler handler;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_internetimage);
- btnInternet = (Button) findViewById(R.id.btnInternet);
- ivInternet = (ImageView) findViewById(R.id.ivInternet);
- tvMsgType = (TextView) findViewById(R.id.tbMsgType);
- // 定義一個handler,用於接收消息
- handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- Bitmap bmp = null;
- // 通過消息碼確定使用什麼方式傳遞圖片信息
- if (msg.what == 0) {
- bmp = (Bitmap) msg.obj;
- tvMsgType.setText("使用obj傳遞數據");
- } else {
- Bundle ble = msg.getData();
- bmp = (Bitmap) ble.get("bmp");
- tvMsgType.setText("使用Bundle傳遞數據");
- }
- // 設置圖片到ImageView中
- ivInternet.setImageBitmap(bmp);
- }
- };
- btnInternet.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //清空之前獲取的數據
- tvMsgType.setText("");
- ivInternet.setImageBitmap(null);
- //定義一個線程類
- new Thread() {
- @Override
- public void run() {
- try {
- //獲取網絡圖片
- InputStream inputStream = HttpUtils
- .getImageViewInputStream();
- Bitmap bitmap = BitmapFactory
- .decodeStream(inputStream);
- Message msg = new Message();
- Random rd = new Random();
- int ird = rd.nextInt(10);
- //通過一個隨機數,隨機選擇通過什麼方式傳遞圖片信息到消息中
- if (ird / 2 == 0) {
- msg.what = 0;
- msg.obj = bitmap;
- } else {
- Bundle bun = new Bundle();
- bun.putParcelable("bmp", bitmap);
- msg.what = 1;
- msg.setData(bun);
- }
- //發送消息
- handler.sendMessage(msg);
- } catch (Exception e) {
- }
- }
- }.start();
- }
- });
- }
- }
訪問網絡類,代碼:
- package com.bgxt.httputils;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- public class HttpUtils {
- private final static String URL_PATH = "http://ww4.sinaimg.cn/bmiddle/9e58dccejw1e6xow22oc6j20c80gyaav.jpg";
- public HttpUtils() {
- }
- public static InputStream getImageViewInputStream() throws IOException {
- InputStream inputStream = null;
- URL url = new URL(URL_PATH);
- if (url != null) {
- HttpURLConnection httpURLConnection = (HttpURLConnection) url
- .openConnection();
- httpURLConnection.setConnectTimeout(3000);
- httpURLConnection.setRequestMethod("GET");
- httpURLConnection.setDoInput(true);
- int response_code = httpURLConnection.getResponseCode();
- if (response_code == 200) {
- inputStream = httpURLConnection.getInputStream();
- }
- }
- return inputStream;
- }
- }
效果展示:
示例代碼下載
總結
以上就講解了ImageView的一些基本使用,對於Android項目而言,一般的用到更多的就是從網絡獲取圖片的功能,所以這裡著重講解了一下。
當我們第一次下載QQ並且打開的時候,會有一個新手引導,引導是幾張圖片,再加上一些文字說明,向右滑動,直到結束,今天一大早起來研究了一下關於此種效果的實現之View
在android中,LayoutInflater有點類似於Activity的findViewById(id),不同的是LayoutInflater是用來找layo
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個
Android提供了很多控件便於開發者進行UI相關的程序設計。但是很多時候,默認的一些UI設置不足以滿足我們的需求,要麼不好看,要麼高度不夠,亦或者是與應用界面不