1、增加照片记录功能2、增加便签语音及照片功能3、修复便签保存后绘制画布没有消失问题
This commit is contained in:
parent
b906ec83d2
commit
3fc43af5bf
@ -6,6 +6,8 @@ import android.graphics.Bitmap
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -90,6 +92,18 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.evaluationDescription.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
viewModel.description = s.toString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
binding.evaluationVoiceRecyclerview.adapter = adapter
|
binding.evaluationVoiceRecyclerview.adapter = adapter
|
||||||
|
|
||||||
//返回按钮点击
|
//返回按钮点击
|
||||||
@ -128,8 +142,6 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
|
|||||||
* 照片view
|
* 照片view
|
||||||
*/
|
*/
|
||||||
binding.evaluationPictureViewpager.adapter = pictureAdapter
|
binding.evaluationPictureViewpager.adapter = pictureAdapter
|
||||||
val list = mutableListOf("1", "2", "3")
|
|
||||||
pictureAdapter.refreshData(list)
|
|
||||||
|
|
||||||
//照片左右选择键点击监听
|
//照片左右选择键点击监听
|
||||||
binding.evaluationPictureLeft.setOnClickListener(this)
|
binding.evaluationPictureLeft.setOnClickListener(this)
|
||||||
@ -205,6 +217,13 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
|
|||||||
binding.evaluationDescription.setText(it)
|
binding.evaluationDescription.setText(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 照片view
|
||||||
|
*/
|
||||||
|
viewModel.liveDataPictureList.observe(viewLifecycleOwner){
|
||||||
|
pictureAdapter.refreshData(it)
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.listDataChatMsgEntityList.observe(viewLifecycleOwner) {
|
viewModel.listDataChatMsgEntityList.observe(viewLifecycleOwner) {
|
||||||
adapter.refreshData(it)
|
adapter.refreshData(it)
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,8 @@ class EvaluationResultViewModel @Inject constructor(
|
|||||||
|
|
||||||
var classCodeTemp: String = ""
|
var classCodeTemp: String = ""
|
||||||
|
|
||||||
|
var description = ""
|
||||||
|
|
||||||
init {
|
init {
|
||||||
mapController.mMapView.addOnNIMapClickListener(TAG, object : OnGeoPointClickListener {
|
mapController.mMapView.addOnNIMapClickListener(TAG, object : OnGeoPointClickListener {
|
||||||
override fun onMapClick(tag: String, point: GeoPoint, other: String) {
|
override fun onMapClick(tag: String, point: GeoPoint, other: String) {
|
||||||
@ -457,7 +459,7 @@ class EvaluationResultViewModel @Inject constructor(
|
|||||||
liveDataToastMessage.postValue("没有绑定到任何link,请选择")
|
liveDataToastMessage.postValue("没有绑定到任何link,请选择")
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
if (liveDataQsRecordBean.value!!.classCode == DataCodeEnum.OMDB_LANEINFO.code)
|
if (liveDataQsRecordBean.value!!.classCode == DataCodeEnum.OMDB_LANEINFO.code){
|
||||||
try {
|
try {
|
||||||
val jsonObject: JSONObject = if (liveDataQsRecordBean.value!!.remarks != "") {
|
val jsonObject: JSONObject = if (liveDataQsRecordBean.value!!.remarks != "") {
|
||||||
JSONObject(liveDataQsRecordBean.value!!.remarks)
|
JSONObject(liveDataQsRecordBean.value!!.remarks)
|
||||||
@ -488,11 +490,16 @@ class EvaluationResultViewModel @Inject constructor(
|
|||||||
jsonObject.put("now", jsonOriginalArray)
|
jsonObject.put("now", jsonOriginalArray)
|
||||||
}
|
}
|
||||||
liveDataQsRecordBean.value!!.remarks = jsonObject.toString()
|
liveDataQsRecordBean.value!!.remarks = jsonObject.toString()
|
||||||
|
SignUtil.getLineInfoIcons(renderEntity!!)
|
||||||
|
Log.e("jingo", "车信json ${liveDataQsRecordBean.value!!.remarks}")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
liveDataQsRecordBean.value!!.description = description
|
||||||
|
liveDataQsRecordBean.value!!.remarks = ""
|
||||||
|
}
|
||||||
|
|
||||||
Log.e("jingo", "车信json ${liveDataQsRecordBean.value!!.remarks}")
|
|
||||||
val realm = realmOperateHelper.getRealmDefaultInstance()
|
val realm = realmOperateHelper.getRealmDefaultInstance()
|
||||||
liveDataQsRecordBean.value!!.taskId = liveDataTaskBean.value!!.id
|
liveDataQsRecordBean.value!!.taskId = liveDataTaskBean.value!!.id
|
||||||
liveDataQsRecordBean.value!!.checkTime = DateTimeUtil.getDataTime()
|
liveDataQsRecordBean.value!!.checkTime = DateTimeUtil.getDataTime()
|
||||||
@ -582,6 +589,8 @@ class EvaluationResultViewModel @Inject constructor(
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
@ -614,6 +623,8 @@ class EvaluationResultViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
liveDataQsRecordBean.value?.attachmentBeanList = it.attachmentBeanList
|
liveDataQsRecordBean.value?.attachmentBeanList = it.attachmentBeanList
|
||||||
liveDataLanInfoChange.postValue(it.description)
|
liveDataLanInfoChange.postValue(it.description)
|
||||||
|
description = it.description
|
||||||
|
|
||||||
// 显示语音数据到界面
|
// 显示语音数据到界面
|
||||||
getChatMsgEntityList()
|
getChatMsgEntityList()
|
||||||
realm.close()
|
realm.close()
|
||||||
@ -808,14 +819,24 @@ class EvaluationResultViewModel @Inject constructor(
|
|||||||
out.close()
|
out.close()
|
||||||
val picList = mutableListOf<String>()
|
val picList = mutableListOf<String>()
|
||||||
if (liveDataPictureList.value == null) {
|
if (liveDataPictureList.value == null) {
|
||||||
picList.add(file.absolutePath)
|
picList.add(file.name)
|
||||||
} else {
|
} else {
|
||||||
picList.addAll(liveDataPictureList.value!!)
|
picList.addAll(liveDataPictureList.value!!)
|
||||||
picList.add(file.absolutePath)
|
picList.add(file.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var attachmentList: RealmList<AttachmentBean> = RealmList()
|
||||||
|
//赋值处理
|
||||||
|
if (liveDataQsRecordBean.value?.attachmentBeanList?.isEmpty() == false) {
|
||||||
|
attachmentList = liveDataQsRecordBean.value?.attachmentBeanList!!
|
||||||
|
}
|
||||||
|
val attachmentBean = AttachmentBean()
|
||||||
|
attachmentBean.name = file.name!!
|
||||||
|
attachmentBean.type = 2
|
||||||
|
attachmentList.add(attachmentBean)
|
||||||
|
liveDataQsRecordBean.value?.attachmentBeanList = attachmentList
|
||||||
liveDataPictureList.postValue(picList)
|
liveDataPictureList.postValue(picList)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,9 +2,13 @@ package com.navinfo.omqs.ui.fragment.evaluationresult
|
|||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import com.navinfo.omqs.Constant
|
||||||
|
import com.navinfo.omqs.R
|
||||||
import com.navinfo.omqs.databinding.AdapterPictureBinding
|
import com.navinfo.omqs.databinding.AdapterPictureBinding
|
||||||
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||||
|
import com.navinfo.omqs.util.ImageTools
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class PictureAdapter : BaseRecyclerViewAdapter<String>() {
|
class PictureAdapter : BaseRecyclerViewAdapter<String>() {
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||||
@ -15,7 +19,18 @@ class PictureAdapter : BaseRecyclerViewAdapter<String>() {
|
|||||||
|
|
||||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||||
val bd = holder.viewBinding as AdapterPictureBinding
|
val bd = holder.viewBinding as AdapterPictureBinding
|
||||||
bd.button.text = data[position]
|
|
||||||
|
val myAppDir = File(Constant.USER_DATA_ATTACHEMNT_PATH)
|
||||||
|
|
||||||
|
if (!myAppDir.exists()) myAppDir.mkdirs() // 确保文件夹已创建
|
||||||
|
|
||||||
|
// 创建一个名为 fileName 的文件
|
||||||
|
val file = File(myAppDir, data[position])
|
||||||
|
if(file.exists()){
|
||||||
|
bd.showImage.setImageBitmap(ImageTools.zoomBitmap(Constant.USER_DATA_ATTACHEMNT_PATH+"/"+data[position],2))
|
||||||
|
}else{
|
||||||
|
bd.showImage.setBackgroundResource(R.drawable.icon_camera_img)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,17 +1,40 @@
|
|||||||
package com.navinfo.omqs.ui.fragment.note
|
package com.navinfo.omqs.ui.fragment.note
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.ViewTreeObserver
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.ActivityResult
|
||||||
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.navinfo.collect.library.enums.DataCodeEnum
|
||||||
|
import com.navinfo.omqs.Constant
|
||||||
import com.navinfo.omqs.R
|
import com.navinfo.omqs.R
|
||||||
import com.navinfo.omqs.databinding.FragmentNoteBinding
|
import com.navinfo.omqs.databinding.FragmentNoteBinding
|
||||||
import com.navinfo.omqs.ui.dialog.FirstDialog
|
import com.navinfo.omqs.ui.dialog.FirstDialog
|
||||||
import com.navinfo.omqs.ui.fragment.BaseFragment
|
import com.navinfo.omqs.ui.fragment.BaseFragment
|
||||||
|
import com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment
|
||||||
|
import com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultViewModel
|
||||||
|
import com.navinfo.omqs.ui.fragment.evaluationresult.PhenomenonFragment
|
||||||
|
import com.navinfo.omqs.ui.fragment.evaluationresult.PictureAdapter
|
||||||
|
import com.navinfo.omqs.ui.fragment.evaluationresult.ProblemLinkFragment
|
||||||
|
import com.navinfo.omqs.ui.fragment.evaluationresult.SoundtListAdapter
|
||||||
import com.navinfo.omqs.ui.other.shareViewModels
|
import com.navinfo.omqs.ui.other.shareViewModels
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
@ -20,8 +43,30 @@ class NoteFragment : BaseFragment(), View.OnClickListener {
|
|||||||
private var _binding: FragmentNoteBinding? = null
|
private var _binding: FragmentNoteBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private var mCameraLauncher: ActivityResultLauncher<Intent>? = null
|
||||||
|
|
||||||
private val viewModel by shareViewModels<NoteViewModel>("note")
|
private val viewModel by shareViewModels<NoteViewModel>("note")
|
||||||
|
|
||||||
|
private val pictureAdapter by lazy {
|
||||||
|
PictureAdapter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
mCameraLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result: ActivityResult ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
// 处理相机返回的结果
|
||||||
|
val extras = result.data!!.extras
|
||||||
|
val imageBitmap: Bitmap? = extras!!["data"] as Bitmap?
|
||||||
|
// 在这里处理图片数据
|
||||||
|
if (imageBitmap != null)
|
||||||
|
viewModel.savePhoto(imageBitmap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
@ -29,7 +74,19 @@ class NoteFragment : BaseFragment(), View.OnClickListener {
|
|||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
activity?.run {
|
||||||
|
findNavController(
|
||||||
|
R.id.main_activity_middle_fragment
|
||||||
|
).navigate(R.id.CanvasFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
//// 设置 RecyclerView 的固定大小,避免在滚动时重新计算视图大小和布局,提高性能
|
||||||
|
binding.noteVoiceRecyclerview.setHasFixedSize(true)
|
||||||
|
val layoutManager = LinearLayoutManager(context)
|
||||||
|
binding.noteVoiceRecyclerview.layoutManager = layoutManager
|
||||||
binding.sketchEraser.setOnClickListener(this)
|
binding.sketchEraser.setOnClickListener(this)
|
||||||
binding.sketchClear.setOnClickListener(this)
|
binding.sketchClear.setOnClickListener(this)
|
||||||
binding.sketchForward.setOnClickListener(this)
|
binding.sketchForward.setOnClickListener(this)
|
||||||
@ -37,6 +94,7 @@ class NoteFragment : BaseFragment(), View.OnClickListener {
|
|||||||
binding.noteBarSave.setOnClickListener(this)
|
binding.noteBarSave.setOnClickListener(this)
|
||||||
binding.noteBarCancel.setOnClickListener(this)
|
binding.noteBarCancel.setOnClickListener(this)
|
||||||
binding.noteBarDelete.setOnClickListener(this)
|
binding.noteBarDelete.setOnClickListener(this)
|
||||||
|
binding.noteCamera.setOnClickListener(this)
|
||||||
binding.noteDescription.addTextChangedListener(object : TextWatcher {
|
binding.noteDescription.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
}
|
}
|
||||||
@ -48,6 +106,30 @@ class NoteFragment : BaseFragment(), View.OnClickListener {
|
|||||||
viewModel.noteBeanDescription = s.toString()
|
viewModel.noteBeanDescription = s.toString()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
viewModel.liveDataNoteBean.observe(viewLifecycleOwner) {
|
||||||
|
binding.noteDescription.setText(it.description)
|
||||||
|
}
|
||||||
|
|
||||||
|
//监听要提示的信息
|
||||||
|
viewModel.liveDataToastMessage.observe(viewLifecycleOwner) {
|
||||||
|
Toast.makeText(requireContext(), it, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 监听左侧栏的点击事件
|
||||||
|
*/
|
||||||
|
val adapter = SoundtListAdapter { _, _ ->
|
||||||
|
|
||||||
|
}
|
||||||
|
binding.noteVoiceRecyclerview.adapter = adapter
|
||||||
|
/**
|
||||||
|
* 照片view
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 照片view
|
||||||
|
*/
|
||||||
|
binding.notePictureViewpager.adapter = pictureAdapter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据操作结束
|
* 数据操作结束
|
||||||
*/
|
*/
|
||||||
@ -69,29 +151,107 @@ class NoteFragment : BaseFragment(), View.OnClickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频view
|
||||||
|
*/
|
||||||
|
viewModel.listDataChatMsgEntityList.observe(viewLifecycleOwner) {
|
||||||
|
adapter.refreshData(it)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
/**
|
||||||
super.onStart()
|
* 照片view
|
||||||
activity?.run {
|
*/
|
||||||
findNavController(
|
viewModel.liveDataPictureList.observe(viewLifecycleOwner){
|
||||||
R.id.main_activity_middle_fragment
|
pictureAdapter.refreshData(it)
|
||||||
).navigate(R.id.CanvasFragment)
|
}
|
||||||
|
|
||||||
|
//照片左右选择键点击监听
|
||||||
|
binding.notePictureLeft.setOnClickListener(this)
|
||||||
|
binding.notePictureRight.setOnClickListener(this)
|
||||||
|
binding.noteCamera.setOnClickListener(this)
|
||||||
|
//设置照片偏移量
|
||||||
|
val viewPager = binding.notePictureViewpager
|
||||||
|
val vto = viewPager.viewTreeObserver
|
||||||
|
vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||||
|
override fun onGlobalLayout() {
|
||||||
|
val width = viewPager.width
|
||||||
|
// 处理View宽度
|
||||||
|
// 在回调完成后,需要将监听器从View树中移除,以避免重复调用
|
||||||
|
viewPager.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||||
|
|
||||||
|
val recyclerView = viewPager.getChildAt(0) as RecyclerView
|
||||||
|
|
||||||
|
recyclerView.setPadding(0, 0, width / 2 - 30, 0)
|
||||||
|
recyclerView.clipToPadding = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
binding.noteVoice.setOnTouchListener { _, event ->
|
||||||
|
Log.e("qj", event?.action.toString())
|
||||||
|
when (event?.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
voiceOnTouchStart()//Do Something
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_OUTSIDE -> {
|
||||||
|
voiceOnTouchStop()//Do Something
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
private fun voiceOnTouchStart() {
|
||||||
super.onStop()
|
viewModel.startSoundMetter(requireActivity(), binding.noteVoice)
|
||||||
activity?.run {
|
}
|
||||||
findNavController(
|
|
||||||
R.id.main_activity_middle_fragment
|
private fun voiceOnTouchStop() {
|
||||||
).navigateUp()
|
Log.e("qj", "voiceOnTouchStop====${Constant.IS_VIDEO_SPEED}")
|
||||||
|
if (Constant.IS_VIDEO_SPEED) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
viewModel.stopSoundMeter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun takePhoto() {
|
||||||
|
try {
|
||||||
|
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
|
||||||
|
if (takePictureIntent.resolveActivity(requireActivity().packageManager) != null) {
|
||||||
|
mCameraLauncher!!.launch(takePictureIntent)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d("TTTT", e.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
activity?.run {
|
||||||
|
val result = findNavController(R.id.main_activity_middle_fragment).navigateUp()
|
||||||
|
Log.e("qj","onStop===$result")
|
||||||
|
}
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
when (v) {
|
when (v) {
|
||||||
|
binding.notePictureLeft->{
|
||||||
|
val currentItem = binding.notePictureViewpager.currentItem
|
||||||
|
if (currentItem > 0) {
|
||||||
|
binding.notePictureViewpager.currentItem = currentItem - 1
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.notePictureRight->{
|
||||||
|
val currentItem = binding.notePictureViewpager.currentItem
|
||||||
|
if (currentItem < pictureAdapter.data.size - 1) {
|
||||||
|
binding.notePictureViewpager.currentItem = currentItem + 1
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
binding.sketchEraser -> {
|
binding.sketchEraser -> {
|
||||||
viewModel.onEraser()
|
viewModel.onEraser()
|
||||||
binding.sketchEraser.isSelected = viewModel.isEraser
|
binding.sketchEraser.isSelected = viewModel.isEraser
|
||||||
@ -125,6 +285,9 @@ class NoteFragment : BaseFragment(), View.OnClickListener {
|
|||||||
mDialog.setNegativeButton("取消", null)
|
mDialog.setNegativeButton("取消", null)
|
||||||
mDialog.show()
|
mDialog.show()
|
||||||
}
|
}
|
||||||
|
binding.noteCamera-> {
|
||||||
|
takePhoto()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,43 @@
|
|||||||
package com.navinfo.omqs.ui.fragment.note
|
package com.navinfo.omqs.ui.fragment.note
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.drawable.AnimationDrawable
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.PopupWindow
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.blankj.utilcode.util.ToastUtils
|
||||||
|
import com.navinfo.collect.library.data.entity.AttachmentBean
|
||||||
import com.navinfo.collect.library.data.entity.NoteBean
|
import com.navinfo.collect.library.data.entity.NoteBean
|
||||||
|
import com.navinfo.collect.library.data.entity.QsRecordBean
|
||||||
import com.navinfo.collect.library.map.NIMapController
|
import com.navinfo.collect.library.map.NIMapController
|
||||||
import com.navinfo.collect.library.utils.MapParamUtils
|
import com.navinfo.collect.library.utils.MapParamUtils
|
||||||
|
import com.navinfo.omqs.Constant
|
||||||
|
import com.navinfo.omqs.R
|
||||||
|
import com.navinfo.omqs.bean.ChatMsgEntity
|
||||||
import com.navinfo.omqs.db.RealmOperateHelper
|
import com.navinfo.omqs.db.RealmOperateHelper
|
||||||
import com.navinfo.omqs.ui.dialog.FirstDialog
|
import com.navinfo.omqs.ui.dialog.FirstDialog
|
||||||
|
import com.navinfo.omqs.util.DateTimeUtil
|
||||||
|
import com.navinfo.omqs.util.SoundMeter
|
||||||
|
import com.navinfo.omqs.util.SpeakMode
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmList
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@ -24,32 +49,40 @@ class NoteViewModel @Inject constructor(
|
|||||||
lateinit var canvasView: CanvasView
|
lateinit var canvasView: CanvasView
|
||||||
|
|
||||||
|
|
||||||
var mNoteBean: NoteBean? = null
|
/**
|
||||||
|
* 要保存的评测数据
|
||||||
|
*/
|
||||||
|
val liveDataNoteBean = MutableLiveData(NoteBean(id = UUID.randomUUID().toString()))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语音列表
|
||||||
|
*/
|
||||||
|
val listDataChatMsgEntityList = MutableLiveData<MutableList<ChatMsgEntity>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 照片列表
|
||||||
|
*/
|
||||||
|
val liveDataPictureList = MutableLiveData<MutableList<String>>()
|
||||||
|
|
||||||
var isEraser = false
|
var isEraser = false
|
||||||
|
|
||||||
var noteBeanDescription = ""
|
var noteBeanDescription = ""
|
||||||
// /**
|
|
||||||
// * 橡皮擦开关
|
|
||||||
// */
|
|
||||||
// val liveEraserData = MutableLiveData(false)
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 清除按钮
|
|
||||||
// */
|
|
||||||
// val liveClearData = MutableLiveData(false)
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 回退按钮
|
|
||||||
// */
|
|
||||||
// val liveBackData = MutableLiveData(false)
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 撤销按钮
|
|
||||||
// */
|
|
||||||
// val liveForward = MutableLiveData(false)
|
|
||||||
|
|
||||||
|
//语音窗体
|
||||||
|
private var pop: PopupWindow? = null
|
||||||
|
|
||||||
|
private var mSpeakMode: SpeakMode? = null
|
||||||
|
|
||||||
|
var oldBean: NoteBean? = null
|
||||||
|
|
||||||
|
//录音图标
|
||||||
|
var volume: ImageView? = null
|
||||||
|
|
||||||
|
var mSoundMeter: SoundMeter? = null
|
||||||
|
/**
|
||||||
|
* toast信息
|
||||||
|
*/
|
||||||
|
val liveDataToastMessage = MutableLiveData<String>()
|
||||||
/**
|
/**
|
||||||
* 处理结束关闭fragment
|
* 处理结束关闭fragment
|
||||||
*/
|
*/
|
||||||
@ -105,21 +138,21 @@ class NoteViewModel @Inject constructor(
|
|||||||
fun onSaveData() {
|
fun onSaveData() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
if (canvasView.paths != null && canvasView.paths!!.isNotEmpty()) {
|
if (canvasView.paths != null && canvasView.paths!!.isNotEmpty()) {
|
||||||
var noteBean =
|
var noteBean = CanvasViewHelper.createNoteBean(mapController, canvasView.paths!!)
|
||||||
CanvasViewHelper.createNoteBean(mapController, canvasView.paths!!)
|
liveDataNoteBean.value!!.taskId = MapParamUtils.getTaskId()
|
||||||
if (mNoteBean != null) {
|
liveDataNoteBean.value!!.list = noteBean.list
|
||||||
noteBean.id = mNoteBean!!.id
|
liveDataNoteBean.value!!.description = noteBeanDescription
|
||||||
noteBean.description = noteBeanDescription
|
liveDataNoteBean.value!!.guideGeometry = noteBean.guideGeometry
|
||||||
}
|
|
||||||
noteBean.taskId = MapParamUtils.getTaskId()
|
|
||||||
mNoteBean = noteBean
|
|
||||||
val realm = realmOperateHelper.getRealmDefaultInstance()
|
val realm = realmOperateHelper.getRealmDefaultInstance()
|
||||||
realm.executeTransaction {
|
realm.executeTransaction {
|
||||||
it.copyToRealmOrUpdate(noteBean)
|
it.copyToRealmOrUpdate(liveDataNoteBean.value)
|
||||||
}
|
}
|
||||||
mapController.markerHandle.addOrUpdateNoteMark(mNoteBean!!)
|
mapController.markerHandle.addOrUpdateNoteMark(liveDataNoteBean.value!!)
|
||||||
liveDataFinish.postValue(true)
|
liveDataFinish.postValue(true)
|
||||||
|
realm.refresh()
|
||||||
realm.close()
|
realm.close()
|
||||||
|
}else{
|
||||||
|
liveDataToastMessage.postValue("请绘制内容!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +161,7 @@ class NoteViewModel @Inject constructor(
|
|||||||
* 删除数据
|
* 删除数据
|
||||||
*/
|
*/
|
||||||
fun deleteData(context: Context) {
|
fun deleteData(context: Context) {
|
||||||
if (mNoteBean == null) {
|
if (liveDataNoteBean.value == null) {
|
||||||
liveDataFinish.postValue(true)
|
liveDataFinish.postValue(true)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@ -143,10 +176,10 @@ class NoteViewModel @Inject constructor(
|
|||||||
val realm = realmOperateHelper.getRealmDefaultInstance()
|
val realm = realmOperateHelper.getRealmDefaultInstance()
|
||||||
realm.executeTransaction {
|
realm.executeTransaction {
|
||||||
val objects = it.where(NoteBean::class.java)
|
val objects = it.where(NoteBean::class.java)
|
||||||
.equalTo("id", mNoteBean!!.id).findFirst()
|
.equalTo("id", liveDataNoteBean.value!!.id).findFirst()
|
||||||
objects?.deleteFromRealm()
|
objects?.deleteFromRealm()
|
||||||
}
|
}
|
||||||
mapController.markerHandle.removeNoteMark(mNoteBean!!)
|
mapController.markerHandle.removeNoteMark(liveDataNoteBean.value!!)
|
||||||
liveDataFinish.postValue(true)
|
liveDataFinish.postValue(true)
|
||||||
realm.close()
|
realm.close()
|
||||||
}
|
}
|
||||||
@ -159,20 +192,200 @@ class NoteViewModel @Inject constructor(
|
|||||||
/**
|
/**
|
||||||
* 初始化数据
|
* 初始化数据
|
||||||
*/
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
fun initData(id: String) {
|
fun initData(id: String) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val realm = realmOperateHelper.getRealmDefaultInstance()
|
val realm = realmOperateHelper.getRealmDefaultInstance()
|
||||||
realm.executeTransaction { it ->
|
realm.executeTransaction { it ->
|
||||||
val objects = it.where(NoteBean::class.java)
|
val objects = it.where(NoteBean::class.java)
|
||||||
.equalTo("id", id).findFirst()
|
.equalTo("id", id).findFirst()
|
||||||
mNoteBean = realm.copyFromRealm(objects)
|
if(objects!=null){
|
||||||
mNoteBean?.let { bean ->
|
oldBean = realm.copyFromRealm(objects)
|
||||||
noteBeanDescription = bean.description
|
oldBean?.let {
|
||||||
val list = CanvasViewHelper.createDrawPaths(mapController, bean)
|
noteBeanDescription = it.description
|
||||||
canvasView.setDrawPathList(list)
|
liveDataNoteBean.postValue(it.copy())
|
||||||
|
val list = CanvasViewHelper.createDrawPaths(mapController, it)
|
||||||
|
canvasView.setDrawPathList(list)
|
||||||
|
liveDataNoteBean.value?.attachmentBeanList = it.attachmentBeanList
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 显示语音数据到界面
|
||||||
|
getChatMsgEntityList()
|
||||||
|
|
||||||
realm.close()
|
realm.close()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun startSoundMetter(activity: Activity, v: View) {
|
||||||
|
|
||||||
|
if (mSpeakMode == null) {
|
||||||
|
mSpeakMode = SpeakMode(activity)
|
||||||
|
}
|
||||||
|
|
||||||
|
//语音识别动画
|
||||||
|
if (pop == null) {
|
||||||
|
pop = PopupWindow()
|
||||||
|
pop!!.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
pop!!.height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
pop!!.setBackgroundDrawable(BitmapDrawable())
|
||||||
|
val view =
|
||||||
|
View.inflate(activity as Context, R.layout.cv_card_voice_rcd_hint_window, null)
|
||||||
|
pop!!.contentView = view
|
||||||
|
volume = view.findViewById(R.id.volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
pop!!.update()
|
||||||
|
|
||||||
|
Constant.IS_VIDEO_SPEED = true
|
||||||
|
//录音动画
|
||||||
|
if (pop != null) {
|
||||||
|
pop!!.showAtLocation(v, Gravity.CENTER, 0, 0)
|
||||||
|
}
|
||||||
|
volume!!.setBackgroundResource(R.drawable.pop_voice_img)
|
||||||
|
val animation = volume!!.background as AnimationDrawable
|
||||||
|
animation.start()
|
||||||
|
|
||||||
|
val name: String = DateTimeUtil.getTimeSSS().toString() + ".m4a"
|
||||||
|
if (mSoundMeter == null) {
|
||||||
|
mSoundMeter = SoundMeter()
|
||||||
|
}
|
||||||
|
mSoundMeter!!.setmListener(object : SoundMeter.OnSoundMeterListener {
|
||||||
|
@RequiresApi(Build.VERSION_CODES.Q)
|
||||||
|
override fun onSuccess(filePath: String?) {
|
||||||
|
filePath?.let {
|
||||||
|
val file = File(it)
|
||||||
|
if (file.exists() && file.length() < 1600) {
|
||||||
|
ToastUtils.showLong("语音时间太短,无效!")
|
||||||
|
mSpeakMode!!.speakText("语音时间太短,无效")
|
||||||
|
stopSoundMeter()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mSpeakMode!!.speakText("结束录音")
|
||||||
|
addChatMsgEntity(filePath!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.Q)
|
||||||
|
override fun onfaild(message: String?) {
|
||||||
|
ToastUtils.showLong("录制失败!")
|
||||||
|
mSpeakMode!!.speakText("录制失败")
|
||||||
|
stopSoundMeter()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mSoundMeter!!.start(Constant.USER_DATA_ATTACHEMNT_PATH + name)
|
||||||
|
ToastUtils.showLong("开始录音")
|
||||||
|
mSpeakMode!!.speakText("开始录音")
|
||||||
|
}
|
||||||
|
|
||||||
|
//停止语音录制
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.Q)
|
||||||
|
fun stopSoundMeter() {
|
||||||
|
//先重置标识,防止按钮抬起时触发语音结束
|
||||||
|
Constant.IS_VIDEO_SPEED = false
|
||||||
|
if (mSoundMeter != null && mSoundMeter!!.isStartSound) {
|
||||||
|
mSoundMeter!!.stop()
|
||||||
|
}
|
||||||
|
pop?.let {
|
||||||
|
if (it.isShowing) {
|
||||||
|
it.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun savePhoto(bitmap: Bitmap) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
// 创建一个名为 "MyApp" 的文件夹
|
||||||
|
val myAppDir = File(Constant.USER_DATA_ATTACHEMNT_PATH)
|
||||||
|
if (!myAppDir.exists()) myAppDir.mkdirs() // 确保文件夹已创建
|
||||||
|
|
||||||
|
// 创建一个名为 fileName 的文件
|
||||||
|
val file = File(myAppDir, "${UUID.randomUUID()}.png")
|
||||||
|
file.createNewFile() // 创建文件
|
||||||
|
|
||||||
|
// 将 Bitmap 压缩为 JPEG 格式,并将其写入文件中
|
||||||
|
val out = FileOutputStream(file)
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
|
||||||
|
out.flush()
|
||||||
|
out.close()
|
||||||
|
val picList = mutableListOf<String>()
|
||||||
|
if (liveDataPictureList.value == null) {
|
||||||
|
picList.add(file.name)
|
||||||
|
} else {
|
||||||
|
picList.addAll(liveDataPictureList.value!!)
|
||||||
|
picList.add(file.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
var attachmentList: RealmList<AttachmentBean> = RealmList()
|
||||||
|
//赋值处理
|
||||||
|
if (liveDataNoteBean.value?.attachmentBeanList?.isEmpty() == false) {
|
||||||
|
attachmentList = liveDataNoteBean.value?.attachmentBeanList!!
|
||||||
|
}
|
||||||
|
val attachmentBean = AttachmentBean()
|
||||||
|
attachmentBean.name = file.name!!
|
||||||
|
attachmentBean.type = 2
|
||||||
|
attachmentList.add(attachmentBean)
|
||||||
|
liveDataNoteBean.value?.attachmentBeanList = attachmentList
|
||||||
|
liveDataPictureList.postValue(picList)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多媒体列表
|
||||||
|
*/
|
||||||
|
private suspend fun getChatMsgEntityList() {
|
||||||
|
val chatMsgEntityList: MutableList<ChatMsgEntity> = ArrayList()
|
||||||
|
val pictureList: MutableList<String> = ArrayList()
|
||||||
|
liveDataNoteBean.value?.attachmentBeanList?.forEach {
|
||||||
|
//1 录音
|
||||||
|
if (it.type == 1) {
|
||||||
|
val chatMsgEntity = ChatMsgEntity()
|
||||||
|
chatMsgEntity.name = it.name
|
||||||
|
chatMsgEntity.voiceUri = Constant.USER_DATA_ATTACHEMNT_PATH
|
||||||
|
chatMsgEntityList.add(chatMsgEntity)
|
||||||
|
}else if(it.type==2){
|
||||||
|
pictureList.add(it.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
listDataChatMsgEntityList.postValue(chatMsgEntityList)
|
||||||
|
liveDataPictureList.postValue(pictureList)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addChatMsgEntity(filePath: String) {
|
||||||
|
|
||||||
|
if (filePath.isNotEmpty()) {
|
||||||
|
var chatMsgEntityList: MutableList<ChatMsgEntity> = ArrayList()
|
||||||
|
if (listDataChatMsgEntityList.value?.isEmpty() == false) {
|
||||||
|
chatMsgEntityList = listDataChatMsgEntityList.value!!
|
||||||
|
}
|
||||||
|
val chatMsgEntity = ChatMsgEntity()
|
||||||
|
chatMsgEntity.name = filePath.replace(Constant.USER_DATA_ATTACHEMNT_PATH, "").toString()
|
||||||
|
chatMsgEntity.voiceUri = Constant.USER_DATA_ATTACHEMNT_PATH
|
||||||
|
chatMsgEntityList.add(chatMsgEntity)
|
||||||
|
|
||||||
|
|
||||||
|
var attachmentList: RealmList<AttachmentBean> = RealmList()
|
||||||
|
|
||||||
|
//赋值处理
|
||||||
|
if (liveDataNoteBean.value?.attachmentBeanList?.isEmpty() == false) {
|
||||||
|
attachmentList = liveDataNoteBean.value?.attachmentBeanList!!
|
||||||
|
}
|
||||||
|
|
||||||
|
val attachmentBean = AttachmentBean()
|
||||||
|
attachmentBean.name = chatMsgEntity.name!!
|
||||||
|
attachmentBean.type = 1
|
||||||
|
attachmentList.add(attachmentBean)
|
||||||
|
liveDataNoteBean.value?.attachmentBeanList = attachmentList
|
||||||
|
|
||||||
|
listDataChatMsgEntityList.postValue(chatMsgEntityList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
943
app/src/main/java/com/navinfo/omqs/util/ImageLoad.java
Normal file
943
app/src/main/java/com/navinfo/omqs/util/ImageLoad.java
Normal file
@ -0,0 +1,943 @@
|
|||||||
|
package com.navinfo.omqs.util;
|
||||||
|
|
||||||
|
|
||||||
|
//Download by http://www.codefans.net
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Bitmap.Config;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.PorterDuff.Mode;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader.TileMode;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.media.ExifInterface;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tools for handler picture
|
||||||
|
*
|
||||||
|
* @author Ryan.Tang
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class ImageLoad {
|
||||||
|
static Bitmap bitmap = null;
|
||||||
|
Context con;
|
||||||
|
|
||||||
|
public ImageLoad(Context con){
|
||||||
|
this.con=con;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer drawable to bitmap
|
||||||
|
*
|
||||||
|
* @param drawable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap drawableToBitmap(Drawable drawable) {
|
||||||
|
int w = drawable.getIntrinsicWidth();
|
||||||
|
int h = drawable.getIntrinsicHeight();
|
||||||
|
|
||||||
|
Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
|
||||||
|
: Config.RGB_565;
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, w, h);
|
||||||
|
drawable.draw(canvas);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap to drawable
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Drawable bitmapToDrawable(Bitmap bitmap) {
|
||||||
|
return new BitmapDrawable(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input stream to bitmap
|
||||||
|
*
|
||||||
|
* @param inputStream
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static Bitmap inputStreamToBitmap(InputStream inputStream)
|
||||||
|
throws Exception {
|
||||||
|
return BitmapFactory.decodeStream(inputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte transfer to bitmap
|
||||||
|
*
|
||||||
|
* @param byteArray
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap byteToBitmap(byte[] byteArray) {
|
||||||
|
if (byteArray.length != 0) {
|
||||||
|
return BitmapFactory
|
||||||
|
.decodeByteArray(byteArray, 0, byteArray.length);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte transfer to drawable
|
||||||
|
*
|
||||||
|
* @param byteArray
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Drawable byteToDrawable(byte[] byteArray) {
|
||||||
|
ByteArrayInputStream ins = null;
|
||||||
|
if (byteArray != null) {
|
||||||
|
ins = new ByteArrayInputStream(byteArray);
|
||||||
|
}
|
||||||
|
return Drawable.createFromStream(ins, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap transfer to bytes
|
||||||
|
*
|
||||||
|
* @param byteArray
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] bitmapToBytes(Bitmap bm) {
|
||||||
|
byte[] bytes = null;
|
||||||
|
if (bm != null) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
|
||||||
|
bytes = baos.toByteArray();
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawable transfer to bytes
|
||||||
|
*
|
||||||
|
* @param drawable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] drawableToBytes(Drawable drawable) {
|
||||||
|
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||||
|
Bitmap bitmap = bitmapDrawable.getBitmap();
|
||||||
|
byte[] bytes = bitmapToBytes(bitmap);
|
||||||
|
;
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base64 to byte[] //
|
||||||
|
*/
|
||||||
|
// public static byte[] base64ToBytes(String base64) throws IOException {
|
||||||
|
// byte[] bytes = Base64.decode(base64);
|
||||||
|
// return bytes;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Byte[] to base64
|
||||||
|
// */
|
||||||
|
// public static String bytesTobase64(byte[] bytes) {
|
||||||
|
// String base64 = Base64.encode(bytes);
|
||||||
|
// return base64;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create reflection images
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
|
||||||
|
final int reflectionGap = 4;
|
||||||
|
int w = bitmap.getWidth();
|
||||||
|
int h = bitmap.getHeight();
|
||||||
|
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.preScale(1, -1);
|
||||||
|
|
||||||
|
Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, h / 2, w,
|
||||||
|
h / 2, matrix, false);
|
||||||
|
|
||||||
|
Bitmap bitmapWithReflection = Bitmap.createBitmap(w, (h + h / 2),
|
||||||
|
Config.ARGB_8888);
|
||||||
|
|
||||||
|
Canvas canvas = new Canvas(bitmapWithReflection);
|
||||||
|
canvas.drawBitmap(bitmap, 0, 0, null);
|
||||||
|
Paint deafalutPaint = new Paint();
|
||||||
|
canvas.drawRect(0, h, w, h + reflectionGap, deafalutPaint);
|
||||||
|
|
||||||
|
canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null);
|
||||||
|
|
||||||
|
Paint paint = new Paint();
|
||||||
|
LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
|
||||||
|
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
|
||||||
|
0x00ffffff, TileMode.CLAMP);
|
||||||
|
paint.setShader(shader);
|
||||||
|
// Set the Transfer mode to be porter duff and destination in
|
||||||
|
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
|
||||||
|
// Draw a rectangle using the paint with our linear gradient
|
||||||
|
canvas.drawRect(0, h, w, bitmapWithReflection.getHeight()
|
||||||
|
+ reflectionGap, paint);
|
||||||
|
|
||||||
|
return bitmapWithReflection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 圆角
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
* @param roundPx
|
||||||
|
* 5 10
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
|
||||||
|
int w = bitmap.getWidth();
|
||||||
|
int h = bitmap.getHeight();
|
||||||
|
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(output);
|
||||||
|
final int color = 0xff424242;
|
||||||
|
final Paint paint = new Paint();
|
||||||
|
final Rect rect = new Rect(0, 0, w, h);
|
||||||
|
final RectF rectF = new RectF(rect);
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
canvas.drawARGB(0, 0, 0, 0);
|
||||||
|
paint.setColor(color);
|
||||||
|
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
|
||||||
|
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
|
||||||
|
canvas.drawBitmap(bitmap, rect, rect, paint);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the bitmap
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
|
||||||
|
int w = bitmap.getWidth();
|
||||||
|
int h = bitmap.getHeight();
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
float scaleWidth = ((float) width / w);
|
||||||
|
float scaleHeight = ((float) height / h);
|
||||||
|
matrix.postScale(scaleWidth, scaleHeight);
|
||||||
|
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
|
||||||
|
return newbmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap zoomBitmap(String cameraPath,int width,int height, int size) {
|
||||||
|
|
||||||
|
// 获取图片Exif
|
||||||
|
ExifInterface exif;
|
||||||
|
int degree = 0;
|
||||||
|
try {
|
||||||
|
exif = new ExifInterface(cameraPath);
|
||||||
|
// 获取指定tag的属性值
|
||||||
|
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
|
||||||
|
if (orientation != -1) {
|
||||||
|
// We only recognize a subset of orientation tag values.
|
||||||
|
switch (orientation) {
|
||||||
|
case ExifInterface.ORIENTATION_NORMAL:
|
||||||
|
degree = 0 ;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_UNDEFINED:
|
||||||
|
degree = 0 ;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
degree = 180;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
degree = 270;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
CMLog.writeLogtoFile("展示图片生成异常", "异常", e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
|
||||||
|
bmpFactoryOptions.inJustDecodeBounds = true;
|
||||||
|
bitmap = BitmapFactory.decodeFile(cameraPath,bmpFactoryOptions);//此时返回bm为空
|
||||||
|
bmpFactoryOptions.inJustDecodeBounds = false;
|
||||||
|
bmpFactoryOptions.inSampleSize = size;
|
||||||
|
int heightRatio = (int) Math.ceil(bmpFactoryOptions.outHeight/ (float) height);
|
||||||
|
int widthRatio = (int) Math.ceil(bmpFactoryOptions.outWidth/ (float) width);
|
||||||
|
if (heightRatio > 1 && widthRatio > 1) {
|
||||||
|
bmpFactoryOptions.inSampleSize = heightRatio < widthRatio ? heightRatio: widthRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
bmpFactoryOptions.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设
|
||||||
|
bmpFactoryOptions.inPurgeable = true;// 同时设置才会有效
|
||||||
|
bmpFactoryOptions.inInputShareable = true;//。当系统内存不够时候图片自动被回收
|
||||||
|
if(bitmap!=null&&!bitmap.isRecycled())
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap=BitmapFactory.decodeFile(cameraPath, bmpFactoryOptions);
|
||||||
|
|
||||||
|
if (degree != 0 && bitmap != null) {
|
||||||
|
Matrix m = new Matrix();
|
||||||
|
m.setRotate(degree, (float) bitmap.getWidth() / 2,(float) bitmap.getHeight() / 2);
|
||||||
|
|
||||||
|
Bitmap b2 = Bitmap.createBitmap(bitmap, 0, 0,bitmap.getWidth(), bitmap.getHeight(), m, true);
|
||||||
|
if (bitmap != b2) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = b2;
|
||||||
|
if(b2!=null&&b2.isRecycled())
|
||||||
|
b2.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
CMLog.writeLogtoFile("照片内存溢出", "异常", "创建展示图异常:OutOfMemoryError");
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
//new File(cameraPath).delete();
|
||||||
|
return bitmap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap zoomBitmap(String cameraPath, int multiple) {
|
||||||
|
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.inSampleSize = multiple; // 图片宽高都为原来的二分之一,即图片为原来的四分之一
|
||||||
|
// 获取图片Exif
|
||||||
|
ExifInterface exif;
|
||||||
|
int degree = 0;
|
||||||
|
try {
|
||||||
|
exif = new ExifInterface(cameraPath);
|
||||||
|
// 获取指定tag的属性值
|
||||||
|
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
|
||||||
|
if (orientation != -1) {
|
||||||
|
// We only recognize a subset of orientation tag values.
|
||||||
|
switch (orientation) {
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
degree = 180;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
degree = 270;
|
||||||
|
break;
|
||||||
|
/* default:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
CMLog.writeLogtoFile("缩略图生成异常", "异常", e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
bitmap = ImageCrop(BitmapFactory.decodeFile(cameraPath, options));
|
||||||
|
if (degree != 0 && bitmap != null) {
|
||||||
|
Matrix m = new Matrix();
|
||||||
|
m.setRotate(degree, (float) bitmap.getWidth() / 2,(float) bitmap.getHeight() / 2);
|
||||||
|
|
||||||
|
Bitmap b2 = Bitmap.createBitmap(bitmap, 0, 0,
|
||||||
|
bitmap.getWidth(), bitmap.getHeight(), m, true);
|
||||||
|
if (bitmap != b2) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
CMLog.writeLogtoFile("照片内存溢出", "异常", "创建缩略图异常:OutOfMemoryError");
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
if (bitmap == null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getDegree(String filePath){
|
||||||
|
if(!new File(filePath).exists())
|
||||||
|
return 0;
|
||||||
|
ExifInterface exif;
|
||||||
|
int degree = 0;
|
||||||
|
try {
|
||||||
|
exif = new ExifInterface(filePath);
|
||||||
|
// 获取指定tag的属性值
|
||||||
|
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
|
||||||
|
if (orientation != -1) {
|
||||||
|
// We only recognize a subset of orientation tag values.
|
||||||
|
switch (orientation) {
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
degree = 180;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
degree = 270;
|
||||||
|
break;
|
||||||
|
/* default:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
CMLog.writeLogtoFile("缩略图生成异常", "异常", e.toString());
|
||||||
|
}
|
||||||
|
return degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按正方形裁切图片
|
||||||
|
*/
|
||||||
|
public static Bitmap ImageCrop(Bitmap bitmap) {
|
||||||
|
if(bitmap == null)
|
||||||
|
return null;
|
||||||
|
int w = bitmap.getWidth(); // 得到图片的宽,高
|
||||||
|
int h = bitmap.getHeight();
|
||||||
|
|
||||||
|
int wh = w > h ? h : w;// 裁切后所取的正方形区域边长
|
||||||
|
|
||||||
|
int retX = w > h ? (w - h) / 2 : 0;// 基于原图,取正方形左上角x坐标
|
||||||
|
int retY = w > h ? 0 : (h - w) / 2;
|
||||||
|
|
||||||
|
// 下面这句是关键
|
||||||
|
return Bitmap.createBitmap(bitmap, retX, retY, wh, wh, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap zoomBitmap(byte[] data, int multiple, int degrees) {
|
||||||
|
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.inSampleSize = multiple; // 图片宽高都为原来的二分之一,即图片为原来的四分之一
|
||||||
|
try {
|
||||||
|
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);
|
||||||
|
|
||||||
|
if (degrees != 0 && bitmap != null) {
|
||||||
|
Matrix m = new Matrix();
|
||||||
|
m.setRotate(degrees, (float) bitmap.getWidth() / 2,
|
||||||
|
(float) bitmap.getHeight() / 2);
|
||||||
|
try {
|
||||||
|
Bitmap b2 = Bitmap.createBitmap(bitmap, 0, 0,
|
||||||
|
bitmap.getWidth(), bitmap.getHeight(), m, true);
|
||||||
|
if (bitmap != b2) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = b2;
|
||||||
|
}
|
||||||
|
} catch (OutOfMemoryError ex) {
|
||||||
|
// We have no memory to rotate. Return the original bitmap.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
CMLog.writeLogtoFile("照片内存溢出", "异常", "创建缩略图异常:OutOfMemoryError");
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
if (bitmap == null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the drawable
|
||||||
|
*
|
||||||
|
* @param drawable
|
||||||
|
* @param w
|
||||||
|
* @param h
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Drawable zoomDrawable(Drawable drawable, int w, int h) {
|
||||||
|
int width = drawable.getIntrinsicWidth();
|
||||||
|
int height = drawable.getIntrinsicHeight();
|
||||||
|
Bitmap oldbmp = drawableToBitmap(drawable);
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
float sx = ((float) w / width);
|
||||||
|
float sy = ((float) h / height);
|
||||||
|
matrix.postScale(sx, sy);
|
||||||
|
Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,
|
||||||
|
matrix, true);
|
||||||
|
return new BitmapDrawable(newbmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get images from SD card by path and the name of image
|
||||||
|
*
|
||||||
|
* @param photoName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap getPhotoFromSDCard(String path, String photoName) {
|
||||||
|
Bitmap photoBitmap = BitmapFactory.decodeFile(path + "/" + photoName
|
||||||
|
+ ".png");
|
||||||
|
if (photoBitmap == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return photoBitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the SD card
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean checkSDCardAvailable() {
|
||||||
|
return android.os.Environment.getExternalStorageState().equals(
|
||||||
|
android.os.Environment.MEDIA_MOUNTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get image from SD card by path and the name of image
|
||||||
|
*
|
||||||
|
* @param photoName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean findPhotoFromSDCard(String path, String photoName) {
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (checkSDCardAvailable()) {
|
||||||
|
File dir = new File(path);
|
||||||
|
if (dir.exists()) {
|
||||||
|
File folders = new File(path);
|
||||||
|
File photoFile[] = folders.listFiles();
|
||||||
|
for (int i = 0; i < photoFile.length; i++) {
|
||||||
|
String fileName = photoFile[i].getName().split("\\.")[0];
|
||||||
|
if (fileName.equals(photoName)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
// File file = new File(path + "/" + photoName + ".jpg" );
|
||||||
|
// if (file.exists()) {
|
||||||
|
// flag = true;
|
||||||
|
// }else {
|
||||||
|
// flag = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save image to the SD card
|
||||||
|
*
|
||||||
|
* @param photoBitmap
|
||||||
|
* @param photoName
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
public static void savePhotoToSDCard(Bitmap photoBitmap, String path,
|
||||||
|
String photoName) {
|
||||||
|
if (checkSDCardAvailable()) {
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
File photoFile = new File(path, photoName + ".png");
|
||||||
|
FileOutputStream fileOutputStream = null;
|
||||||
|
try {
|
||||||
|
fileOutputStream = new FileOutputStream(photoFile);
|
||||||
|
if (photoBitmap != null) {
|
||||||
|
if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100,
|
||||||
|
fileOutputStream)) {
|
||||||
|
fileOutputStream.flush();
|
||||||
|
// fileOutputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
photoFile.delete();
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
photoFile.delete();
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
fileOutputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the image from SD card
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* file:///sdcard/temp.jpg
|
||||||
|
*/
|
||||||
|
public static void deleteAllPhoto(String path) {
|
||||||
|
if (checkSDCardAvailable()) {
|
||||||
|
File folder = new File(path);
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
files[i].delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deletePhotoAtPathAndName(String path, String fileName) {
|
||||||
|
if (checkSDCardAvailable()) {
|
||||||
|
File folder = new File(path);
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
System.out.println(files[i].getName());
|
||||||
|
if (files[i].getName().equals(fileName)) {
|
||||||
|
files[i].delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitmap setImage(Uri mImageCaptureUri) {
|
||||||
|
// 不管是拍照还是选择图片每张图片都有在数据中存储也存储有对应旋转角度orientation值
|
||||||
|
// 所以我们在取出图片是把角度值取出以便能正确的显示图片,没有旋转时的效果观看
|
||||||
|
|
||||||
|
ContentResolver cr = con.getContentResolver();
|
||||||
|
Cursor cursor = cr.query(mImageCaptureUri, null, null, null, null);// 根据Uri从数据库中找
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.moveToFirst();// 把游标移动到首位,因为这里的Uri是包含ID的所以是唯一的不需要循环找指向第一个就是了
|
||||||
|
String filePath = cursor.getString(cursor.getColumnIndex("_data"));// 获取图片路
|
||||||
|
String orientation = cursor.getString(cursor
|
||||||
|
.getColumnIndex("orientation"));// 获取旋转的角度
|
||||||
|
cursor.close();
|
||||||
|
if (filePath != null) {
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeFile(filePath);// 根据Path读取资源图片
|
||||||
|
int angle = 0;
|
||||||
|
if (orientation != null && !"".equals(orientation)) {
|
||||||
|
angle = Integer.parseInt(orientation);
|
||||||
|
}
|
||||||
|
if (angle != 0) {
|
||||||
|
// 下面的方法主要作用是把图片转一个角度,也可以放大缩小等
|
||||||
|
Matrix m = new Matrix();
|
||||||
|
int width = bitmap.getWidth();
|
||||||
|
int height = bitmap.getHeight();
|
||||||
|
m.setRotate(angle); // 旋转angle度
|
||||||
|
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,
|
||||||
|
m, true);// 从新生成图片
|
||||||
|
}
|
||||||
|
// photo.setImageBitmap(bitmap);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取图片属性:旋转的角度
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* 图片绝对路径
|
||||||
|
* @return degree旋转的角度
|
||||||
|
*/
|
||||||
|
public static int readPictureDegree(String path) {
|
||||||
|
int degree = 0;
|
||||||
|
try {
|
||||||
|
ExifInterface exifInterface = new ExifInterface(path);
|
||||||
|
int orientation = exifInterface.getAttributeInt(
|
||||||
|
ExifInterface.TAG_ORIENTATION, -1);
|
||||||
|
switch (orientation) {
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
degree = 180;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
degree = 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Log.i("ImageTools", "获取拍照角度:" + degree);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Log.i("ImageTools", "获取拍照角度异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
return degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 旋转图片
|
||||||
|
*
|
||||||
|
* @param angle
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
*
|
||||||
|
* @return Bitmap
|
||||||
|
*/
|
||||||
|
public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
|
||||||
|
// 旋转图片 动作
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postRotate(angle);
|
||||||
|
System.out.println("angle2=" + angle);
|
||||||
|
if (bitmap != null) {
|
||||||
|
// 创建新的图片
|
||||||
|
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
|
||||||
|
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||||
|
return resizedBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 旋转图片
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
*
|
||||||
|
* @param filePath
|
||||||
|
*
|
||||||
|
* @return Bitmap
|
||||||
|
*/
|
||||||
|
public static void saveBitmap(Bitmap bitmap, String filePath) {
|
||||||
|
File f = new File(filePath);
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
CMLog.writeLogtoFile("照片生成", "拍照", "重新生成照片异常FileNotFoundException:"
|
||||||
|
+ e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
CMLog.writeLogtoFile("照片生成", "拍照", "重新生成照片IO异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 释放Bitmap
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
*/
|
||||||
|
public static void recycleBitmap(Bitmap bitmap) {
|
||||||
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
|
|
||||||
|
// 回收并且置为null
|
||||||
|
|
||||||
|
bitmap.recycle();
|
||||||
|
|
||||||
|
bitmap = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 创建缩略图
|
||||||
|
*
|
||||||
|
* @param filePath
|
||||||
|
*
|
||||||
|
* @return Bitmap
|
||||||
|
*/
|
||||||
|
public static Bitmap createZoominBitmap(String filePath) {
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// 实例化Bitmap
|
||||||
|
|
||||||
|
bitmap = BitmapFactory.decodeFile(filePath);
|
||||||
|
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap getBitmapLittle(Context context, String absolutePath) {
|
||||||
|
BitmapFactory.Options opt = new BitmapFactory.Options();
|
||||||
|
// 这个isjustdecodebounds很重要
|
||||||
|
opt.inJustDecodeBounds = true;
|
||||||
|
Bitmap bm = BitmapFactory.decodeFile(absolutePath, opt);
|
||||||
|
|
||||||
|
// 获取到这个图片的原始宽度和高度
|
||||||
|
int picWidth = opt.outWidth;
|
||||||
|
int picHeight = opt.outHeight;
|
||||||
|
|
||||||
|
// 获取屏的宽度和高度
|
||||||
|
WindowManager windowManager = ((Activity)context).getWindowManager();
|
||||||
|
Display display = windowManager.getDefaultDisplay();
|
||||||
|
int screenWidth = display.getWidth();
|
||||||
|
int screenHeight = display.getHeight();
|
||||||
|
|
||||||
|
// isSampleSize是表示对图片的缩放程度,比如值为2图片的宽度和高度都变为以前的1/2
|
||||||
|
opt.inSampleSize = 1;
|
||||||
|
// 根据屏的大小和图片大小计算出缩放比例
|
||||||
|
if (picWidth > picHeight) {
|
||||||
|
if (picWidth > screenWidth)
|
||||||
|
opt.inSampleSize = picWidth / screenWidth;
|
||||||
|
} else {
|
||||||
|
if (picHeight > screenHeight)
|
||||||
|
|
||||||
|
opt.inSampleSize = picHeight / screenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这次再真正地生成一个有像素的,经过缩放了的bitmap
|
||||||
|
opt.inJustDecodeBounds = false;
|
||||||
|
bm = BitmapFactory.decodeFile(absolutePath, opt);
|
||||||
|
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算压缩比例值
|
||||||
|
* @param options 解析图片的配置信息
|
||||||
|
* @param reqWidth 所需图片压缩尺寸最小宽度
|
||||||
|
* @param reqHeight 所需图片压缩尺寸最小高度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int calculateInSampleSize(BitmapFactory.Options options,
|
||||||
|
int reqWidth, int reqHeight) {
|
||||||
|
// 保存图片原宽高值
|
||||||
|
final int height = options. outHeight;
|
||||||
|
final int width = options. outWidth;
|
||||||
|
// 初始化压缩比例为1
|
||||||
|
int inSampleSize = 1;
|
||||||
|
|
||||||
|
// 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统
|
||||||
|
if (height > reqHeight || width > reqWidth) {
|
||||||
|
|
||||||
|
final int halfHeight = height / 2;
|
||||||
|
final int halfWidth = width / 2;
|
||||||
|
|
||||||
|
// 压缩比例值每次循环两倍增加,
|
||||||
|
// 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止
|
||||||
|
while ((halfHeight / inSampleSize) >= reqHeight
|
||||||
|
&& (halfWidth / inSampleSize) >= reqWidth) {
|
||||||
|
inSampleSize *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inSampleSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static void loadImage(int resid, String url, final ImageView imageView){
|
||||||
|
final String tmpUrl = url;
|
||||||
|
DisplayImageOptions options = new DisplayImageOptions.Builder()
|
||||||
|
.showImageOnLoading(resid)
|
||||||
|
.showImageForEmptyUri(resid)
|
||||||
|
.showImageOnFail(resid)
|
||||||
|
.cacheInMemory(true)
|
||||||
|
.cacheOnDisc(true)
|
||||||
|
.bitmapConfig(Bitmap.Config.ARGB_8888)
|
||||||
|
.build();
|
||||||
|
ImageLoader.getInstance().displayImage(tmpUrl, imageView, options,
|
||||||
|
new ImageLoadingListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadingStarted(String arg0, View arg1) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadingFailed(String arg0, View arg1,
|
||||||
|
FailReason arg2) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadingComplete(String arg0, View arg1,
|
||||||
|
Bitmap bmp) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
if (bmp == null)
|
||||||
|
return;
|
||||||
|
if( ((BaseZoomImageView)arg1).isDestroyed() ){
|
||||||
|
bmp.recycle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String path = ((PictureInfor)arg1.getTag()).mFilePath;
|
||||||
|
int degree = getDegree(path);
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (degree != 0 && bmp != null&&!bmp.isRecycled()) {
|
||||||
|
Matrix m = new Matrix();
|
||||||
|
m.setRotate(degree, (float) bmp.getWidth() / 2,(float) bmp.getHeight() / 2);
|
||||||
|
|
||||||
|
Bitmap b2 = Bitmap.createBitmap(bmp, 0, 0,
|
||||||
|
bmp.getWidth(), bmp.getHeight(), m, true);
|
||||||
|
if (bmp != b2) {
|
||||||
|
bmp.recycle();
|
||||||
|
bmp = b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
CMLog.writeLogtoFile("照片内存溢出", "异常", "创建缩略图异常:OutOfMemoryError");
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
((BaseZoomImageView)arg1).setImageBitmap(bmp);
|
||||||
|
((BaseZoomImageView)arg1).setImageDrawable(null);
|
||||||
|
if(new File(path).exists())
|
||||||
|
return;
|
||||||
|
saveBitmap(bmp, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadingCancelled(String arg0, View arg1) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
1264
app/src/main/java/com/navinfo/omqs/util/ImageTools.java
Normal file
1264
app/src/main/java/com/navinfo/omqs/util/ImageTools.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,9 +3,12 @@
|
|||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
<Button
|
|
||||||
android:id="@+id/button"
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/show_image"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/app_name" />
|
android:src="@drawable/icon_camera_img"
|
||||||
|
android:layout_gravity="center_horizontal"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
@ -1,8 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="fragment"
|
||||||
|
type="com.navinfo.omqs.ui.fragment.note.NoteFragment" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="com.navinfo.omqs.ui.fragment.note.NoteViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="@dimen/right_fragment_w"
|
android:layout_width="@dimen/right_fragment_w"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/shape_right_fragment_bg"
|
android:background="@drawable/shape_right_fragment_bg"
|
||||||
@ -221,4 +235,6 @@
|
|||||||
app:layout_constraintHorizontal_weight="1"
|
app:layout_constraintHorizontal_weight="1"
|
||||||
app:layout_constraintLeft_toRightOf="@id/note_camera"
|
app:layout_constraintLeft_toRightOf="@id/note_camera"
|
||||||
app:layout_constraintRight_toRightOf="parent" />
|
app:layout_constraintRight_toRightOf="parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</layout>
|
@ -74,6 +74,7 @@ dependencies {
|
|||||||
api 'androidx.constraintlayout:constraintlayout:2.1.4'
|
api 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
api 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
api 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
||||||
api 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
api 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||||
|
implementation files('libs\\universal-image-loader-1.9.3.jar')
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
|
BIN
collect-library/libs/universal-image-loader-1.9.3.jar
Normal file
BIN
collect-library/libs/universal-image-loader-1.9.3.jar
Normal file
Binary file not shown.
@ -11,4 +11,16 @@ open class NoteBean @JvmOverloads constructor(
|
|||||||
var description: String = "",
|
var description: String = "",
|
||||||
var taskId :Int = 0,
|
var taskId :Int = 0,
|
||||||
var list: RealmList<SketchAttachContent> = RealmList<SketchAttachContent>(),
|
var list: RealmList<SketchAttachContent> = RealmList<SketchAttachContent>(),
|
||||||
) : RealmObject()
|
var attachmentBeanList: RealmList<AttachmentBean> = RealmList<AttachmentBean>(),
|
||||||
|
) : RealmObject(){
|
||||||
|
fun copy(): NoteBean {
|
||||||
|
return NoteBean(
|
||||||
|
taskId = taskId,
|
||||||
|
id = id,
|
||||||
|
guideGeometry = guideGeometry,
|
||||||
|
description = description,
|
||||||
|
list = list,
|
||||||
|
attachmentBeanList = attachmentBeanList
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user