feat: 增加拍摄界面

This commit is contained in:
xiaoyan 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.google.code.gson:gson:2.10'
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"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
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
android:allowBackup="true"

View File

@ -1,18 +1,24 @@
package com.navinfo.volvo
import android.Manifest
import android.content.DialogInterface
import android.os.Bundle
import android.widget.Toast
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.ActivityMainBinding
import permissions.dispatcher.*
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
@NeedsPermission(Manifest.permission.CAMERA)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -32,4 +38,29 @@ class MainActivity : AppCompatActivity() {
// setupActionBarWithNavController(navController, appBarConfiguration)
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
import android.Manifest
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.gredicer.datetimepicker.DateTimePickerFragment
import com.navinfo.volvo.databinding.FragmentObtainMessageBinding
import com.navinfo.volvo.ui.markRequiredInRed
import permissions.dispatcher.*
import java.util.*
class ObtainMessageFragment: Fragment() {
private var _binding: FragmentObtainMessageBinding? = null
@ -59,10 +65,43 @@ class ObtainMessageFragment: Fragment() {
}
// 点击按钮选择拍照
binding.btnStartCamera.setOnClickListener {
// 启动相机
startCamera()
}
}
override fun onDestroyView() {
super.onDestroyView()
_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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.navinfo.volvo.ui.dashboard.DashboardFragment">
tools:context="com.navinfo.volvo.ui.dashboard.CameraFragment">
<TextView
android:id="@+id/text_dashboard"

View File

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

View File

@ -33,4 +33,13 @@
android:name="com.navinfo.volvo.ui.message.ObtainMessageFragment"
android:label="问候编辑"
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>

View File

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