Android仿百度圖片查看功能
我們知道,進(jìn)入百度圖片后,輸入一個(gè)關(guān)鍵字后,首先看到的是很多縮略圖,當(dāng)我們點(diǎn)擊某張縮略圖時(shí),我們就可以進(jìn)入到大圖顯示頁(yè)面,在大圖顯示頁(yè)面,中包含了一個(gè)圖片畫(huà)廊,同時(shí)當(dāng)前大圖為剛剛我們點(diǎn)擊的那張圖片?,F(xiàn)在我們看看在Android中如何實(shí)現(xiàn)類(lèi)似的效果:
首先,我們需要有一個(gè)控件來(lái)顯示縮略圖,這里沒(méi)有什么比GridView更加合適了。
配置文件如下:
<?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"
>
<GridView
android:id="@+id/view_photos"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp"
android:columnWidth="100dp"
android:numColumns="auto_fit"
android:horizontalSpacing="5dp"
android:verticalSpacing="5dp"
android:listSelector="@drawable/frame_select" />
</LinearLayout>
對(duì)于GridView中每一項(xiàng)是一張縮略圖,我們需要繼承BaseAdapter,實(shí)現(xiàn)自己的一個(gè)GridImageAdapter,代碼:
package com.liner.manager;
import java.util.List;
import com.liner.manager.adapter.GridImageAdapter;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.ImageButton;
import android.widget.AdapterView.OnItemClickListener;
public class GalleryActivity extends Activity{
private ImageButton currentImage;
private Gallery gallery;
private int[] thumbIds;
private int currentPos;
private Bitmap currentBitmap;
private List<Bitmap> bitmapCache;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery);
currentImage = (ImageButton)this.findViewById(R.id.image_current);
gallery = (Gallery)this.findViewById(R.id.image_gallery);
gallery.setOnItemClickListener(galleryItemClickListener);
init();
}
private OnItemClickListener galleryItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> p, View v, int position,
long id) {
// 點(diǎn)擊事件
showCurrentImage(position);
}
};
private void init(){
thumbIds = this.getIntent().getIntArrayExtra("thumbIds");
currentPos = this.getIntent().getIntExtra("currentPos",0);
//galleryIds = this.getThumbnailIds(currentPos); //當(dāng)前的gallery里的圖片信息
bitmapCache = BitmapUtils.queryThumbnailListByIds(this, thumbIds);
GridImageAdapter adapter = new GridImageAdapter(this.getApplication(), bitmapCache);
gallery.setAdapter(adapter);
gallery.setSelection(currentPos);
showCurrentImage(currentPos);
}
private void showCurrentImage(int position){
if(currentBitmap != null){
currentBitmap.recycle();
}
currentBitmap = BitmapUtils.queryImageByThumbnailId(GalleryActivity.this, thumbIds[position]);
if(currentBitmap != null){
currentImage.setImageBitmap(currentBitmap);
}else{
//什么都不做
}
//releaseBitmaps();
}
/**
* 將Gallery當(dāng)前可見(jiàn)的顯示之前的3張,后3張緩存起來(lái),其余的釋放掉,這樣是為了放置內(nèi)存不夠用
* 之所以前三張后三張,是為了Gallery可以滑動(dòng)的更加順暢
*/
private void releaseBitmaps(){
int start = gallery.getFirstVisiblePosition()-3; //緩存的起始位置
int end = gallery.getLastVisiblePosition()+3; //緩存的結(jié)束位置
Bitmap delBitmap;
for(int i=0; i<start; i++){
delBitmap = bitmapCache.get(i);
if(delBitmap != null){
bitmapCache.remove(i);
delBitmap.recycle();
}
}
for(int i=end+1; i<bitmapCache.size(); i++){
delBitmap = bitmapCache.get(i);
if(delBitmap != null){
bitmapCache.remove(i);
delBitmap.recycle();
}
}
}
/**
* 獲取當(dāng)前位置的前三個(gè)Id和后三個(gè)Id
* @param position
* @return
*/
private Integer[] getThumbnailIds(int position){
Integer[] ids = new Integer[]{0,0,0,0,0,0,0};
int currPos = 0;
//關(guān)于這里的處理,比較復(fù)雜
for(int i=3; i>0; i--){
if(position - i >= 0){
currPos = 3-i;
ids[currPos] = thumbIds[position-i];
}
}
ids[++currPos] = thumbIds[position]; //當(dāng)前Id
//currGallerySelection = currPos;
//這樣右邊剩下的位置數(shù)就是7-currPos-1
for(int i=1; i<=6-currPos;i++){
if(position+i < thumbIds.length){
ids[currPos+i] = thumbIds[position+i];
}
}
return ids;
}
}
然后,我們就可以在Activity中通過(guò)查詢MediaStore的多媒體圖片庫(kù)來(lái)查詢所有的圖片的縮略圖,縮略圖所在的位置是:
MediaStore.Images.Thumbnails。Activity代碼如下:
package com.liner.manager;
import java.util.ArrayList;
import java.util.List;
import com.liner.manager.adapter.GridImageAdapter;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
public class MainActivity extends Activity {
private GridView photoView;
private GridImageAdapter imageAdapter;
private Cursor cursor;
private int[] thumbIds;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
photoView = (GridView)this.findViewById(R.id.view_photos);
photoView.setOnItemClickListener(photoClickListener);
//showImages();
showThumbnails();
}
private void showThumbnails(){
cursor = BitmapUtils.queryThumbnails(this);
if(cursor.moveToFirst()){
List<Bitmap> bitmaps = new ArrayList<Bitmap>();
thumbIds = new int[cursor.getCount()];
for(int i=0; i<cursor.getCount();i++){
cursor.moveToPosition(i);
String currPath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
thumbIds[i] = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
Bitmap b = BitmapUtils.decodeBitmap(currPath,100,100);
bitmaps.add(b);
}
imageAdapter = new GridImageAdapter(this.getApplication(), bitmaps);
photoView.setAdapter(imageAdapter);
}
}
private AdapterView.OnItemClickListener photoClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> p, View v, int position,
long id) {
//點(diǎn)擊某張縮略圖時(shí),轉(zhuǎn)到圖片顯示界面
Intent intent = new Intent();
intent.setClass(MainActivity.this, GalleryActivity.class);
intent.putExtra("thumbIds", thumbIds);
intent.putExtra("currentPos", position);
startActivity(intent);
}
};
}
注意到,我們記錄了,所有縮略圖對(duì)應(yīng)的id號(hào),和當(dāng)前的用戶選擇的位置,然后通過(guò)Intent傳遞到第二個(gè)展示界面。第二個(gè)界面的布局文件如下:我們用了一個(gè)Gallery和一個(gè)ImageButton來(lái)實(shí)現(xiàn)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Gallery
android:id="@+id/image_gallery"
android:layout_width="fill_parent"
android:layout_height="100dp"
/>
<ImageButton
android:id="@+id/image_current"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:layout_marginTop="10dp"
/>
</LinearLayout>
然后,對(duì)應(yīng)的Activity如下:
package com.liner.manager;
import java.util.List;
import com.liner.manager.adapter.GridImageAdapter;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.ImageButton;
import android.widget.AdapterView.OnItemClickListener;
public class GalleryActivity extends Activity{
private ImageButton currentImage;
private Gallery gallery;
private int[] thumbIds;
private int currentPos;
private Bitmap currentBitmap;
private List<Bitmap> bitmapCache;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery);
currentImage = (ImageButton)this.findViewById(R.id.image_current);
gallery = (Gallery)this.findViewById(R.id.image_gallery);
gallery.setOnItemClickListener(galleryItemClickListener);
init();
}
private OnItemClickListener galleryItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> p, View v, int position,
long id) {
// 點(diǎn)擊事件
showCurrentImage(position);
}
};
private void init(){
thumbIds = this.getIntent().getIntArrayExtra("thumbIds");
currentPos = this.getIntent().getIntExtra("currentPos",0);
//galleryIds = this.getThumbnailIds(currentPos); //當(dāng)前的gallery里的圖片信息
bitmapCache = BitmapUtils.queryThumbnailListByIds(this, thumbIds);
GridImageAdapter adapter = new GridImageAdapter(this.getApplication(), bitmapCache);
gallery.setAdapter(adapter);
gallery.setSelection(currentPos);
showCurrentImage(currentPos);
}
private void showCurrentImage(int position){
if(currentBitmap != null){
currentBitmap.recycle();
}
currentBitmap = BitmapUtils.queryImageByThumbnailId(GalleryActivity.this, thumbIds[position]);
if(currentBitmap != null){
currentImage.setImageBitmap(currentBitmap);
}else{
//什么都不做
}
//releaseBitmaps();
}
}
可以看到,當(dāng)用戶點(diǎn)擊Gallery中某一項(xiàng)時(shí),觸發(fā)onItemClick事件,在其中,我們通過(guò)根據(jù)該縮略圖對(duì)應(yīng)的Image_ID來(lái)從MediaStore.Images.Media中查詢?cè)摽s略圖對(duì)應(yīng)的大圖。并在ImageButton中顯示。
這里當(dāng)圖片很多時(shí),可能會(huì)出現(xiàn)內(nèi)存溢出,為了避免這種情況,可以更加Gallery的特點(diǎn),使用緩存。保存當(dāng)前可見(jiàn)的縮略圖的前三個(gè)到后三個(gè)。其余的全部recycle。當(dāng)用戶點(diǎn)擊Gallery的時(shí)候,在判斷當(dāng)前的位置,如果大于或小于某個(gè)值時(shí),則重新更新緩存。這樣保證內(nèi)存中的縮略圖的個(gè)數(shù)總是6+Gallery.getLastVisiblePosition-Gallery.getFirstVisiblePosition個(gè)。其實(shí)這就是浮動(dòng)緩存窗口,一個(gè)固定大小窗口在整個(gè)坐標(biāo)(全部縮略圖)上游動(dòng)。這里沒(méi)有實(shí)現(xiàn),以后待續(xù)。
同時(shí),你可能已經(jīng)注意到,程序中使用到了一個(gè)BitmapUtils類(lèi),這個(gè)類(lèi)是封裝了一系列對(duì)查詢圖片,并將其解析為Bitmap的類(lèi)。
代碼如下:
package com.liner.manager;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.provider.MediaStore;
import android.util.Log;
public final class BitmapUtils {
public static Bitmap decodeBitmap(String path, int displayWidth, int displayHeight){
BitmapFactory.Options op = new BitmapFactory.Options();
op.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(path, op); //獲取尺寸信息
//獲取比例大小
int wRatio = (int)Math.ceil(op.outWidth/(float)displayWidth);
int hRatio = (int)Math.ceil(op.outHeight/(float)displayHeight);
//如果超出指定大小,則縮小相應(yīng)的比例
if(wRatio > 1 && hRatio > 1){
if(wRatio > hRatio){
op.inSampleSize = wRatio;
}else{
op.inSampleSize = hRatio;
}
}
op.inJustDecodeBounds = false;
bmp = BitmapFactory.decodeFile(path, op);
return Bitmap.createScaledBitmap(bmp, displayWidth, displayHeight, true);
}
/**
* 采用復(fù)雜計(jì)算來(lái)決定縮放
* @param path
* @param maxImageSize
* @return
*/
public static Bitmap decodeBitmap(String path, int maxImageSize){
BitmapFactory.Options op = new BitmapFactory.Options();
op.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(path, op); //獲取尺寸信息
int scale = 1;
if(op.outWidth > maxImageSize || op.outHeight > maxImageSize){
scale = (int)Math.pow(2, (int)Math.round(Math.log(maxImageSize/(double)Math.max(op.outWidth, op.outHeight))/Math.log(0.5)));
}
op.inJustDecodeBounds = false;
op.inSampleSize = scale;
bmp = BitmapFactory.decodeFile(path, op);
return bmp;
}
public static Cursor queryThumbnails(Activity context){
String[] columns = new String[]{
MediaStore.Images.Thumbnails.DATA,
MediaStore.Images.Thumbnails._ID,
MediaStore.Images.Thumbnails.IMAGE_ID
};
return context.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, columns, null, null, MediaStore.Images.Thumbnails.DEFAULT_SORT_ORDER);
}
public static Cursor queryThumbnails(Activity context, String selection, String[] selectionArgs){
String[] columns = new String[]{
MediaStore.Images.Thumbnails.DATA,
MediaStore.Images.Thumbnails._ID,
MediaStore.Images.Thumbnails.IMAGE_ID
};
return context.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, columns, selection, selectionArgs, MediaStore.Images.Thumbnails.DEFAULT_SORT_ORDER);
}
public static Bitmap queryThumbnailById(Activity context, int thumbId){
String selection = MediaStore.Images.Thumbnails._ID + " = ?";
String[] selectionArgs = new String[]{
thumbId+""
};
Cursor cursor = BitmapUtils.queryThumbnails(context,selection,selectionArgs);
if(cursor.moveToFirst()){
String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
cursor.close();
return BitmapUtils.decodeBitmap(path, 100, 100);
}else{
cursor.close();
return null;
}
}
public static Bitmap[] queryThumbnailsByIds(Activity context, Integer[] thumbIds){
Bitmap[] bitmaps = new Bitmap[thumbIds.length];
for(int i=0; i<bitmaps.length; i++){
bitmaps[i] = BitmapUtils.queryThumbnailById(context, thumbIds[i]);
}
return bitmaps;
}
/**
* 獲取全部
* @param context
* @return
*/
public static List<Bitmap> queryThumbnailList(Activity context){
List<Bitmap> bitmaps = new ArrayList<Bitmap>();
Cursor cursor = BitmapUtils.queryThumbnails(context);
for(int i=0; i<cursor.getCount(); i++){
cursor.moveToPosition(i);
String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
Bitmap b = BitmapUtils.decodeBitmap(path, 100, 100);
bitmaps.add(b);
}
cursor.close();
return bitmaps;
}
public static List<Bitmap> queryThumbnailListByIds(Activity context, int[] thumbIds){
List<Bitmap> bitmaps = new ArrayList<Bitmap>();
for(int i=0; i<thumbIds.length; i++){
Bitmap b = BitmapUtils.queryThumbnailById(context, thumbIds[i]);
bitmaps.add(b);
}
return bitmaps;
}
public static Cursor queryImages(Activity context){
String[] columns = new String[]{
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME
};
return context.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
}
public static Cursor queryImages(Activity context, String selection, String[] selectionArgs){
String[] columns = new String[]{
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME
};
return context.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selection, selectionArgs, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
}
public static Bitmap queryImageById(Activity context, int imageId){
String selection = MediaStore.Images.Media._ID + "=?";
String[] selectionArgs = new String[]{
imageId + ""
};
Cursor cursor = BitmapUtils.queryImages(context, selection, selectionArgs);
if(cursor.moveToFirst()){
String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
cursor.close();
//return BitmapUtils.decodeBitmap(path, 260, 260);
return BitmapUtils.decodeBitmap(path, 220); //看看和上面這種方式的差別,看了,差不多
}else{
cursor.close();
return null;
}
}
/**
* 根據(jù)縮略圖的Id獲取對(duì)應(yīng)的大圖
* @param context
* @param thumbId
* @return
*/
public static Bitmap queryImageByThumbnailId(Activity context, Integer thumbId){
String selection = MediaStore.Images.Thumbnails._ID + " = ?";
String[] selectionArgs = new String[]{
thumbId+""
};
Cursor cursor = BitmapUtils.queryThumbnails(context, selection, selectionArgs);
if(cursor.moveToFirst()){
int imageId = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
cursor.close();
return BitmapUtils.queryImageById(context, imageId);
}else{
cursor.close();
return null;
}
}
}
這樣就實(shí)現(xiàn)了,類(lèi)似百度圖片瀏覽的效果。效果圖如下:


