我们知道,进入百度图片后,输入一个关键字后,首先看到的是很多缩略图,当我们点击某张缩略图时,我们就可以进入到大图显示页面,在
大图显示页面,中包含了一个图片画廊,同时当前大图为刚刚我们点击的那张图片。现在我们看看在Android中如何实现类似的效果:
首先,我们需要有一个控件来显示缩略图,这里没有什么比GridView更加合适了。
配置文件如下:
我们知道,进入百度图片后,输入一个关键字后,首先看到的是很多缩略图,当我们点击某张缩略图时,我们就可以进入到大图显示页面,在
大图显示页面,中包含了一个图片画廊,同时当前大图为刚刚我们点击的那张图片。现在我们看看在Android中如何实现类似的效果:
首先,我们需要有一个控件来显示缩略图,这里没有什么比GridView更加合适了。
配置文件如下:
view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?>
02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03. android:orientation="vertical"
04. android:layout_width="fill_parent"
05. android:layout_height="fill_parent"
06. >
07. <GridView
08. android:id="@+id/view_photos"
09. android:layout_width="fill_parent"
10. android:layout_height="fill_parent"
11. android:layout_marginTop="10dp"
12. android:columnWidth="100dp"
13. android:numColumns="auto_fit"
14. android:horizontalSpacing="5dp"
15. android:verticalSpacing="5dp"
16. android:listSelector="@drawable/frame_select" />
17.</LinearLayout>
对于GridView中每一项是一张缩略图,我们需要继承BaseAdapter,实现自己的一个GridImageAdapter,代码:
view plaincopy to clipboardprint?
01.package com.liner.manager;
02.import java.util.List;
03.import com.liner.manager.adapter.GridImageAdapter;
04.import android.app.Activity;
05.import android.graphics.Bitmap;
06.import android.os.Bundle;
07.import android.view.View;
08.import android.widget.AdapterView;
09.import android.widget.Gallery;
10.import android.widget.ImageButton;
11.import android.widget.AdapterView.OnItemClickListener;
12.public class GalleryActivity extends Activity{
13.
14. private ImageButton currentImage;
15. private Gallery gallery;
16.
17. private int[] thumbIds;
18. private int currentPos;
19.
20. private Bitmap currentBitmap;
21.
22. private List<Bitmap> bitmapCache;
23.
24. public void onCreate(Bundle savedInstanceState){
25. super.onCreate(savedInstanceState);
26. setContentView(R.layout.gallery);
27.
28. currentImage = (ImageButton)this.findViewById(R.id.image_current);
29. gallery = (Gallery)this.findViewById(R.id.image_gallery);
30. gallery.setOnItemClickListener(galleryItemClickListener);
31. init();
32. }
33.
34. private OnItemClickListener galleryItemClickListener = new OnItemClickListener() {
35. @Override
36. public void onItemClick(AdapterView<?> p, View v, int position,
37. long id) {
38. // 点击事件
39. showCurrentImage(position);
40. }
41. };
42.
43. private void init(){
44. thumbIds = this.getIntent().getIntArrayExtra("thumbIds");
45. currentPos = this.getIntent().getIntExtra("currentPos",0);
46. //galleryIds = this.getThumbnailIds(currentPos); //当前的gallery里的图片信息
47. bitmapCache = BitmapUtils.queryThumbnailListByIds(this, thumbIds);
48. GridImageAdapter adapter = new GridImageAdapter(this.getApplication(), bitmapCache);
49. gallery.setAdapter(adapter);
50. gallery.setSelection(currentPos);
51.
52. showCurrentImage(currentPos);
53.
54. }
55.
56. private void showCurrentImage(int position){
57.
58. if(currentBitmap != null){
59. currentBitmap.recycle();
60. }
61.
62. currentBitmap = BitmapUtils.queryImageByThumbnailId(GalleryActivity.this, thumbIds[position]);
63. if(currentBitmap != null){
64. currentImage.setImageBitmap(currentBitmap);
65. }else{
66. //什么都不做
67. }
68.
69. //releaseBitmaps();
70. }
71.
72. /**
73. * 将Gallery当前可见的显示之前的3张,后3张缓存起来,其余的释放掉,这样是为了放置内存不够用
74. * 之所以前三张后三张,是为了Gallery可以滑动的更加顺畅
75. */
76. private void releaseBitmaps(){
77. int start = gallery.getFirstVisiblePosition()-3; //缓存的起始位置
78. int end = gallery.getLastVisiblePosition()+3; //缓存的结束位置
79.
80. Bitmap delBitmap;
81. for(int i=0; i<start; i++){
82. delBitmap = bitmapCache.get(i);
83. if(delBitmap != null){
84. bitmapCache.remove(i);
85. delBitmap.recycle();
86. }
87. }
88. for(int i=end+1; i<bitmapCache.size(); i++){
89. delBitmap = bitmapCache.get(i);
90. if(delBitmap != null){
91. bitmapCache.remove(i);
92. delBitmap.recycle();
93. }
94. }
95. }
96.
97. /**
98. * 获取当前位置的前三个Id和后三个Id
99. * @param position
100. * @return
101. */
102. private Integer[] getThumbnailIds(int position){
103. Integer[] ids = new Integer[]{0,0,0,0,0,0,0};
104. int currPos = 0;
105. //关于这里的处理,比较复杂
106. for(int i=3; i>0; i--){
107. if(position - i >= 0){
108. currPos = 3-i;
109. ids[currPos] = thumbIds[position-i];
110. }
111. }
112. ids[++currPos] = thumbIds[position]; //当前Id
113. //currGallerySelection = currPos;
114. //这样右边剩下的位置数就是7-currPos-1
115. for(int i=1; i<=6-currPos;i++){
116. if(position+i < thumbIds.length){
117. ids[currPos+i] = thumbIds[position+i];
118. }
119. }
120.
121. return ids;
122. }
123.}
然后,我们就可以在Activity中通过查询MediaStore的多媒体图片库来查询所有的图片的缩略图,缩略图所在的位置是:
MediaStore.Images.Thumbnails。Activity代码如下:
view plaincopy to clipboardprint?
01.package com.liner.manager;
02.import java.util.ArrayList;
03.import java.util.List;
04.import com.liner.manager.adapter.GridImageAdapter;
05.import android.app.Activity;
06.import android.content.Intent;
07.import android.database.Cursor;
08.import android.graphics.Bitmap;
09.import android.graphics.BitmapFactory;
10.import android.net.Uri;
11.import android.os.Bundle;
12.import android.provider.MediaStore;
13.import android.view.View;
14.import android.widget.Adapter;
15.import android.widget.AdapterView;
16.import android.widget.GridView;
17.import android.widget.Toast;
18.public class MainActivity extends Activity {
19. private GridView photoView;
20. private GridImageAdapter imageAdapter;
21.
22. private Cursor cursor;
23. private int[] thumbIds;
24.
25. @Override
26. public void onCreate(Bundle savedInstanceState) {
27. super.onCreate(savedInstanceState);
28. setContentView(R.layout.main);
29.
30. photoView = (GridView)this.findViewById(R.id.view_photos);
31. photoView.setOnItemClickListener(photoClickListener);
32.
33. //showImages();
34. showThumbnails();
35. }
36.
37.
38. private void showThumbnails(){
39.
40. cursor = BitmapUtils.queryThumbnails(this);
41. if(cursor.moveToFirst()){
42. List<Bitmap> bitmaps = new ArrayList<Bitmap>();
43. thumbIds = new int[cursor.getCount()];
44. for(int i=0; i<cursor.getCount();i++){
45. cursor.moveToPosition(i);
46. String currPath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
47. thumbIds[i] = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
48. Bitmap b = BitmapUtils.decodeBitmap(currPath,100,100);
49. bitmaps.add(b);
50. }
51. imageAdapter = new GridImageAdapter(this.getApplication(), bitmaps);
52. photoView.setAdapter(imageAdapter);
53. }
54. }
55.
56. private AdapterView.OnItemClickListener photoClickListener = new AdapterView.OnItemClickListener() {
57. @Override
58. public void onItemClick(AdapterView<?> p, View v, int position,
59. long id) {
60. //点击某张缩略图时,转到图片显示界面
61. Intent intent = new Intent();
62. intent.setClass(MainActivity.this, GalleryActivity.class);
63. intent.putExtra("thumbIds", thumbIds);
64. intent.putExtra("currentPos", position);
65. startActivity(intent);
66. }
67. };
68.
69.}
注意到,我们记录了,所有缩略图对应的id号,和当前的用户选择的位置,然后通过Intent传递到第二个展示界面。第二个界面的布局文件如下:我们用了一个Gallery和一个ImageButton来实现
view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?>
02.<LinearLayout
03. xmlns:android="http://schemas.android.com/apk/res/android"
04. android:layout_width="fill_parent"
05. android:layout_height="fill_parent"
06. android:orientation="vertical">
07. <Gallery
08. android:id="@+id/image_gallery"
09. android:layout_width="fill_parent"
10. android:layout_height="100dp"
11. />
12. <ImageButton
13. android:id="@+id/image_current"
14. android:layout_width="fill_parent"
15. android:layout_height="fill_parent"
16. android:padding="10dp"
17. android:layout_marginTop="10dp"
18. />
19.</LinearLayout>
然后,对应的Activity如下:
view plaincopy to clipboardprint?
01.package com.liner.manager;
02.import java.util.List;
03.import com.liner.manager.adapter.GridImageAdapter;
04.import android.app.Activity;
05.import android.graphics.Bitmap;
06.import android.os.Bundle;
07.import android.view.View;
08.import android.widget.AdapterView;
09.import android.widget.Gallery;
10.import android.widget.ImageButton;
11.import android.widget.AdapterView.OnItemClickListener;
12.public class GalleryActivity extends Activity{
13.
14. private ImageButton currentImage;
15. private Gallery gallery;
16.
17. private int[] thumbIds;
18. private int currentPos;
19.
20. private Bitmap currentBitmap;
21.
22. private List<Bitmap> bitmapCache;
23.
24. public void onCreate(Bundle savedInstanceState){
25. super.onCreate(savedInstanceState);
26. setContentView(R.layout.gallery);
27.
28. currentImage = (ImageButton)this.findViewById(R.id.image_current);
29. gallery = (Gallery)this.findViewById(R.id.image_gallery);
30. gallery.setOnItemClickListener(galleryItemClickListener);
31. init();
32. }
33.
34. private OnItemClickListener galleryItemClickListener = new OnItemClickListener() {
35. @Override
36. public void onItemClick(AdapterView<?> p, View v, int position,
37. long id) {
38. // 点击事件
39. showCurrentImage(position);
40. }
41. };
42.
43. private void init(){
44. thumbIds = this.getIntent().getIntArrayExtra("thumbIds");
45. currentPos = this.getIntent().getIntExtra("currentPos",0);
46. //galleryIds = this.getThumbnailIds(currentPos); //当前的gallery里的图片信息
47. bitmapCache = BitmapUtils.queryThumbnailListByIds(this, thumbIds);
48. GridImageAdapter adapter = new GridImageAdapter(this.getApplication(), bitmapCache);
49. gallery.setAdapter(adapter);
50. gallery.setSelection(currentPos);
51.
52. showCurrentImage(currentPos);
53.
54. }
55.
56. private void showCurrentImage(int position){
57.
58. if(currentBitmap != null){
59. currentBitmap.recycle();
60. }
61.
62. currentBitmap = BitmapUtils.queryImageByThumbnailId(GalleryActivity.this, thumbIds[position]);
63. if(currentBitmap != null){
64. currentImage.setImageBitmap(currentBitmap);
65. }else{
66. //什么都不做
67. }
68.
69. //releaseBitmaps();
70. }
71.
72.}
可以看到,当用户点击Gallery中某一项时,触发onItemClick事件,在其中,我们通过根据该缩略图对应的Image_ID来从MediaStore.Images.Media中查询该缩略图对应的大图。并在ImageButton中显示。
这里当图片很多时,可能会出现内存溢出,为了避免这种情况,可以更加Gallery的特点,使用缓存。保存当前可见的缩略图的前三个到后三个。其余的全部recycle。当用户点击Gallery的时候,在判断当前的位置,如果大于或小于某个值时,则重新更新缓存。这样保证内存中的缩略图的个数总是6+Gallery.getLastVisiblePosition-Gallery.getFirstVisiblePosition个。其实这就是浮动缓存窗口,一个固定大小窗口在整个坐标(全部缩略图)上游动。这里没有实现,以后待续。
同时,你可能已经注意到,程序中使用到了一个BitmapUtils类,这个类是封装了一系列对查询图片,并将其解析为Bitmap的类。
代码如下:
view plaincopy to clipboardprint?
01.package com.liner.manager;
02.import java.util.ArrayList;
03.import java.util.List;
04.import android.app.Activity;
05.import android.database.Cursor;
06.import android.graphics.Bitmap;
07.import android.graphics.BitmapFactory;
08.import android.provider.MediaStore;
09.import android.util.Log;
10.public final class BitmapUtils {
11.
12.
13.
14. public static Bitmap decodeBitmap(String path, int displayWidth, int displayHeight){
15. BitmapFactory.Options op = new BitmapFactory.Options();
16. op.inJustDecodeBounds = true;
17. Bitmap bmp = BitmapFactory.decodeFile(path, op); //获取尺寸信息
18. //获取比例大小
19. int wRatio = (int)Math.ceil(op.outWidth/(float)displayWidth);
20. int hRatio = (int)Math.ceil(op.outHeight/(float)displayHeight);
21. //如果超出指定大小,则缩小相应的比例
22. if(wRatio > 1 && hRatio > 1){
23. if(wRatio > hRatio){
24. op.inSampleSize = wRatio;
25. }else{
26. op.inSampleSize = hRatio;
27. }
28. }
29. op.inJustDecodeBounds = false;
30. bmp = BitmapFactory.decodeFile(path, op);
31. return Bitmap.createScaledBitmap(bmp, displayWidth, displayHeight, true);
32. }
33.
34. /**
35. * 采用复杂计算来决定缩放
36. * @param path
37. * @param maxImageSize
38. * @return
39. */
40. public static Bitmap decodeBitmap(String path, int maxImageSize){
41. BitmapFactory.Options op = new BitmapFactory.Options();
42. op.inJustDecodeBounds = true;
43. Bitmap bmp = BitmapFactory.decodeFile(path, op); //获取尺寸信息
44. int scale = 1;
45. if(op.outWidth > maxImageSize || op.outHeight > maxImageSize){
46. scale = (int)Math.pow(2, (int)Math.round(Math.log(maxImageSize/(double)Math.max(op.outWidth, op.outHeight))/Math.log(0.5)));
47. }
48. op.inJustDecodeBounds = false;
49. op.inSampleSize = scale;
50. bmp = BitmapFactory.decodeFile(path, op);
51. return bmp;
52. }
53.
54.
55. public static Cursor queryThumbnails(Activity context){
56. String[] columns = new String[]{
57. MediaStore.Images.Thumbnails.DATA,
58. MediaStore.Images.Thumbnails._ID,
59. MediaStore.Images.Thumbnails.IMAGE_ID
60. };
61. return context.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, columns, null, null, MediaStore.Images.Thumbnails.DEFAULT_SORT_ORDER);
62. }
63.
64. public static Cursor queryThumbnails(Activity context, String selection, String[] selectionArgs){
65. String[] columns = new String[]{
66. MediaStore.Images.Thumbnails.DATA,
67. MediaStore.Images.Thumbnails._ID,
68. MediaStore.Images.Thumbnails.IMAGE_ID
69. };
70. return context.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, columns, selection, selectionArgs, MediaStore.Images.Thumbnails.DEFAULT_SORT_ORDER);
71. }
72.
73. public static Bitmap queryThumbnailById(Activity context, int thumbId){
74. String selection = MediaStore.Images.Thumbnails._ID + " = ?";
75. String[] selectionArgs = new String[]{
76. thumbId+""
77. };
78. Cursor cursor = BitmapUtils.queryThumbnails(context,selection,selectionArgs);
79.
80. if(cursor.moveToFirst()){
81. String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
82. cursor.close();
83. return BitmapUtils.decodeBitmap(path, 100, 100);
84. }else{
85. cursor.close();
86. return null;
87. }
88. }
89.
90. public static Bitmap[] queryThumbnailsByIds(Activity context, Integer[] thumbIds){
91. Bitmap[] bitmaps = new Bitmap[thumbIds.length];
92. for(int i=0; i<bitmaps.length; i++){
93. bitmaps[i] = BitmapUtils.queryThumbnailById(context, thumbIds[i]);
94. }
95.
96. return bitmaps;
97. }
98.
99. /**
100. * 获取全部
101. * @param context
102. * @return
103. */
104. public static List<Bitmap> queryThumbnailList(Activity context){
105. List<Bitmap> bitmaps = new ArrayList<Bitmap>();
106. Cursor cursor = BitmapUtils.queryThumbnails(context);
107. for(int i=0; i<cursor.getCount(); i++){
108. cursor.moveToPosition(i);
109. String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
110. Bitmap b = BitmapUtils.decodeBitmap(path, 100, 100);
111. bitmaps.add(b);
112. }
113. cursor.close();
114. return bitmaps;
115. }
116.
117. public static List<Bitmap> queryThumbnailListByIds(Activity context, int[] thumbIds){
118. List<Bitmap> bitmaps = new ArrayList<Bitmap>();
119. for(int i=0; i<thumbIds.length; i++){
120. Bitmap b = BitmapUtils.queryThumbnailById(context, thumbIds[i]);
121. bitmaps.add(b);
122. }
123.
124. return bitmaps;
125. }
126.
127. public static Cursor queryImages(Activity context){
128. String[] columns = new String[]{
129. MediaStore.Images.Media._ID,
130. MediaStore.Images.Media.DATA,
131. MediaStore.Images.Media.DISPLAY_NAME
132. };
133. return context.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
134. }
135.
136. public static Cursor queryImages(Activity context, String selection, String[] selectionArgs){
137. String[] columns = new String[]{
138. MediaStore.Images.Media._ID,
139. MediaStore.Images.Media.DATA,
140. MediaStore.Images.Media.DISPLAY_NAME
141. };
142. return context.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selection, selectionArgs, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
143. }
144.
145. public static Bitmap queryImageById(Activity context, int imageId){
146. String selection = MediaStore.Images.Media._ID + "=?";
147. String[] selectionArgs = new String[]{
148. imageId + ""
149. };
150. Cursor cursor = BitmapUtils.queryImages(context, selection, selectionArgs);
151. if(cursor.moveToFirst()){
152. String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
153. cursor.close();
154. //return BitmapUtils.decodeBitmap(path, 260, 260);
155. return BitmapUtils.decodeBitmap(path, 220); //看看和上面这种方式的差别,看了,差不多
156. }else{
157. cursor.close();
158. return null;
159. }
160. }
161.
162. /**
163. * 根据缩略图的Id获取对应的大图
164. * @param context
165. * @param thumbId
166. * @return
167. */
168. public static Bitmap queryImageByThumbnailId(Activity context, Integer thumbId){
169.
170. String selection = MediaStore.Images.Thumbnails._ID + " = ?";
171. String[] selectionArgs = new String[]{
172. thumbId+""
173. };
174. Cursor cursor = BitmapUtils.queryThumbnails(context, selection, selectionArgs);
175.
176. if(cursor.moveToFirst()){
177. int imageId = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
178. cursor.close();
179. return BitmapUtils.queryImageById(context, imageId);
180. }else{
181. cursor.close();
182. return null;
183. }
184. }
185.}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chenjie19891104/archive/2011/04/20/6336439.aspx