Android中的Gallery的使用

来源:互联网 发布:软件已过期怎么办 编辑:程序博客网 时间:2024/05/19 21:58

 

我们有时候在iPhone手机上或者Windows上面看到动态的图片,可以通过鼠标或者手指触摸来移动它,产生动态的图片滚动效果,还可以根据你的点击或者触摸触发其他事件响应。同样的,在Android中也提供这这种实现,这就是通过Gallery在UI上实现缩略图浏览器。

 

我们来看看Gallery是如何来实现的,先把控件从布局文件中声明,只需知道ID为gallery。 

 

Java代码  收藏代码
  1. Gallery gallery = (Gallery) findViewById(R.id.gallery);  

 一般情况下,我们在Android中要用到类似这种图片容器的控件,都需要为它指定一个适配器,让它可以把内容按照我们定义的方式来显示,因此我们来给它加一个适配器,至于这个适配器如何实现,后面接着来操作,这里只需知道这个适配器的类叫ImageAdapter。 gallery.setAdapter(new ImageAdapter(this));

 

复制代码接下来就是重头戏了,适配器可以说是最重要的,我们来看看如何做?到这里似乎还缺少一些很重要的东西?什么东西呢?我们需要显示的是图片,那么图片我们当然首先要准备好,这里我们准备了5张图片(存放drawable文件夹中),我们用其IDs做索引,以便在适配器中使用。

Java代码  收藏代码
  1. private Integer[] mps = {  
  2.         R.drawable.icon1,  
  3.         R.drawable.icon2,  
  4.         R.drawable.icon3,  
  5.         R.drawable.icon4,  
  6.         R.drawable.icon5  
  7. };  

OK,这里将开始定义适配器了,通过继承BaseAdapter用以实现的适配器。  

 

