這一次想了解讀取 Camera / Album 的部分,還有 ImageView 相關的設定。
- 提供兩個按鈕,一個從相冊取圖片、一個從相機拍照取圖片。
- 將取到的圖片顯示在主畫面的 ImageView 上。
- ImageView 需要設定 ScaleType
Layout
自定義圓角按鈕,通過在 /res/drawable 下,建立一個檔案設定圓角樣式 shape.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <!-- 按鈕背景顏色 --> <solid android:color="@color/colorPrimary" /> <!-- 圓角 --> <corners android:radius="15dip" /> <!-- 文字 padding --> <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" /> </shape> |
通過對 <button> 設定 background 來繼承圓角樣式
1 |
android:background="@drawable/shape" |
ScaleType
和 iOS 的 UIImageView 一樣,圖片可以設定填充模式,控制圖片是否完整顯示,或者是否允許變形。
- ImageView.ScaleType.CENTER
- ImageView.ScaleType.CENTER_CROP
- ImageView.ScaleType.CENTER_INSIDE
- ImageView.ScaleType.FIT_START
- ImageView.ScaleType.FIT_CENTER
- ImageView.ScaleType.FIT_END
- ImageView.ScaleType.FIT_XY
Resources
- /res/mipmap-* 這類資料夾裡面,負責放 icon
- /res/drawable 當中放入其它素材。
資源的命名有規範,比如說不能用「-」而是英文大小寫、數字、底線。
Constraint Layout
這裡有點像 iOS 開發過程通過 Storyboard 做的 AutoLayout,只是多了些蠻有趣的設定。
在 Android Studio 中,將 xml 對應的 Design 標籤下,可以看到可視化的佈局情況。
每一個元件的四邊都會有圓形的點,可以通過拖拉圓點來設定相對其他元件的距離。
而右側可以看到這樣的設定,中間部分的線條像彈簧一樣,其實就是如果設定好了邊界距離,剩下的部分就會平均分配。
除非去設定了左邊或下面的滑桿,目前就是上圖顯示的 50/50,也就是平均分配。
Intent
有點像 iOS 的 Segue / URL Scheme,我們可以將值傳送到別的頁面/App上,而在 Android 上甚至可以跟系統說,我需要用相機,然後就跳出一個選項,讓我們選要用哪一個 App 的相機,然後再取得照片回來用。
Permission
使用其他 App 獲取圖片
在 iOS 系統中,我們通常要用到的 Album/Camera,都會是由系統提供的(原生的),而在使用前都會需向使用者請求同意。
而 Android 不太一樣的地方是,我們可以通過 Intent 方法去打開別的相機、相冊 App,這時候會跳到別的 App 上,
在拿到圖片以後可以返回到原本的 App 上做接收,在這種情況下,只需要相機、相冊 App 有允許權限就可以了。
一個請求使用 Camera 的例子,
這裡的 ACTION_CAMERA_REQUEST_CODE,是自己定義的一個數字,用來在後面接受請求結果。
1 2 |
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) startActivityForResult(intent, MainActivity.ACTION_CAMERA_REQUEST_CODE) |
接收 intent 結果的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) println("收到 result code $requestCode") when(requestCode) { ACTION_CAMERA_REQUEST_CODE -> { if(resultCode == Activity.RESULT_OK && data != null){ displayImage(data.extras.get("data") as Bitmap) } } ACTION_ALBUM_REQUEST_CODE -> { if(resultCode == Activity.RESULT_OK && data != null){ val resolver = this.contentResolver val bitmap = MediaStore.Images.Media.getBitmap(resolver, data?.data) displayImage(bitmap) } } else -> { println("no handler onActivityReenter") } } } |
原生的 Album/Camera 使用權限
類似於 iOS 中的 info.plist,Android 在 main folder 底下有個 AndroidManifest.xml 。
我們可以在這裡定義想要取得的權限,比如相機的使用。
1 |
<uses-permission android:name="android.permission.CAMERA"/> |
檢查使用權限
通過 Contextcompat 類提供的方法來進行檢查,比如檢查 Camera 的使用權限
1 |
if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){} |
筆記
- 動手做:嘗試直接使用原生的 Camera / Album
參考
- 官方文檔 – MediaStore
- 官方文檔 – Intent
- 可以到 Github 上看對應的 Source Code
請問 在android 8.1中
val bitmap = MediaStore.Images.Media.getBitmap(resolver, data?.data)
這行為甚麼會出錯閃退??
用android 5.0的舊手機正常運行,但8.1卻會閃退…??
在android 8.1中
displayImage(data.extras.get(“data”) as Bitmap)
是可以正常執行的 但…取得的影像畫質很低
除了用MediaStore.Images.Media.getBitmap(resolver, data?.data)之外,還有甚麼方法可以取得拍照的原畫質??