編輯:關於Android編程
本文實例分析了Android可循環顯示圖像的Android Gallery組件用法。分享給大家供大家參考,具體如下:
Gallery組件主要用於橫向顯示圖像列表,不過按常規做法。Gallery組件只能有限地顯示指定的圖像。也就是說,如果為Gallery組件指定了10張圖像,那麼當Gallery組件顯示到第10張時,就不會再繼續顯示了。這雖然在大多數時候沒有什麼關系,但在某些情況下,我們希望圖像顯示到最後一張時再重第1張開始顯示,也就是循環顯示。要實現這種風格的Gallery組件,就需要對Gallery的Adapter對象進行一番改進。
Gallery組件的傳統用法
在實現可循環顯示圖像的Gallery組件之前先來回顧一下Gallery組件的傳統用法。Gallery組件可以橫向顯示一個圖像列表,當單擊當前圖像的後一個圖像時,這個圖像列表會向左移動一格,當單擊當前圖像的前一個圖像時,這個圖像列表會向右移動一樣。也可以通過拖動的方式來向左和向右移動圖像列表。當前顯示的是第1個圖像的效果如圖1所示。Gallery組件顯示到最後一個圖像的效果如圖2所示。
從圖2可以看出,當顯示到最後一個圖像時,列表後面就沒有圖像的,這也是Gallery組件的基本顯示效果。在本文後面的部分將詳細介紹如何使Gallery組件顯示到最後一個圖像時會從第1個圖像開始顯示。
好了,現在我們來看一下圖1和圖2的效果是如何做出來的吧。Gallery既然用於顯示圖像,那第1步就必須要有一些圖像文件用來顯示。現在可以隨意准備一些圖像。在本文的例子中准備了15個jpg文件(item1.jpg至item15.jpg)。將這些文件都放在res\drawable目錄中。
下面將這些圖像的資源ID都保存在int數組中,代碼如下:
private int[] resIds = new int[] { R.drawable.item1, R.drawable.item2, R.drawable.item3, R.drawable.item4, R.drawable.item5, R.drawable.item6, R.drawable.item7, R.drawable.item8, R.drawable.item9, R.drawable.item10, R.drawable.item11, R.drawable.item12, R.drawable.item13, R.drawable.item14, R.drawable.item15 };
在本例的main.xml文件中配置了一個Gallery組件,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Gallery android:id="@+id/gallery" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" /> </LinearLayout>
現在在onCreate方法中裝載這個組件,代碼如下:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 裝載Gallery組件 Gallery gallery = (Gallery) findViewById(R.id.gallery); // 創建用於描述圖像數據的ImageAdapter對象 ImageAdapter imageAdapter = new ImageAdapter(this); // 設置Gallery組件的Adapter對象 gallery.setAdapter(imageAdapter); }
在上面的代碼中涉及到一個非常重要的類:ImageAdapter。該類是android.widget.BaseAdapter的子類,用於描述圖像信息。下面先看一下這個類的完整代碼。
public class ImageAdapter extends BaseAdapter { int mGalleryItemBackground; private Context mContext; public ImageAdapter(Context context) { mContext = context; // 獲得Gallery組件的屬性 TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery); mGalleryItemBackground = typedArray.getResourceId( R.styleable.Gallery_android_galleryItemBackground, 0); } // 返回圖像總數 public int getCount() { return resIds.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } // 返回具體位置的ImageView對象 public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = new ImageView(mContext); // 設置當前圖像的圖像(position為當前圖像列表的位置) imageView.setImageResource(resIds[position]); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setLayoutParams(new Gallery.LayoutParams(163, 106)); // 設置Gallery組件的背景風格 imageView.setBackgroundResource(mGalleryItemBackground); return imageView; } }
在編寫ImageAdapter類時應注意的兩點:
1. 在ImageAdapter類的構造方法中獲得了Gallery組件的屬性信息。這些信息被定義在res\values\attrs.xml文件中,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="Gallery"> <attr name="android:galleryItemBackground" /> </declare-styleable> </resources>
上面的屬性信息用於設置Gallery的背景風格。
2. 在ImageAdapter類中有兩個非常重要的方法:getCount和getView。其中getCount方法用於返回圖像總數,要注意的是,這個總數不能大於圖像的實際數(可以小於圖像的實際數),否則會拋出越界異常。當Gallery組件要顯示某一個圖像時,就會調用getView方法,並將當前的圖像索引(position參數)傳入該方法。一般getView方法用於返回每一個顯示圖像的組件(ImageView對象)。從這一點可以看出,Gallery組件是即時顯示圖像的,而不是一下將所有的圖像都顯示出來。在getView方法中除了創建了ImageView對象,還用從resIds數組中獲得了相應的圖像資源ID來設置在ImageView中顯示的圖像。最後還設置了Gallery組件的背景顯示風格。
OK,現在來運行這個程序,來回拖動圖像列表,就會看到如圖1和圖2所示的效果了。
循環顯示圖像的原理
循環顯示有些類似於循環鏈表,最後一個結點的下一個結點又是第1個結點。循環顯示圖像也可以模擬這一點。
也許細心的讀者從上一節實現的ImageAdapter類中會發現些什麼。對!就是getView方法中的position參數和getCount方法的關系。position參數的值是不可能超過getCount方法返回的值的,也就是說,position參數值的范圍是0至getCount() - 1。
如果這時Gallery組件正好顯示到最後一個圖像,position參數值正好為getCount() - 1。那麼我們如何再讓Gallery顯示下一個圖像呢?也就是說讓position參數值再增1,對!將getCount()方法的返回值也增1。
那麼這裡還有一個問題,如果position參數值無限地增加,就意味著resIds數組要不斷地增大,這樣會大大消耗系統的資源。想到這,就需要解決兩個問題:既要position不斷地增加,又讓resIds數組中保存的圖像資源ID是有限的,該怎麼做呢?對於getCount()方法非常好解決,可以讓getCount方法返回一個很大的數,例如,Integer.MAX_VALUE。這時position參數值就可以隨著Gallery組件的圖像不斷向前移動而增大。現在resIds數組只有15個元素,如果position的值超過數組邊界,要想繼續循環取得數組中的元素(也就是說,當position的值是15時,取resIds數組的第0個元素,是16時取第1個元素),最簡單的方法就是取余,代碼如下:
resIds[position % resIds.length]
在本節對ImageAdapter類做了如下兩個改進:
1. 使getCount方法返回一個很大的值。建議返回Integer.MAX_VALUE。
2. 在getView方法中通過取余來循環取得resIds數組中的圖像資源ID。
通過上面兩點改進,可以使圖像列表在向右移動時會循環顯示圖像。當然,這種方法從本質上說只是偽循環,也就是說,如果真把圖像移動到getCount方法返回的值那裡,那也就顯示到最後一個圖像的。不過在這裡getCount方法返回的是Integer.MAX_VALUE,這個值超過了20億,除非有人真想把圖像移動到第20億的位置,否則Gallery組件看著就是一個循環顯示圖像的組件。
實現循環顯示圖像的Gallery組件
在本節將組出與循環顯示圖像相關的ImageAdapter類的完整代碼。讀者可以從中看到上一節介紹的兩點改進。為了使界面看上去更豐滿,本例還在單擊某一個Gallery組件中的圖像時在下方顯示一個放大的圖像(使用ImageSwitcher組件)。本例的顯示效果如圖3所示。當不斷向後移動圖像時,圖像可不斷顯示,讀者可以自己運行本例來體驗一下。
在main.xml文件中定義的Gallery和ImageSwitcher組件的代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Gallery android:id="@+id/gallery" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" /> <ImageSwitcher android:id="@+id/imageswitcher" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" /> </LinearLayout>
本例中Main類的完整代碼如下:
package net.blogjava.mobile; import android.app.Activity; import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageSwitcher; import android.widget.ImageView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Gallery.LayoutParams; import android.widget.ViewSwitcher.ViewFactory; public class Main extends Activity implements OnItemSelectedListener, ViewFactory { private Gallery gallery; private ImageSwitcher imageSwitcher; private ImageAdapter imageAdapter; private int[] resIds = new int[] { R.drawable.item1, R.drawable.item2, R.drawable.item3, R.drawable.item4, R.drawable.item5, R.drawable.item6, R.drawable.item7, R.drawable.item8, R.drawable.item9, R.drawable.item10, R.drawable.item11, R.drawable.item12, R.drawable.item13, R.drawable.item14, R.drawable.item15 }; public class ImageAdapter extends BaseAdapter { int mGalleryItemBackground; private Context mContext; public ImageAdapter(Context context) { mContext = context; TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery); mGalleryItemBackground = typedArray.getResourceId( R.styleable.Gallery_android_galleryItemBackground, 0); } // 第1點改進,返回一個很大的值,例如,Integer.MAX_VALUE public int getCount() { return Integer.MAX_VALUE; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = new ImageView(mContext); // 第2點改進,通過取余來循環取得resIds數組中的圖像資源ID imageView.setImageResource(resIds[position % resIds.length]); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setLayoutParams(new Gallery.LayoutParams(163, 106)); imageView.setBackgroundResource(mGalleryItemBackground); return imageView; } } @Override public void onItemSelected(AdapterView<?> parent, View view, int position,long id) { // 選中Gallery中某個圖像時,在ImageSwitcher組件中放大顯示該圖像 imageSwitcher.setImageResource(resIds[position % resIds.length]); } @Override public void onNothingSelected(AdapterView<?> parent) { } @Override // ImageSwitcher組件需要這個方法來創建一個View對象(一般為ImageView對象) // 來顯示圖像 public View makeView() { ImageView imageView = new ImageView(this); imageView.setBackgroundColor(0xFF000000); imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setLayoutParams(new ImageSwitcher.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); return imageView; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); gallery = (Gallery) findViewById(R.id.gallery); imageAdapter = new ImageAdapter(this); gallery.setAdapter(imageAdapter); gallery.setOnItemSelectedListener(this); imageSwitcher = (ImageSwitcher) findViewById(R.id.imageswitcher); // 設置ImageSwitcher組件的工廠對象 imageSwitcher.setFactory(this); // 設置ImageSwitcher組件顯示圖像的動畫效果 imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); } }
總結
在本文介紹了如何實現可循環顯示的Gallery組件。實際上,這個循環顯示只是一個偽循環,不過由於getCount方法返回的圖像總數很大(超過20億),這就意味著已經非常接近無限循環了。實現循環顯示圖像的關鍵點有如下兩個:
1. getCount方法返回一個很大的整數值(例如,Integer.MAX_VALUE)。
2. 在getView方法中通過取余的方法來循環獲得圖像的資源ID。
更多關於Android相關內容感興趣的讀者可查看本站專題:《Android調試技巧與常見問題解決方法匯總》、《Android開發入門與進階教程》、《Android多媒體操作技巧匯總(音頻,視頻,錄音等)》、《Android基本組件用法總結》、《Android視圖View技巧總結》、《Android布局layout技巧總結》及《Android控件用法總結》
希望本文所述對大家Android程序設計有所幫助。
前言這篇文章是這個系列的開篇,作為移動開發者,開發的應用不免會對網絡進行訪問,雖然現在已經有很多的開源庫幫助我們可以輕而易舉的訪問網絡,但是我們仍要去了解網絡訪問的原理,
一、批量打包1、集成了友盟統計,並在AndroidManifest.xml中添加了如下代碼<meta-dataandroid:name=UMENG_CHANNELa
前言WebView(網絡視圖)在Andorid中就是用來顯示網頁的,下面我們來一起看看它是如何使用的。一、基本使用1.聲明權限,WebView不可避免地要用到網絡,我們要
重點內容我們在做項目中經常會遇到要使用第三方SDK,這時,我們通常先將第三方jar包導入,然後再導入相應的資源文件,最後在自己的項目中調用,很多人只會用卻不知道怎麼讓自己