以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android查看網(wǎng)絡(luò)圖片的實(shí)現(xiàn)方法
- Android圖片處理教程之全景查看效果實(shí)現(xiàn)
- Android 簡(jiǎn)單的圖片查看器源碼實(shí)現(xiàn)
- android自定義Camera拍照并查看圖片
- Android 通過(guò)網(wǎng)絡(luò)圖片路徑查看圖片實(shí)例詳解
- Android 網(wǎng)絡(luò)圖片查看器與網(wǎng)頁(yè)源碼查看器
- android網(wǎng)絡(luò)圖片查看器簡(jiǎn)單實(shí)現(xiàn)代碼
- Android 實(shí)現(xiàn)WebView點(diǎn)擊圖片查看大圖列表及圖片保存功能
- Android實(shí)現(xiàn)圖片查看功能
相關(guān)文章
RxJava實(shí)戰(zhàn)之訂閱流基本原理示例解析
這篇文章主要為大家介紹了RxJava實(shí)戰(zhàn)之訂閱流基本原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android判斷手機(jī)是否是小米MIUI系統(tǒng)的方法
這篇文章主要介紹了Android判斷手機(jī)是否是小米MIUI系統(tǒng)的方法的相關(guān)資料,需要的朋友可以參考下2016-02-02
Android中SharedPreference詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了 Android中SharedPreference詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09
微信小程序在安卓的白屏問(wèn)題原因及改進(jìn)講解
今天小編就為大家分享一篇關(guān)于微信小程序在安卓的白屏問(wèn)題原因及改進(jìn)講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02
詳解Android中使用Notification實(shí)現(xiàn)進(jìn)度通知欄(示例三)
這篇文章主要介紹了詳解Android中使用Notification實(shí)現(xiàn)進(jìn)度通知欄(示例三),具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12
Android AutoCompleteTextView控件使用實(shí)例
AutoCompleteTextView這個(gè)控件用于輸入框的自動(dòng)完成提示,非常適合搜索框等。它本質(zhì)上是個(gè)EditText,實(shí)際上它也是從EditText繼承的,使用起來(lái)也十分簡(jiǎn)單2014-04-04
Android實(shí)現(xiàn)漸變啟動(dòng)頁(yè)和帶有指示器的引導(dǎo)頁(yè)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)漸變啟動(dòng)頁(yè)和帶有指示器的引導(dǎo)頁(yè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09
android聊天界面鍵盤(pán)、表情切換絲滑實(shí)現(xiàn)的具體思路
這篇文章主要給大家介紹了關(guān)于android聊天界面鍵盤(pán)、表情切換絲滑實(shí)現(xiàn)的具體思路,具體實(shí)現(xiàn)包括在XML布局中使用FrameLayout和RecyclerView,并在代碼中進(jìn)行相應(yīng)的高度控制和事件處理,需要的朋友可以參考下2024-12-12
android教程viewpager自動(dòng)循環(huán)和手動(dòng)循環(huán)
這篇文章主要介紹了android的viewpager自動(dòng)循環(huán)和手動(dòng)循環(huán)示例,需要的朋友可以參考下2014-02-02

