MonoDroid学习笔记(八)—— 如IPhone拖动相片特效,Gallery画廊

曾经被IPhone用手指在屏幕上滑来滑去拖动图片的操作方式吸引吗?在Android里,这并不是什么难事,只要用到Gallery即可。它通常用在设计相册、图片类型的选择器上。

在开始之前,先了解一下什么是Context以及Android.Widget命名空间下的BaseAdapter,在Activity当中,Context就如同是Canvas画布,随时等着被处理或覆盖。还记得先前介绍Activity之间的传递时,做过Intent以及Context的应用吗?当中Intent是Android.Content命名空间下的一个类,而Context也是一样。本范例在Layout里布局一个Gallery对象,再通过BaseAdapter容器存放Gallery所需要的图片。先将你要显示的图片放到Drawable文件夹下,然后编译一下工程,使其能在代码中使用。

Main.axml的结构很简单,只要放上一个Gallery即可:

[xhtml]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.   <Gallery android:id="@+id/gallery" android:layout_height="fill_parent" android:layout_width="fill_parent"></Gallery>  
  8. </LinearLayout>  
 

本范例的另一个重点,就是如何设置Gallery图片的宽高以及放置图片Layout的大小,在此我们新建一个ImageAdapter类来继承BaseAdapter容器来存放图片,通过ImageView的SetScaleType方法来改变图片的显示,再通过LayoutParameters属性类改变Layout的宽高。

我们先在Values目录下新建一个attrs.xml文件,这是一个自制Layout元素的用法,在其中定义<declare-styleable>标签,目的是自定义layout的背景风格,并且通过Android.Content.Res.TypedArray类的特性,让相同的Layout元素可以重复用于每一张图片。

[xhtml]  view plain copy print ?
  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>  
 

ImageAdapter类的结构如下:

[c-sharp]  view plain copy print ?
  1. public class ImageAdapter : BaseAdapter  
  2. {  
  3.     private Context ctx;  
  4.     int mGalleryItemBackground;  
  5.     private int[] images =   
  6.     {  
  7.         Resource.Drawable.btn1,  
  8.         Resource.Drawable.btn1_b,  
  9.         Resource.Drawable.btn2,  
  10.         Resource.Drawable.btn2_b,  
  11.         Resource.Drawable.btn3,  
  12.         Resource.Drawable.btn3_b,  
  13.         Resource.Drawable.btn4,  
  14.         Resource.Drawable.btn4_b  
  15.     };  
  16.     public ImageAdapter(Context ctx)  
  17.     {  
  18.         try  
  19.         {  
  20.             this.ctx = ctx;  
  21.             Android.Content.Res.TypedArray a = ctx.ObtainStyledAttributes(Resource.Styleable.Gallery);  
  22.             mGalleryItemBackground = a.GetResourceId(Resource.Styleable.Gallery_android_galleryItemBackground, Android.Graphics.Color.Azure);  
  23.             a.Recycle();  
  24.         }  
  25.         catch (System.Exception ex)  
  26.         {  
  27.             MessageBox.ShowErrorMessage(ctx, ex);  
  28.         }  
  29.     }  
  30.     public override int Count  
  31.     {  
  32.         get  
  33.         {  
  34.             return images.Length;  
  35.         }  
  36.     }  
  37.     public override Java.Lang.Object GetItem(int position)  
  38.     {  
  39.         return position;  
  40.     }  
  41.     public override long GetItemId(int position)  
  42.     {  
  43.         return position;  
  44.     }  
  45.     public override View GetView(int position, View convertView, ViewGroup parent)  
  46.     {  
  47.         try  
  48.         {  
  49.             ImageView v = new ImageView(this.ctx);  
  50.             v.SetImageResource(this.images[position]);  
  51.             v.SetScaleType(ImageView.ScaleType.FitXy);  
  52.             v.LayoutParameters = new Gallery.LayoutParams(100, 50);  
  53.             v.SetBackgroundResource(mGalleryItemBackground);  
  54.             return v;  
  55.         }  
  56.         catch (System.Exception ex)  
  57.         {  
  58.             MessageBox.ShowErrorMessage(this.ctx, ex);  
  59.             return null;  
  60.         }  
  61.     }  
  62. }  
 

Activity1.cs的代码:

[c-sharp]  view plain copy print ?
  1. [Activity(Label = "MonoDroidTest", MainLauncher = true)]  
  2. public class Activity1 : Activity  
  3. {  
  4.     protected override void OnCreate(Bundle bundle)  
  5.     {  
  6.         base.OnCreate(bundle);  
  7.         SetContentView(Resource.Layout.Main);  
  8.         try  
  9.         {  
  10.             Gallery mGallery = FindViewById<Gallery>(Resource.Id.gallery);  
  11.             mGallery.Adapter = new ImageAdapter(this);  
  12.         }  
  13.         catch (System.Exception ex)  
  14.         {  
  15.             MessageBox.ShowErrorMessage(this, ex);  
  16.         }  
  17.     }  
  18. }  
 

 

运行程序,效果如下:

MonoDroid学习笔记(八)—— 如IPhone拖动相片特效,Gallery画廊

 

接下来的问题就是,我们能不能读取我们SD卡上的图片,而不是直接把图片作为资源打到包里啊?这当然是可以的,下面我们把ImageAdapter改写一下,从下面的例子,我们还可以学到如何读取SD卡的文件(记得using Java.IO;):

