Android上傳圖片之呼叫系統拍照和從相簿選擇圖片

發表於2016-04-13

前言:

萬丈高樓平底起,萬事起於微末。不知不覺距離上篇博文已近四個月,2015年12月17日下午發了第一篇博文,現在是2016年4月6日。時間間隔長的過分啊,我自己都看不下去了。原因呢?當然是自己的原因,其實是有很多時間來些部落格的,但是這些時間都花在DOTA上了(還是太年輕啊)。請原諒我的過錯…….
一、概述:
現在幾乎應用都會用到上傳圖片的功能,而要上傳圖片,首先得選擇圖片,本文不針對如何上傳圖片到伺服器(每個專案與伺服器互動的方式不同,因此不寫上傳圖片到伺服器相關程式碼),只是對選擇圖片做簡單的介紹,沒有涉及到對圖片的圓角處理與剪裁。本文主要涉及以下幾個簡單的知識點:

  • 簡單的呼叫系統拍照和系統相簿選擇圖片
  • 通過GridView實現動態新增圖片的效果
  • Adapter使用的小技巧
  • Fragment中呼叫系統拍照該怎麼獲取資料(介面回撥)

二、實現:
我們先來看專案目錄:
工程目錄
一個Adapter、兩個Activity,一個Fragment、一個工具類,一目瞭然。有人在這裡有疑問了,為什麼是兩個Activity?不是三個嗎?沒錯,理論上ChooseActivityChooseFragmentActivityBaseActivity加起來是三個,不過在這裡BaseActivity是模擬實際專案抽離Activity中公共的程式碼,不做為檢視,所以我不把BaseActivity算進去。
ChooseActivity是模擬Activity中呼叫系統拍照和系統相簿選擇圖片,ChooseFragmentActivity中放入ChooseFragment模擬Fragment中呼叫系統拍照和系統相簿選擇圖片(在這裡我定死了一個Fragment模擬專案實際情況,實際情況一個Activity中會有多個Fragment),ImageUtils做一些簡單的圖片處理。SelectPicPopupWindow一個簡單的PopupWindow,UploadImageAdapter動態選擇圖片上傳的介面卡。
先來點效果圖吧:


圖中展示的效果:點選預設圖片彈出PopupWindow讓使用者選擇拍照還是從相簿選擇圖片(模擬器中不便使用拍照功能,本人在幾臺手機上試過沒有問題,請到真機上測試),選擇好圖片後已選擇好的圖片可長按刪除,這裡控制了最多選擇6張圖片。

簡單的呼叫系統拍照和系統相簿選擇圖片
我們先來看是怎麼呼叫系統拍照和從相簿選擇圖片的:
申明元件與變數:

彈出PopupWindow:

其中最重要的就是拍照相關的takephoto方法了了,部分機型拍完照後沒有資料返回,只能通過指定拍完照獲得圖片的儲存路徑來解決這個問題了。註釋寫的很詳細,這裡不再多解釋了。但是注意一點指定路徑的時候可能會出現拍完照後無法點確定返回,有的手機甚至會點選後掛掉,這個時候會報不是有效路徑的錯誤。我遇到錯誤是在獲取到的與應用相關聯的路徑後面再建立一個檔案/xxxx,至於為什麼不行,我也不知道原理。

通過GridView實現動態新增圖片的效果
其實你們更關心GridView動態增加item,item刪除等效果:

申明元件和變數:

初始化GridView和Adapter:

GridView的item點選監聽和長按監聽:

對於onActivityResult的回撥如下:

Adapter使用的小技巧
我們可以看到GirdView點選監聽和長按監聽都用到了

判斷語句,為什麼用parent.getItemAtPosition(position) 而不用dataList .get(position)呢?個人認為使用介面卡最好將資料來源隔離出來,即除了在Adapter傳入資料或者Adapter更新資料,其他情況不再使用資料來源,避免資料不同步造成一些問題。我們再來看一下Adapter的程式碼:

在這裡我對getCount()、getItem()方法都做了非空的判斷,個人認為能避免空指標異常就要避免,當然這樣做也是為了在getView中直接使用getItem(position)方法,而不是取用dataList.get(position)獲取當前item的對應的資料,原因在GridView點選和長按事件中有提到過。邏輯比較簡單,不做過多的介紹。

Fragment與Activity之間通過介面傳遞資料
我覺得最重要的就是Fragment與Activity之間怎麼傳遞資料,在這裡我採取了介面回撥來實現資料傳遞。
首先在BaseActivity中定義一個介面:

然後我們來看看是怎麼使用的吧:
因為ChooseFragmentActivity繼承自BaseActivity,所以直接mOnFragmentResult

Fragment中:

而在Fragment中對GridView點選、長按事件操作與Activity中大同小異,主要是Context的獲取。

最關鍵的地方就是(BaseActivity)getActivity()這步操作,這樣能在Fragment中拿到BaseActivity中的方法和屬性。這種操作在很多情景使用會帶來很大的便利。

好了,本片文章就進入尾聲了……

Think great thoughts and you will be great.

上原始碼

相關文章