編輯:Android開發實例
我們知道,進入百度圖片後,輸入一個關鍵字後,首先看到的是很多縮略圖,當我們點擊某張縮略圖時,我們就可以進入到大圖顯示頁面,在
大圖顯示頁面,中包含了一個圖片畫廊,同時當前大圖為剛剛我們點擊的那張圖片。現在我們看看在Android中如何實現類似的效果:
首先,我們需要有一個控件來顯示縮略圖,這裡沒有什麼比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>
對於GridView中每一項是一張縮略圖,我們需要繼承BaseAdapter,實現自己的一個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) {
- // 點擊事件
- showCurrentImage(position);
- }
- };
- private void init(){
- thumbIds = this.getIntent().getIntArrayExtra("thumbIds");
- currentPos = this.getIntent().getIntExtra("currentPos",0);
- //galleryIds = this.getThumbnailIds(currentPos); //當前的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當前可見的顯示之前的3張,後3張緩存起來,其余的釋放掉,這樣是為了放置內存不夠用
- * 之所以前三張後三張,是為了Gallery可以滑動的更加順暢
- */
- private void releaseBitmaps(){
- int start = gallery.getFirstVisiblePosition()-3; //緩存的起始位置
- int end = gallery.getLastVisiblePosition()+3; //緩存的結束位置
- 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();
- }
- }
- }
- /**
- * 獲取當前位置的前三個Id和後三個Id
- * @param position
- * @return
- */
- private Integer[] getThumbnailIds(int position){
- Integer[] ids = new Integer[]{0,0,0,0,0,0,0};
- int currPos = 0;
- //關於這裡的處理,比較復雜
- for(int i=3; i>0; i--){
- if(position - i >= 0){
- currPos = 3-i;
- ids[currPos] = thumbIds[position-i];
- }
- }
- ids[++currPos] = thumbIds[position]; //當前Id
- //currGallerySelection = currPos;
- //這樣右邊剩下的位置數就是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中通過查詢MediaStore的多媒體圖片庫來查詢所有的圖片的縮略圖,縮略圖所在的位置是:
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) {
- //點擊某張縮略圖時,轉到圖片顯示界面
- Intent intent = new Intent();
- intent.setClass(MainActivity.this, GalleryActivity.class);
- intent.putExtra("thumbIds", thumbIds);
- intent.putExtra("currentPos", position);
- startActivity(intent);
- }
- };
- }
注意到,我們記錄了,所有縮略圖對應的id號,和當前的用戶選擇的位置,然後通過Intent傳遞到第二個展示界面。第二個界面的布局文件如下:我們用了一個Gallery和一個ImageButton來實現
- <?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>
然後,對應的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) {
- // 點擊事件
- showCurrentImage(position);
- }
- };
- private void init(){
- thumbIds = this.getIntent().getIntArrayExtra("thumbIds");
- currentPos = this.getIntent().getIntExtra("currentPos",0);
- //galleryIds = this.getThumbnailIds(currentPos); //當前的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中某一項時,觸發onItemClick事件,在其中,我們通過根據該縮略圖對應的Image_ID來從MediaStore.Images.Media中查詢該縮略圖對應的大圖。並在ImageButton中顯示。
這裡當圖片很多時,可能會出現內存溢出,為了避免這種情況,可以更加Gallery的特點,使用緩存。保存當前可見的縮略圖的前三個到後三個。其余的全部recycle。當用戶點擊Gallery的時候,在判斷當前的位置,如果大於或小於某個值時,則重新更新緩存。這樣保證內存中的縮略圖的個數總是6+Gallery.getLastVisiblePosition-Gallery.getFirstVisiblePosition個。其實這就是浮動緩存窗口,一個固定大小窗口在整個坐標(全部縮略圖)上游動。這裡沒有實現,以後待續。
同時,你可能已經注意到,程序中使用到了一個BitmapUtils類,這個類是封裝了一系列對查詢圖片,並將其解析為Bitmap的類。
代碼如下:
- 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);
- //如果超出指定大小,則縮小相應的比例
- 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);
- }
- /**
- * 采用復雜計算來決定縮放
- * @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;
- }
- }
- /**
- * 根據縮略圖的Id獲取對應的大圖
- * @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;
- }
- }
- }
這樣就實現了,類似百度圖片浏覽的效果。效果圖如下:
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
Service是在一段不定的時間運行在後台,不和用戶交互應用組件。每個Service必須在manifest中 通過<service>來聲明。可以通過c
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放