[c-sharp]  view plain copy print ?
  1. public class ImageAdapter : BaseAdapter  
  2. {  
  3.     private Context ctx;  
  4.     int mGalleryItemBackground;  
  5.     File[] files;  
  6.     int width, height;  
  7.     public ImageAdapter(Context ctx)  
  8.     {  
  9.         try  
  10.         {  
  11.             this.ctx = ctx;  
  12.             DisplayMetrics dm = new DisplayMetrics();  
  13.             ((Activity)this.ctx).WindowManager.DefaultDisplay.GetMetrics(dm);  
  14.             width = dm.WidthPixels;  
  15.             height = dm.HeightPixels;  
  16.             if (Android.OS.Environment.ExternalStorageState.Equals(Android.OS.Environment.MediaMounted))  
  17.             {  
  18.                 File path = Android.OS.Environment.ExternalStorageDirectory;  
  19.                 File file = new File(path.Path + "/Pictures/Camera");  
  20.                 if (file.Exists())  
  21.                     files = file.ListFiles();  
  22.                 else  
  23.                     throw new System.Exception("SD卡中不存在此路径");  
  24.             }  
  25.             else if (Android.OS.Environment.ExternalStorageState.Equals(Android.OS.Environment.MediaRemoved))  
  26.                 throw new System.Exception("没有SD卡");  
  27.             Android.Content.Res.TypedArray a = ctx.ObtainStyledAttributes(Resource.Styleable.Gallery);  
  28.             mGalleryItemBackground = a.GetResourceId(Resource.Styleable.Gallery_android_galleryItemBackground, Android.Graphics.Color.Azure);  
  29.             a.Recycle();  
  30.         }  
  31.         catch (System.Exception ex)  
  32.         {  
  33.             MessageBox.ShowErrorMessage(ctx, ex);  
  34.         }  
  35.     }  
  36.     public override int Count  
  37.     {  
  38.         get  
  39.         {  
  40.             if (files == null)  
  41.                 return 0;  
  42.             return this.files.Length;  
  43.         }  
  44.     }  
  45.     public override Java.Lang.Object GetItem(int position)  
  46.     {  
  47.         return position;  
  48.     }  
  49.     public override long GetItemId(int position)  
  50.     {  
  51.         return position;  
  52.     }  
  53.     public override View GetView(int position, View convertView, ViewGroup parent)  
  54.     {  
  55.         try  
  56.         {  
  57.             ImageView v = new ImageView(this.ctx);  
  58.             Bitmap bmp = BitmapFactory.DecodeFile(files[position].Path);  
  59.             v.SetImageBitmap(bmp);  
  60.             v.SetScaleType(ImageView.ScaleType.FitXy);  
  61.             v.LayoutParameters = new Gallery.LayoutParams(width, height);  
  62.             v.SetBackgroundResource(mGalleryItemBackground);  
  63.             return v;  
  64.         }  
  65.         catch (System.Exception ex)  
  66.         {  
  67.             MessageBox.ShowErrorMessage(this.ctx, ex);  
  68.             return null;  
  69.         }  
  70.     }  
  71. }  
 

然后我们在增加一点小功能,就是在点击图片的时候,弹出个小提示,提示你点击的是哪张图片。这里用到了Toast对象,其实Toast对象我们在第四篇文章介绍布局的时候就已经用过了,但没有具体介绍过它,Toast是Android专属的提示小对象,它的使用方法相当简单,但用途却很广泛。基本上,Toast就是一个简短的小信息,将要告诉用户的信息以一个浮动在最上层的View显示,显示Toast之后,静待几秒就会自动消失,最常见的应用就是音量大小的调整。当单击音量调整按钮之后,会看见跳出的音量指示Toast对象,等待调整完之后便会消失。

[c-sharp]  view plain copy print ?
  1. Gallery mGallery = FindViewById<Gallery>(Resource.Id.gallery);  
  2. mGallery.Adapter = new ImageAdapter(this);  
  3. mGallery.ItemClick += (sender, e) =>  
  4. {  
  5.     Toast.MakeText(thisstring.Format("你点击的是{0}号图片", e.Position), ToastLength.Short).Show();  
  6. };  
 

 

运行后的效果:

 

MonoDroid学习笔记(八)—— 如IPhone拖动相片特效,Gallery画廊

 

Toast显示后会在一定时间内消失,在Toast.MakeText方法的第三个参数是一个ToastLength枚举,颗选择Long或Short,前者时间较长,后者较短。

当然,你也可以使用重写Toast对象的方法,自定义Toast显示的Layout,以不同于系统内置的方式显示Toast对象,如要在Toast里显示图片,方式如下:

[c-sharp]  view plain copy print ?
  1. Gallery mGallery = FindViewById<Gallery>(Resource.Id.gallery);  
  2. mGallery.Adapter = new ImageAdapter(this);  
  3. mGallery.ItemClick += (sender, e) =>  
  4. {  
  5.     Toast t = new Toast(this);  
  6.     ImageView img = new ImageView(this);  
  7.     img.SetImageResource(Android.Resource.Drawable.IcMenuCamera);  
  8.     t.View = img;  
  9.     t.Show();  
  10.     //Toast.MakeText(this, string.Format("你点击的是{0}号图片", e.Position), ToastLength.Short).Show();  
  11. };  
 

MonoDroid学习笔记(八)—— 如IPhone拖动相片特效,Gallery画廊

 

最后说一下BitmapFactory(位于Android.Graphics命名空间下),它是Android API提供的对象,可以将图片文件转换成Bitmap对象,范例中使用的DecodeFile()方法可以将手机系统中的图片文件转换成为Bitmap对象。另外,BitmapFactory也提供了其他的方法,如DecodeResource可以将预先存入的图片文件转换成Bitmap对象,DecodeStream方法则可以将InputStream转换成Bitmap对象。

你可能感兴趣的:(gallery)