feat: 增加拍摄界面

This commit is contained in:
2022-12-28 11:03:29 +08:00
parent acbc7c957b
commit 2337dfd8dd
13 changed files with 269 additions and 5 deletions

View File

@@ -82,4 +82,15 @@ dependencies {
implementation 'com.github.Gredicer:datetimepicker:V1.0.0' implementation 'com.github.Gredicer:datetimepicker:V1.0.0'
implementation 'com.google.code.gson:gson:2.10' implementation 'com.google.code.gson:gson:2.10'
implementation 'com.yanzhenjie.recyclerview:x:1.3.2' implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
// 动态权限申请 https://github.com/permissions-dispatcher/PermissionsDispatcher
implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.9.2"
annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.9.2"
// 相机库 https://natario1.github.io/CameraView/about/getting-started
implementation("com.otaliastudios:cameraview:2.7.2")
// 图片压缩算法 https://github.com/Curzibn/Luban
implementation 'top.zibin:Luban:1.1.8'
// Android工具类库 https://github.com/l123456789jy/Lazy
implementation 'com.github.lazylibrary:lazylibrary:1.0.2'
} }

View File

@@ -1,6 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<!--拍照-->
<uses-permission android:name="android.permission.CAMERA" android:required="false"/>
<!--网络请求-->
<uses-permission android:name="android.permission.INTERNET" android:required="false"/>
<!--录音-->
<uses-permission android:name="android.permission.RECORD_AUDIO" android:required="false"/>
<!--读写文件-->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application <application
android:allowBackup="true" android:allowBackup="true"

View File

@@ -1,18 +1,24 @@
package com.navinfo.volvo package com.navinfo.volvo
import android.Manifest
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.widget.Toast
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.navinfo.volvo.R import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.ActivityMainBinding import com.navinfo.volvo.databinding.ActivityMainBinding
import permissions.dispatcher.*
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
@NeedsPermission(Manifest.permission.CAMERA)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -32,4 +38,29 @@ class MainActivity : AppCompatActivity() {
// setupActionBarWithNavController(navController, appBarConfiguration) // setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController) navView.setupWithNavController(navController)
} }
@OnShowRationale(Manifest.permission.CAMERA)
fun showRationaleForCamera(request: PermissionRequest) {
// showRationaleDialog(R.string.permission_camera_rationale, request)
// Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
MaterialAlertDialogBuilder(this)
.setTitle("提示")
.setMessage("当前操作需要您授权读写SD卡权限")
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
// 在SD卡创建项目目录
})
.show()
}
@OnPermissionDenied(Manifest.permission.CAMERA)
fun onCameraDenied() {
Toast.makeText(this, "当前操作需要您授权读写SD卡权限", Toast.LENGTH_SHORT).show()
}
@OnNeverAskAgain(Manifest.permission.CAMERA)
fun onCameraNeverAskAgain() {
Toast.makeText(this, "您已永久拒绝授权读写SD卡权限", Toast.LENGTH_SHORT).show()
}
} }

View File

@@ -0,0 +1,87 @@
package com.navinfo.volvo.ui.camera
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.navinfo.volvo.databinding.FragmentCameraBinding
import com.otaliastudios.cameraview.CameraListener
import com.otaliastudios.cameraview.CameraView
import com.otaliastudios.cameraview.PictureResult
import top.zibin.luban.Luban
import top.zibin.luban.OnCompressListener
import java.io.File
import java.util.*
class CameraFragment : Fragment() {
private var _binding: FragmentCameraBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private val cameraLifeCycleObserver: CameraLifeCycleObserver by lazy {
CameraLifeCycleObserver()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
lifecycle.addObserver(cameraLifeCycleObserver)
val cameraViewModel =
ViewModelProvider(this).get(CameraViewModel::class.java)
_binding = FragmentCameraBinding.inflate(inflater, container, false)
val root: View = binding.root
val cameraView: CameraView = binding.camera
cameraView.setLifecycleOwner(this)
cameraView.addCameraListener(object:CameraListener() { // 添加拍照回调
override fun onPictureTaken(result: PictureResult) {
super.onPictureTaken(result)
result.toFile()
// 压缩图片文件
Luban.with(context)
.load<Any>(photos)
.ignoreBy(100)
.setTargetDir(getPath())
.filter { path ->
!(TextUtils.isEmpty(path) || path.lowercase(Locale.getDefault())
.endsWith(".gif"))
}
.setCompressListener(object : OnCompressListener {
override fun onStart() {
// TODO 压缩开始前调用,可以在方法内启动 loading UI
}
override fun onSuccess(file: File?) {
// TODO 压缩成功后调用,返回压缩后的图片文件
}
override fun onError(e: Throwable) {
// TODO 当压缩过程出现问题时调用
}
}).launch()
}
})
// 点击拍照
binding.imgStartCamera.setOnClickListener {
cameraView.takePicture()
}
return root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
lifecycle.removeObserver(cameraLifeCycleObserver)
}
}

View File

@@ -0,0 +1,31 @@
package com.navinfo.volvo.ui.camera
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
class CameraLifeCycleObserver: DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
}
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
}
}

