iT邦幫忙

DAY 28
2

以「寶寶聯絡簿」為例,適合 Android 初學者的學習筆記系列 第 28

寶寶生活記錄 App (Day28 從內建的相片集程式中選取照片)

作天已將「寶寶列表 (BabyListActivity)」所有實作細節都說明完畢了,今天我們回到「新增/編輯寶寶」尚未介紹的部分,今天先介紹「寶寶大頭照」的處理,程式讓使用者從兩種管道選取照片:(1) 從內建的相片集程式 (或其它相片管理軟體) 中選取照片;(2) 透過相機拍攝來獲得照片。關於透過相機拍攝來獲得照片的方法可參考筆者的書籍 [1],這篇文章只專注介紹從內建的相片集程式中選取照片。相關的程式碼片段如下所示:

    private void showPhotoSourceDialog() {

        LayoutInflater inflater = LayoutInflater.from(this);
        View view = inflater.inflate(R.layout.dialog_headshotsource, null);

        ImageView iv_photo = (ImageView)view.findViewById(R.id.iv_photo);
        iv_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ad.dismiss();
                Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
                photoPickerIntent.setType("image/*");
                startActivityForResult(photoPickerIntent, PHOTO_PICKER);
            }
        });
        ImageView iv_camera = (ImageView)view.findViewById(R.id.iv_camera);

        AlertDialog.Builder adb = new AlertDialog.Builder(this);
        ad = adb.create();
        ad.setView(view);
        ad.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == PHOTO_PICKER) {
            if (resultCode == RESULT_OK) {
                Uri uri = data.getData();
                String picturepath = getPathFromUri(uri);
                Log.d("LINCYU", "Picture Path: " + picturepath);
                baby.headshot = picturepath;
                Bitmap bitmap = Util.decodeFile(picturepath, 256);
                iv_headshot.setImageBitmap(bitmap);
            }
        }
    }

    private String getPathFromUri(Uri uri) {

        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, filePathColumn, null, null, null);
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();
        return picturePath;
    }

昨天已經介紹過 AlertDialog.Builder 的範例,然而今天有點不太一樣,我們不是直接呼叫 AlertDialog.Builder 物件的方法來設定對話框,而是呼叫 AlertDialog.Builder 物件的 create 方法來產生一個 AlertDialog 物件,再呼叫 AlertDialog 物件的方法來設定對話框,為什麼要這樣做呢?這是因為昨天的對話框有兩個按鈕(「取消」和「刪除資料」),這兩個按鈕按下後,對話框就會消失,今天的對話框沒有這樣的按鈕,我們必須呼叫 AlertDialog 物件的 dismiss 讓對話框消失 (AlertDialog.Builder 物件沒有 dismiss 方法可呼叫)。

這個對話框的主體有兩個 ImageView,按下 iv_photo 後可讓使用者從內建的相片集程式中選取照片,做法是使用先前介紹過的 Implicit Intent,現在來討論 onClick 裡面的內容,首先呼叫 AlertDialog 物件的 dismiss 將對話框關掉,接著設定 Implicit Intent,ACTION 設為 ACTION_PICK,接著利用 setType 設定想選取的是「圖 (Image)」,setType 的參數為 MIME Type [2],接著呼叫 startActivityForResult 來啟動內建相片集程式。

先前我們已經學過利用 startActivity 啟動一個新的 Activity,並且透過 Intent 攜帶資料給新的 Activity,那麼新的Activity若想將資料回傳該怎麼達成?我們要使用 startActivityForResult 取代startActivity,當您希望被呼叫的Activity能在結束時回傳資料的話,就應該使用startActivityForResult,這個Method需要兩個參數,第一個參數是Intent,已經不需再多說,第二個參數是「請求碼」,這個請求碼是用來分辨是哪個 Activity 回傳的 (詳細說明可參考筆者書籍 [1])。

我們還必須覆寫 onActivityResult 處理新的 Activity 所回傳的資料 (在我們的例子中,這個新的 Activity 為內建相片集程式),onActivityResult會傳入三個參數,第一個參數是請求碼,我們可藉著請求碼來判斷資料是哪一個被呼叫的 Activity 所回傳的 (也就是 startActivityForResult 的第二個參數),第二個參數是結果碼,通常若執行正常會回傳 RESULT_OK,第三個參數是Intent,回傳的資料可從Intent中取得。在我們的範例中,我們先取出圖檔的 URI,並把這個 URI 轉換成 SD 卡上的路徑 (記得必須於 AndroidManifest.xml 宣告相關的 Permissions),最後讀取此圖黨並轉換成 Bitmap 物件後顯示於 ImageView 上,把檔案轉成 Bitmap 物件的方法可參考 [3] 和 [4]。

最後要提醒的是,viewInitialization 中關於 iv_headshot 的程式碼也必須跟著改寫:

        iv_headshot = (ImageView)findViewById(R.id.iv_headshot);
        Bitmap bitmap = Util.decodeFile(baby.headshot, 256);
        if (bitmap != null) {
            iv_headshot.setImageBitmap(bitmap);
        }
        iv_headshot.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showPhotoSourceDialog();
            }
        });

今天的文章主要介紹從內建的相片集程式中選取照片。由於我們自己的程式會從 SD 卡上讀取照片,Permission 的宣告會於明天做說明,而更多 startActivityForResult 的範例以及如何透過相機拍攝來獲得照片,請讀者自行參考筆者的書籍 [1]。

最後附上程式的執行結果畫面:

參考資料

[1] 林致宇, Android程式設計入門與應用(附範例光碟), 全華出版社, ISBN: 9789572194126, http://www.opentech.com.tw/search/bookinfo.asp?isbn=9789572194126&companyID=04383129

[2] Internet media type - Wikipedia, the free encyclopedia, http://en.wikipedia.org/wiki/Internet\_media\_type

[3] android - Resizing bitmap from InputStream - Stack Overflow, http://stackoverflow.com/questions/12841482/resizing-bitmap-from-inputstream

[4] Android: How to load image into Bitmap - Stack Overflow, http://stackoverflow.com/questions/4887297/android-how-to-load-image-into-bitmap


上一篇
寶寶生活記錄 App (Day27 寶寶列表的其它實作細節)
下一篇
寶寶生活記錄 App (Day29 「編輯寶寶」的其它實作細節)
系列文
以「寶寶聯絡簿」為例,適合 Android 初學者的學習筆記30

尚未有邦友留言

立即登入留言