Android可循環(huán)顯示圖像的Android Gallery組件用法實(shí)例
本文實(shí)例分析了Android可循環(huán)顯示圖像的Android Gallery組件用法。分享給大家供大家參考,具體如下:
Gallery組件主要用于橫向顯示圖像列表,不過(guò)按常規(guī)做法。Gallery組件只能有限地顯示指定的圖像。也就是說(shuō),如果為Gallery組件指定了10張圖像,那么當(dāng)Gallery組件顯示到第10張時(shí),就不會(huì)再繼續(xù)顯示了。這雖然在大多數(shù)時(shí)候沒(méi)有什么關(guān)系,但在某些情況下,我們希望圖像顯示到最后一張時(shí)再重第1張開(kāi)始顯示,也就是循環(huán)顯示。要實(shí)現(xiàn)這種風(fēng)格的Gallery組件,就需要對(duì)Gallery的Adapter對(duì)象進(jìn)行一番改進(jìn)。
Gallery組件的傳統(tǒng)用法
在實(shí)現(xiàn)可循環(huán)顯示圖像的Gallery組件之前先來(lái)回顧一下Gallery組件的傳統(tǒng)用法。Gallery組件可以橫向顯示一個(gè)圖像列表,當(dāng)單擊當(dāng)前圖像的后一個(gè)圖像時(shí),這個(gè)圖像列表會(huì)向左移動(dòng)一格,當(dāng)單擊當(dāng)前圖像的前一個(gè)圖像時(shí),這個(gè)圖像列表會(huì)向右移動(dòng)一樣。也可以通過(guò)拖動(dòng)的方式來(lái)向左和向右移動(dòng)圖像列表。當(dāng)前顯示的是第1個(gè)圖像的效果如圖1所示。Gallery組件顯示到最后一個(gè)圖像的效果如圖2所示。
從圖2可以看出,當(dāng)顯示到最后一個(gè)圖像時(shí),列表后面就沒(méi)有圖像的,這也是Gallery組件的基本顯示效果。在本文后面的部分將詳細(xì)介紹如何使Gallery組件顯示到最后一個(gè)圖像時(shí)會(huì)從第1個(gè)圖像開(kāi)始顯示。
好了,現(xiàn)在我們來(lái)看一下圖1和圖2的效果是如何做出來(lái)的吧。Gallery既然用于顯示圖像,那第1步就必須要有一些圖像文件用來(lái)顯示。現(xiàn)在可以隨意準(zhǔn)備一些圖像。在本文的例子中準(zhǔn)備了15個(gè)jpg文件(item1.jpg至item15.jpg)。將這些文件都放在res\drawable目錄中。
下面將這些圖像的資源ID都保存在int數(shù)組中,代碼如下:
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文件中配置了一個(gè)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>
現(xiàn)在在onCreate方法中裝載這個(gè)組件,代碼如下:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 裝載Gallery組件 Gallery gallery = (Gallery) findViewById(R.id.gallery); // 創(chuàng)建用于描述圖像數(shù)據(jù)的ImageAdapter對(duì)象 ImageAdapter imageAdapter = new ImageAdapter(this); // 設(shè)置Gallery組件的Adapter對(duì)象 gallery.setAdapter(imageAdapter); }
在上面的代碼中涉及到一個(gè)非常重要的類:ImageAdapter。該類是android.widget.BaseAdapter的子類,用于描述圖像信息。下面先看一下這個(gè)類的完整代碼。
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); } // 返回圖像總數(shù) public int getCount() { return resIds.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } // 返回具體位置的ImageView對(duì)象 public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = new ImageView(mContext); // 設(shè)置當(dāng)前圖像的圖像(position為當(dāng)前圖像列表的位置) imageView.setImageResource(resIds[position]); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setLayoutParams(new Gallery.LayoutParams(163, 106)); // 設(shè)置Gallery組件的背景風(fēng)格 imageView.setBackgroundResource(mGalleryItemBackground); return imageView; } }
在編寫ImageAdapter類時(shí)應(yīng)注意的兩點(diǎn):
1. 在ImageAdapter類的構(gòu)造方法中獲得了Gallery組件的屬性信息。這些信息被定義在res\values\attrs.xml文件中,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="Gallery"> <attr name="android:galleryItemBackground" /> </declare-styleable> </resources>
上面的屬性信息用于設(shè)置Gallery的背景風(fēng)格。
2. 在ImageAdapter類中有兩個(gè)非常重要的方法:getCount和getView。其中g(shù)etCount方法用于返回圖像總數(shù),要注意的是,這個(gè)總數(shù)不能大于圖像的實(shí)際數(shù)(可以小于圖像的實(shí)際數(shù)),否則會(huì)拋出越界異常。當(dāng)Gallery組件要顯示某一個(gè)圖像時(shí),就會(huì)調(diào)用getView方法,并將當(dāng)前的圖像索引(position參數(shù))傳入該方法。一般getView方法用于返回每一個(gè)顯示圖像的組件(ImageView對(duì)象)。從這一點(diǎn)可以看出,Gallery組件是即時(shí)顯示圖像的,而不是一下將所有的圖像都顯示出來(lái)。在getView方法中除了創(chuàng)建了ImageView對(duì)象,還用從resIds數(shù)組中獲得了相應(yīng)的圖像資源ID來(lái)設(shè)置在ImageView中顯示的圖像。最后還設(shè)置了Gallery組件的背景顯示風(fēng)格。
OK,現(xiàn)在來(lái)運(yùn)行這個(gè)程序,來(lái)回拖動(dòng)圖像列表,就會(huì)看到如圖1和圖2所示的效果了。
循環(huán)顯示圖像的原理
循環(huán)顯示有些類似于循環(huán)鏈表,最后一個(gè)結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)又是第1個(gè)結(jié)點(diǎn)。循環(huán)顯示圖像也可以模擬這一點(diǎn)。
也許細(xì)心的讀者從上一節(jié)實(shí)現(xiàn)的ImageAdapter類中會(huì)發(fā)現(xiàn)些什么。對(duì)!就是getView方法中的position參數(shù)和getCount方法的關(guān)系。position參數(shù)的值是不可能超過(guò)getCount方法返回的值的,也就是說(shuō),position參數(shù)值的范圍是0至getCount() - 1。
如果這時(shí)Gallery組件正好顯示到最后一個(gè)圖像,position參數(shù)值正好為getCount() - 1。那么我們?nèi)绾卧僮孏allery顯示下一個(gè)圖像呢?也就是說(shuō)讓position參數(shù)值再增1,對(duì)!將getCount()方法的返回值也增1。
那么這里還有一個(gè)問(wèn)題,如果position參數(shù)值無(wú)限地增加,就意味著resIds數(shù)組要不斷地增大,這樣會(huì)大大消耗系統(tǒng)的資源。想到這,就需要解決兩個(gè)問(wèn)題:既要position不斷地增加,又讓resIds數(shù)組中保存的圖像資源ID是有限的,該怎么做呢?對(duì)于getCount()方法非常好解決,可以讓getCount方法返回一個(gè)很大的數(shù),例如,Integer.MAX_VALUE。這時(shí)position參數(shù)值就可以隨著Gallery組件的圖像不斷向前移動(dòng)而增大。現(xiàn)在resIds數(shù)組只有15個(gè)元素,如果position的值超過(guò)數(shù)組邊界,要想繼續(xù)循環(huán)取得數(shù)組中的元素(也就是說(shuō),當(dāng)position的值是15時(shí),取resIds數(shù)組的第0個(gè)元素,是16時(shí)取第1個(gè)元素),最簡(jiǎn)單的方法就是取余,代碼如下:
resIds[position % resIds.length]
在本節(jié)對(duì)ImageAdapter類做了如下兩個(gè)改進(jìn):
1. 使getCount方法返回一個(gè)很大的值。建議返回Integer.MAX_VALUE。
2. 在getView方法中通過(guò)取余來(lái)循環(huán)取得resIds數(shù)組中的圖像資源ID。
通過(guò)上面兩點(diǎn)改進(jìn),可以使圖像列表在向右移動(dòng)時(shí)會(huì)循環(huán)顯示圖像。當(dāng)然,這種方法從本質(zhì)上說(shuō)只是偽循環(huán),也就是說(shuō),如果真把圖像移動(dòng)到getCount方法返回的值那里,那也就顯示到最后一個(gè)圖像的。不過(guò)在這里getCount方法返回的是Integer.MAX_VALUE,這個(gè)值超過(guò)了20億,除非有人真想把圖像移動(dòng)到第20億的位置,否則Gallery組件看著就是一個(gè)循環(huán)顯示圖像的組件。
實(shí)現(xiàn)循環(huán)顯示圖像的Gallery組件
在本節(jié)將組出與循環(huán)顯示圖像相關(guān)的ImageAdapter類的完整代碼。讀者可以從中看到上一節(jié)介紹的兩點(diǎn)改進(jìn)。為了使界面看上去更豐滿,本例還在單擊某一個(gè)Gallery組件中的圖像時(shí)在下方顯示一個(gè)放大的圖像(使用ImageSwitcher組件)。本例的顯示效果如圖3所示。當(dāng)不斷向后移動(dòng)圖像時(shí),圖像可不斷顯示,讀者可以自己運(yùn)行本例來(lái)體驗(yàn)一下。
在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點(diǎn)改進(jìn),返回一個(gè)很大的值,例如,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點(diǎn)改進(jìn),通過(guò)取余來(lái)循環(huán)取得resIds數(shù)組中的圖像資源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中某個(gè)圖像時(shí),在ImageSwitcher組件中放大顯示該圖像 imageSwitcher.setImageResource(resIds[position % resIds.length]); } @Override public void onNothingSelected(AdapterView<?> parent) { } @Override // ImageSwitcher組件需要這個(gè)方法來(lái)創(chuàng)建一個(gè)View對(duì)象(一般為ImageView對(duì)象) // 來(lái)顯示圖像 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); // 設(shè)置ImageSwitcher組件的工廠對(duì)象 imageSwitcher.setFactory(this); // 設(shè)置ImageSwitcher組件顯示圖像的動(dòng)畫效果 imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); } }
總結(jié)
在本文介紹了如何實(shí)現(xiàn)可循環(huán)顯示的Gallery組件。實(shí)際上,這個(gè)循環(huán)顯示只是一個(gè)偽循環(huán),不過(guò)由于getCount方法返回的圖像總數(shù)很大(超過(guò)20億),這就意味著已經(jīng)非常接近無(wú)限循環(huán)了。實(shí)現(xiàn)循環(huán)顯示圖像的關(guān)鍵點(diǎn)有如下兩個(gè):
1. getCount方法返回一個(gè)很大的整數(shù)值(例如,Integer.MAX_VALUE)。
2. 在getView方法中通過(guò)取余的方法來(lái)循環(huán)獲得圖像的資源ID。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android調(diào)試技巧與常見(jiàn)問(wèn)題解決方法匯總》、《Android開(kāi)發(fā)入門與進(jìn)階教程》、《Android多媒體操作技巧匯總(音頻,視頻,錄音等)》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android中ViewPager組件的基本用法及實(shí)現(xiàn)圖片切換的示例
- android Gallery組件實(shí)現(xiàn)的iPhone圖片滑動(dòng)效果實(shí)例
- Android組件Glide實(shí)現(xiàn)圖片平滑滾動(dòng)效果
- Android自定義組件獲取本地圖片和相機(jī)拍照?qǐng)D片
- Android高級(jí)組件Gallery畫廊視圖使用方法詳解
- Android高級(jí)組件ImageSwitcher圖像切換器使用方法詳解
- 淺析Android Studio 3.0 升級(jí)各種坑(推薦)
- Android中EditText setText方法的踩坑實(shí)戰(zhàn)
- Android WebView使用的技巧與一些坑
- Android開(kāi)發(fā)之StackView用法和遇到的坑分析
相關(guān)文章
Android下使用TCPDUMP實(shí)現(xiàn)數(shù)據(jù)抓包教程
這篇文章主要介紹了Android下使用TCPDUMP實(shí)現(xiàn)數(shù)據(jù)抓包教程,本文講解使用抓包工具tcpdump抓取數(shù)據(jù),然后使用Wireshark來(lái)分析數(shù)據(jù),需要的朋友可以參考下2015-02-02Android 自定義 View 中使用 Spannable的實(shí)例詳解
這篇文章主要介紹了Android 自定義 View 中使用 Spannable的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Android觸摸及手勢(shì)操作GestureDetector
這篇文章主要a為大家詳細(xì)介紹了Android觸摸及手勢(shì)操作GestureDetector的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-07-07Android實(shí)現(xiàn)簡(jiǎn)單的答題系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)單的答題系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Android 自定義精美界面包含選項(xiàng)菜單 上下文菜單及監(jiān)聽(tīng)詳解流程
這篇文章主要介紹了一個(gè)Android實(shí)例小項(xiàng)目,它包含了選項(xiàng)菜單、上下文菜單及其對(duì)應(yīng)的監(jiān)聽(tīng)事件,它很小,但這部分功能在Android開(kāi)發(fā)中很常見(jiàn),需要的朋友來(lái)看看吧2021-11-11android studio 4.0 新建類沒(méi)有修飾符的方法
這篇文章主要介紹了android studio 4.0 新建類沒(méi)有修飾符的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10android實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Android利用ViewPager實(shí)現(xiàn)用戶引導(dǎo)界面效果的方法
這篇文章主要介紹了Android利用ViewPager實(shí)現(xiàn)用戶引導(dǎo)界面效果的方法,結(jié)合實(shí)例形式詳細(xì)分析了Android軟件功能界面的初始化、view實(shí)例化、動(dòng)畫功能實(shí)現(xiàn)與布局相關(guān)技巧,需要的朋友可以參考下2016-07-07Android 獲取IP地址的實(shí)現(xiàn)方法
這篇文章主要介紹了Android 獲取IP地址的實(shí)現(xiàn)方法的相關(guān)資料,這里提供了具體實(shí)現(xiàn)的方法及代碼,使用WIFI 和GPRS的思路,需要的朋友可以參考下2016-11-11Android利用AudioRecord類實(shí)現(xiàn)音頻錄制程序
這篇文章主要為大家詳細(xì)介紹了Android利用AudioRecord類實(shí)現(xiàn)音頻錄制程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04