Java代码  收藏代码
  1. public class ImageAdapter extends BaseAdapter {  
  2.     private Context mContext;  
  3.         public ImageAdapter(Context context) {  
  4.         mContext = context;  
  5.     }  
  6.   
  7.     public int getCount() {   
  8.         return mps.length;  
  9.     }  
  10.   
  11.     public Object getItem(int position) {  
  12.         return position;  
  13.     }  
  14.   
  15.     public long getItemId(int position) {  
  16.         return position;  
  17.     }  
  18.   
  19.     public View getView(int position, View convertView, ViewGroup parent) {  
  20.         ImageView image = new ImageView(mContext);  
  21.         image.setImageResource(mps[position]);  
  22.         image.setAdjustViewBounds(true);  
  23.         image.setLayoutParams(new Gallery.LayoutParams(  
  24.             LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  
  25.         return image;  
  26.     }  
  27. }  

至此,整个Gallery基本都是先完成了,我们还需要为它添加一个监听器,否则这个缩略图浏览器就仅仅只可以看不能用了。

 

Java代码  收藏代码
  1. gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {  
  2.     @Override  
  3.     public void onItemSelected(AdapterView<?> parent, View v,int position, long id) {  
  4.     }  
  5.   
  6.     @Override  
  7.     public void onNothingSelected(AdapterView<?> arg0) {  
  8.     //这里不做响应  
  9.     }  
  10. });  
  11. 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数组中,代码如下:

    java代码:
    1privateint[] resIds = newint[]{
    2R.drawable.item1, R.drawable.item2, R.drawable.item3,
    3R.drawable.item4, R.drawable.item5, R.drawable.item6,
    4R.drawable.item7, R.drawable.item8, R.drawable.item9,
    5R.drawable.item10, R.drawable.item11, R.drawable.item12,
    6R.drawable.item13, R.drawable.item14, R.drawable.item15
    7};

    main.xml文件中配置了一个Gallery组件,代码如下:

    java代码:
    01<?xml version="1.0"encoding="utf-8"?>
    02<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    03android:orientation="vertical"
    04android:layout_width="fill_parent"
    05android:layout_height="fill_parent">
    06<Gallery
    07android:id="@+id/gallery"
    08android:layout_width="fill_parent"
    09android:layout_height="wrap_content"
    10android:layout_marginTop="30dp"/>
    11</LinearLayout>

    现在在onCreate方法中装载这个组件,代码如下:

    java代码:
    01publicvoid onCreate(Bundle savedInstanceState){
    02super.onCreate(savedInstanceState);
    03setContentView(R.layout.main);
    04// 装载Gallery组件
    05Gallery gallery = (Gallery) findViewById(R.id.gallery);
    06// 创建用于描述图像数据的ImageAdapter对象
    07ImageAdapter imageAdapter = newImageAdapter(this);
    08// 设置Gallery组件的Adapter对象
    09gallery.setAdapter(imageAdapter);
    10}

      在上面的代码中涉及到一个非常重要的类:ImageAdapter。该类是android.widget.BaseAdapter的子类,用于描述图像信息。下面先看一下这个类的完整代码。

    java代码:
    01publicclass ImageAdapter extendsBaseAdapter
    02{
    03intmGalleryItemBackground;
    04privateContext mContext;
    05 
    06publicImageAdapter(Context context)
    07{
    08mContext = context;
    09// 获得Gallery组件的属性
    10TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery);
    11mGalleryItemBackground = typedArray.getResourceId(
    12R.styleable.Gallery_android_galleryItemBackground,0);
    13}
    14// 返回图像总数
    15publicint getCount()
    16{
    17returnresIds.length;
    18}
    19publicObject getItem(intposition)
    20{
    21returnposition;
    22}
    23 
    24publiclong getItemId(intposition)
    25{
    26returnposition;
    27}
    28// 返回具体位置的ImageView对象
    29publicView getView(intposition, View convertView, ViewGroup parent)
    30{
    31ImageView imageView = newImageView(mContext);
    32// 设置当前图像的图像(position为当前图像列表的位置)
    33imageView.setImageResource(resIds[position]);
    34imageView.setScaleType(ImageView.ScaleType.FIT_XY);
    35imageView.setLayoutParams(newGallery.LayoutParams(163,106));
    36// 设置Gallery组件的背景风格
    37imageView.setBackgroundResource(mGalleryItemBackground);
    38returnimageView;
    39}
    40}

      在编写ImageAdapter类时应注意的两点:

    1.  在ImageAdapter类的构造方法中获得了Gallery组件的属性信息。这些信息被定义在res\values\attrs.xml文件中,代码如下:

    java代码:
    1<?xml version="1.0"encoding="utf-8"?>
    2<resources>
    3<declare-styleable name="Gallery">
    4<attr name="android:galleryItemBackground"/>
    5</declare-styleable>
    6</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组件的代码如下:

    java代码:
    01<font color="black"><font face="微软雅黑"><font size="3"><?xml version="1.0"encoding="utf-8"?>
    02<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    03android:orientation="vertical"
    04android:layout_width="fill_parent"
    05android:layout_height="fill_parent">
    06<Gallery
    07android:id="@+id/gallery"
    08android:layout_width="fill_parent"
    09android:layout_height="wrap_content"
    10android:layout_marginTop="30dp"/>
    11<ImageSwitcher
    12android:id="@+id/imageswitcher"
    13android:layout_width="fill_parent"
    14android:layout_height="wrap_content"
    15android:layout_marginTop="30dp"/>
    16</LinearLayout></font></font></font>

    本例中Main类的完整代码如下:

    java代码:

    view source
    001packageeoe.demo;
    002 
    003importandroid.app.Activity;
    004importandroid.content.Context;
    005importandroid.content.res.TypedArray;
    006importandroid.os.Bundle;
    007importandroid.view.View;
    008importandroid.view.ViewGroup;
    009importandroid.view.animation.AnimationUtils;
    010importandroid.widget.AdapterView;
    011importandroid.widget.BaseAdapter;
    012importandroid.widget.Gallery;
    013importandroid.widget.ImageSwitcher;
    014importandroid.widget.ImageView;
    015importandroid.widget.AdapterView.OnItemSelectedListener;
    016importandroid.widget.Gallery.LayoutParams;
    017importandroid.widget.ViewSwitcher.ViewFactory;
    018 
    019publicclass Main extendsActivity implementsOnItemSelectedListener,
    020ViewFactory{
    021privateGallery gallery;
    022privateImageSwitcher imageSwitcher;
    023privateImageAdapter imageAdapter;
    024 
    025privateint[] resIds = newint[]
    026{ R.drawable.item1, R.drawable.item2, R.drawable.item3, R.drawable.item4,
    027R.drawable.item5, R.drawable.item6, R.drawable.item7,
    028R.drawable.item8, R.drawable.item9, R.drawable.item10,
    029R.drawable.item11, R.drawable.item12, R.drawable.item13,
    030R.drawable.item14, R.drawable.item15 };
    031 
    032publicclass ImageAdapter extendsBaseAdapter
    033{
    034intmGalleryItemBackground;
    035privateContext mContext;
    036 
    037publicImageAdapter(Context context)
    038{
    039mContext = context;
    040TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery);
    041mGalleryItemBackground = typedArray.getResourceId(
    042R.styleable.Gallery_android_galleryItemBackground,0);
    043}
    044// 第1点改进,返回一个很大的值,例如,Integer.MAX_VALUE
    045publicint getCount()
    046{
    047returnInteger.MAX_VALUE;
    048}
    049 
    050publicObject getItem(intposition)
    051{
    052returnposition;
    053}
    054 
    055publiclong getItemId(intposition)
    056{
    057returnposition;
    058}
    059 
    060publicView getView(intposition, View convertView, ViewGroup parent)
    061{
    062ImageView imageView = newImageView(mContext);
    063// 第2点改进,通过取余来循环取得resIds数组中的图像资源ID
    064imageView.setImageResource(resIds[position % resIds.length]);
    065imageView.setScaleType(ImageView.ScaleType.FIT_XY);
    066imageView.setLayoutParams(newGallery.LayoutParams(163,106));
    067imageView.setBackgroundResource(mGalleryItemBackground);
    068returnimageView;
    069}
    070}
    071 
    072@Override
    073publicvoid onItemSelected(AdapterView<?> parent, View view, intposition,longid)
    074{
    075// 选中Gallery中某个图像时,在ImageSwitcher组件中放大显示该图像
    076imageSwitcher.setImageResource(resIds[position % resIds.length]);
    077 
    078}
    079@Override
    080publicvoid onNothingSelected(AdapterView<?> parent)
    081{
    082}
    083 
    084@Override
    085// ImageSwitcher组件需要这个方法来创建一个View对象(一般为ImageView对象)
    086// 来显示图像
    087publicView makeView()
    088{
    089ImageView imageView = newImageView(this);
    090imageView.setBackgroundColor(0xFF000000);
    091imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    092imageView.setLayoutParams(newImageSwitcher.LayoutParams(
    093LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    094returnimageView;
    095}
    096 
    097@Override
    098publicvoid onCreate(Bundle savedInstanceState)
    099{
    100super.onCreate(savedInstanceState);
    101setContentView(R.layout.main);
    102gallery = (Gallery) findViewById(R.id.gallery);
    103imageAdapter = newImageAdapter(this);
    104gallery.setAdapter(imageAdapter);
    105gallery.setOnItemSelectedListener(this);
    106imageSwitcher = (ImageSwitcher) findViewById(R.id.imageswitcher);
    107// 设置ImageSwitcher组件的工厂对象
    108imageSwitcher.setFactory(this);
    109// 设置ImageSwitcher组件显示图像的动画效果
    110imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
    111android.R.anim.fade_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
    112android.R.anim.fade_out));
    113 
    114}
    115}


  12. 转载地址:http://txlong-onz.iteye.com/blog/934959
0 0
原创粉丝点击