2014年1月24日

Android 使用gridview 顯示相簿中的縮圖

Android 使用gridview 顯示相簿中的縮圖

這次我想做一個相簿功能,先把手機裝置裡的照片縮圖讀出排列,點擊縮圖可以放大顯示圖片。

main_activity.xml

< RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android"
    xmlns:tools= "http://schemas.android.com/tools"
    android:layout_width= "fill_parent"
    android:layout_height= "fill_parent"
    tools:context= ".MainActivity" >

    <GridView
        android:id= "@+id/gridView1"
        android:layout_width= "fill_parent"
        android:layout_height= "fill_parent"
        android:gravity= "center"
        android:horizontalSpacing= "1dp"
        android:numColumns= "4"
        android:verticalSpacing= "1dp"
        >
    </GridView >

    <ImageView
        android:id= "@+id/imageView1"
        android:layout_width= "fill_parent"
        android:layout_height= "fill_parent"
        android:gravity= "center"
        android:visibility= "gone"
        android:background= "#00000000"
         />

</ RelativeLayout>

在 main_activty 裡配置了一個gridview 和 一個imageView,gridview 是讓我們放縮圖用的,imageview是當我們點擊小圖顯示放大圖片用的。gridview 裡有幾個屬性是我們需要注意的:android:numColumns= "4" 這意指每一行我們要放四張縮圖,android:horizontalSpacing= "1dp" 水平間隔是 1dp,android:verticalSpacing= "1dp" 垂直間格是1dp。

再來我加了一個 item_photo.xml ,是拿來放一張一張的縮圖用。

<? xml version= "1.0" encoding= "utf-8" ?>
< RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android"
    android:id= "@+id/rl_item_photo"
    android:layout_width= "wrap_content"
    android:layout_height= "wrap_content"
    >

    <ImageView
        android:id= "@+id/imageView1"
        android:layout_width= "fill_parent"
        android:layout_height= "fill_parent" />

</ RelativeLayout>

那為什麼要特別要加一個 item_photo.xml 來放縮圖呢? 這是我們方便可以為縮圖的顯示做客製加以變化。

MainActivity.java

package com.example.gridview;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

     private GridView gridView;
     private ImageView imageView;
     private List<String> thumbs;  //存放縮圖的id
     private List<String> imagePaths;  //存放圖片的路徑
     private ImageAdapter imageAdapter;  //用來顯示縮圖

     @Override
     protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);

          gridView = (GridView) findViewById(R.id.gridView1);
          imageView = (ImageView) findViewById(R.id.imageView1);

          ContentResolver cr = getContentResolver();
          String[] projection = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };

          //查詢SD卡的圖片
          Cursor cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    projection, null, null, null);

          thumbs = new ArrayList<String>();
          imagePaths = new ArrayList<String>();

          for (int i = 0; i < cursor.getCount(); i++) {

               cursor.moveToPosition(i);
               int id = cursor.getInt(cursor
                         .getColumnIndex(MediaStore.Images.Media._ID));// ID
               thumbs.add(id + "");

               String filepath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));//抓路徑

               imagePaths.add(filepath);
          }

          cursor.close();

          imageAdapter = new ImageAdapter(MainActivity.this, thumbs);
          gridView.setAdapter(imageAdapter);
          imageAdapter.notifyDataSetChanged();


          imageView.setOnClickListener(new OnClickListener() {

               @Override
               public void onClick(View v) {
                    // TODO Auto-generated method stub
                    imageView.setVisibility(View.GONE);
                    gridView.setVisibility(View.VISIBLE);
               }

          });
          imageView.setVisibility(View.GONE);

     }

     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main, menu);
          return true;
     }

     public void setImageView(int position){
          Bitmap bm = BitmapFactory.decodeFile(imagePaths.get(position));
          imageView.setImageBitmap(bm);
          imageView.setVisibility(View.VISIBLE);
          gridView.setVisibility(View.GONE);
     }
}

