Android多媒体学习十一:实现仿百度图片查看功能

本文原作者 chenjie19891104

原文地址:

Android多媒体学习十一:实现仿百度图片查看功能


我们知道,进入百度图片后,输入一个关键字后,首先看到的是很多缩略图,当我们点击某张缩略图时,我们就可以进入到大图显示页面,在

大图显示页面,中包含了一个图片画廊,同时当前大图为刚刚我们点击的那张图片。现在我们看看在Android中如何实现类似的效果:

 

首先,我们需要有一个控件来显示缩略图,这里没有什么比GridView更加合适了。

 

配置文件如下:

 

  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.     <GridView  
  8.         android:id="@+id/view_photos"   
  9.         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,代码:

 

  1. package com.liner.manager;  
  2. import java.util.List;  
  3. import com.liner.manager.adapter.GridImageAdapter;  
  4. import android.app.Activity;  
  5. import android.graphics.Bitmap;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.widget.AdapterView;  
  9. 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代码如下:

 

  1. package com.liner.manager;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. import com.liner.manager.adapter.GridImageAdapter;  
  5. import android.app.Activity;  
  6. import android.content.Intent;  
  7. import android.database.Cursor;  
  8. import android.graphics.Bitmap;  
  9. 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来实现

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:layout_width="fill_parent"  
  5.   android:layout_height="fill_parent"  
  6.   android:orientation="vertical">  
  7.     <Gallery  
  8.         android:id="@+id/image_gallery"   
  9.         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如下:

 

  1. package com.liner.manager;  
  2. import java.util.List;  
  3. import com.liner.manager.adapter.GridImageAdapter;  
  4. import android.app.Activity;  
  5. import android.graphics.Bitmap;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.widget.AdapterView;  
  9. 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的类。

 

代码如下:

 

  1. package com.liner.manager;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. import android.app.Activity;  
  5. import android.database.Cursor;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.provider.MediaStore;  
  9. 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, nullnull, 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, 100100);  
  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, 100100);  
  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, nullnull, 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. }  

 

这样就实现了,类似百度图片浏览的效果。效果图如下:

 

缩略图

 

大图预览

 




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值