View File

@@ -0,0 +1,13 @@
package com.navinfo.volvo.ui.camera
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class CameraViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is dashboard Fragment"
}
val text: LiveData<String> = _text
}

View File

@@ -1,15 +1,21 @@
package com.navinfo.volvo.ui.message package com.navinfo.volvo.ui.message
import android.Manifest
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.gredicer.datetimepicker.DateTimePickerFragment import com.gredicer.datetimepicker.DateTimePickerFragment
import com.navinfo.volvo.databinding.FragmentObtainMessageBinding import com.navinfo.volvo.databinding.FragmentObtainMessageBinding
import com.navinfo.volvo.ui.markRequiredInRed import com.navinfo.volvo.ui.markRequiredInRed
import permissions.dispatcher.*
import java.util.*
class ObtainMessageFragment: Fragment() { class ObtainMessageFragment: Fragment() {
private var _binding: FragmentObtainMessageBinding? = null private var _binding: FragmentObtainMessageBinding? = null
@@ -59,10 +65,43 @@ class ObtainMessageFragment: Fragment() {
} }
// 点击按钮选择拍照 // 点击按钮选择拍照
binding.btnStartCamera.setOnClickListener {
// 启动相机
startCamera()
}
} }
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null
} }
@NeedsPermission(Manifest.permission.CAMERA)
fun startCamera() {
}
@OnShowRationale(Manifest.permission.CAMERA)
fun showRationaleForCamera(request: PermissionRequest) {
// showRationaleDialog(R.string.permission_camera_rationale, request)
// Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
MaterialAlertDialogBuilder(context!!)
.setTitle("提示")
.setMessage("当前操作需要您授权相机权限!")
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
startCamera()
dialogInterface.dismiss()
})
.show()
}
@OnPermissionDenied(Manifest.permission.CAMERA)
fun onCameraDenied() {
Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
}
@OnNeverAskAgain(Manifest.permission.CAMERA)
fun onCameraNeverAskAgain() {
Toast.makeText(context, "您已永久拒绝授权相机权限!", Toast.LENGTH_SHORT).show()
}
} }

View File

@@ -0,0 +1,6 @@
<vector android:height="64dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path android:fillColor="@android:color/white" android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.otaliastudios.cameraview.CameraView
android:id="@+id/camera"
android:keepScreenOn="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/img_start_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:shapeAppearance="@style/CircleStyle"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/ic_baseline_camera_alt_24"></com.google.android.material.imageview.ShapeableImageView>
</RelativeLayout>

View File

@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="com.navinfo.volvo.ui.dashboard.DashboardFragment"> tools:context="com.navinfo.volvo.ui.dashboard.CameraFragment">
<TextView <TextView
android:id="@+id/text_dashboard" android:id="@+id/text_dashboard"

View File

@@ -82,6 +82,7 @@
android:text="上传图片:"></TextView> android:text="上传图片:"></TextView>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_start_camera"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.ElevatedButton" style="@style/Widget.Material3.Button.ElevatedButton"
@@ -92,6 +93,7 @@
android:layout_width="@dimen/default_widget_padding" android:layout_width="@dimen/default_widget_padding"
android:layout_height="wrap_content"></Space> android:layout_height="wrap_content"></Space>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_start_photo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.ElevatedButton" style="@style/Widget.Material3.Button.ElevatedButton"
@@ -183,8 +185,7 @@
android:id="@+id/edt_send_from" android:id="@+id/edt_send_from"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/selector_bg_4_round_corner" android:background="@drawable/selector_bg_4_round_corner"></androidx.appcompat.widget.AppCompatEditText>
tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck"></androidx.appcompat.widget.AppCompatEditText>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@@ -209,8 +210,7 @@
android:id="@+id/edt_send_to" android:id="@+id/edt_send_to"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/selector_bg_4_round_corner" android:background="@drawable/selector_bg_4_round_corner"></androidx.appcompat.widget.AppCompatEditText>
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck"></androidx.appcompat.widget.AppCompatEditText>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout

View File

@@ -33,4 +33,13 @@
android:name="com.navinfo.volvo.ui.message.ObtainMessageFragment" android:name="com.navinfo.volvo.ui.message.ObtainMessageFragment"
android:label="问候编辑" android:label="问候编辑"
tools:layout="@layout/fragment_obtain_message" /> tools:layout="@layout/fragment_obtain_message" />
<fragment
android:id="@+id/navigation_camera"
android:name="com.navinfo.volvo.ui.camera.CameraFragment"
android:label="@string/title_dashboard"
tools:layout="@layout/fragment_camera" />
<action android:id="@+id/nav_2_camera"
app:destination="@id/nav_2_camera"></action>
</navigation> </navigation>

View File

@@ -3,4 +3,10 @@
<style name="default_line"> <style name="default_line">
<item name="android:padding">@dimen/default_widget_padding</item> <item name="android:padding">@dimen/default_widget_padding</item>
</style> </style>
<!--ShapeableImageView 圆 -->
<style name="CircleStyle">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
</resources> </resources>