以上我們在 onCreate() 時,去讀取SD卡上的圖片,取出圖片的ID放入 thumbs, 取出圖片的路徑放入 imagePaths,透過ImageAdapter 將thumbs的圖片ID去取縮圖。

imageView 加入click event 以切換 gridview 及 imageview 的顯示。

setImageView() 取出路徑轉成Bitmap放入ImageView 顯示處理。

package com.example.gridview;

import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class ImageAdapter extends BaseAdapter {

    private ViewGroup layout;
    private Context context;
    private List coll;

    public ImageAdapter(Context context, List coll) {

        super();
        this.context = context;
        this.coll = coll;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowview = inflater.inflate(R.layout.item_photo, parent, false);
        layout = (ViewGroup) rowview.findViewById(R.id.rl_item_photo);
        ImageView imageView = (ImageView) rowview.findViewById(R.id.imageView1);

        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        float dd = dm.density;
        float px = 25 * dd;
        float screenWidth = dm.widthPixels;
        int newWidth = (int) (screenWidth - px) / 4; // 一行顯示四個縮圖

        layout.setLayoutParams(new GridView.LayoutParams(newWidth, newWidth));
        imageView.setId(position);
        // Bitmap bm = BitmapFactory.decodeFile((String)coll.get(position));
        // Bitmap newBit = Bitmap.createScaledBitmap(bm, newWidth, newWidth,
        // true);

        Bitmap bm = MediaStore.Images.Thumbnails.getThumbnail(context
                .getApplicationContext().getContentResolver(), Long
                .parseLong((String) coll.get(position)),
                MediaStore.Images.Thumbnails.MICRO_KIND, null);

        imageView.setImageBitmap(bm);
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);

        //點擊照片
        imageView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(context, "index:" + position, Toast.LENGTH_SHORT)
                        .show();

                ((MainActivity)context).setImageView(position);
            }

        });

        return rowview;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return coll.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return coll.get(arg0);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

}

layout.setLayoutParams(new GridView.LayoutParams(newWidth, newWidth)); 為了顯示正方形的縮圖形狀,先算出適合的寬高。

DisplayMetrics dm = context.getResources().getDisplayMetrics();
float dd = dm.density;  //取出密度
float px = 25 * dd;  //像素 = dp * 密度
float screenWidth = dm.widthPixels;  //取出螢幕寬度

這個公式用來計算一張圖片在不同裝置下不同解析度時應該縮放顯示的像素。

imageView.setScaleType(ImageView.ScaleType.FIT_XY); // 把圖片不按比例 擴大/縮小到View的大小顯示

以下 ImageView.ScaleType / android:scaleType值說明:

CENTER /center 按圖片的原來size居中顯示,當圖片長/寬超過View的長/寬,則截 取圖片的居中部分顯示

CENTER_CROP / centerCrop 按比例擴大圖片的size居中顯示,使得圖片長 (寬)等於或大於View的長(寬)

CENTER_INSIDE / centerInside 將圖片的內容完整居中顯示,通過按比例縮小 或原來的size使得圖片長/寬等於或小於View的長/寬

FIT_CENTER / fitCenter 把圖片按比例擴大/縮小到View的寬度,居中顯示

FIT_END / fitEnd 把 圖片按比例擴大/縮小到View的寬度,顯示在View的下部分位置

FIT_START / fitStart 把 圖片按比例擴大/縮小到View的寬度,顯示在View的上部分位置

FIT_XY / fitXY 把圖片 不按比例 擴大/縮小到View的大小顯示

MATRIX / matrix 用矩陣來繪製

//點擊照片
imageView.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        Toast.makeText(context, "index:" + position, Toast.LENGTH_SHORT).show();
        ((MainActivity)context).setImageView(position);
    }
});

點擊縮圖時,去呼叫MainActivity的 setImageView(position) method 顯示圖片。