From c7c466b7f73320b8601dfcde4b058a644ddbc77b Mon Sep 17 00:00:00 2001 From: Rifqi222 <mrifki193@gmail.com> Date: Thu, 28 Mar 2024 21:31:20 +0700 Subject: [PATCH] add: add scan init --- .../java/com/pbd/psi/ui/scan/ScanFragment.kt | 186 ++++++++++++++---- .../java/com/pbd/psi/ui/scan/ScanViewModel.kt | 13 ++ app/src/main/res/drawable/scan_button.png | Bin 0 -> 10675 bytes .../main/res/layout-land/fragment_twibbon.xml | 4 +- app/src/main/res/layout/activity_scan.xml | 27 +++ app/src/main/res/layout/dialog_scan.xml | 41 ++++ app/src/main/res/layout/fragment_scan.xml | 21 +- app/src/main/res/layout/fragment_twibbon.xml | 4 +- 8 files changed, 249 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/com/pbd/psi/ui/scan/ScanViewModel.kt create mode 100644 app/src/main/res/drawable/scan_button.png create mode 100644 app/src/main/res/layout/activity_scan.xml create mode 100644 app/src/main/res/layout/dialog_scan.xml diff --git a/app/src/main/java/com/pbd/psi/ui/scan/ScanFragment.kt b/app/src/main/java/com/pbd/psi/ui/scan/ScanFragment.kt index f5166de..f34f6ec 100644 --- a/app/src/main/java/com/pbd/psi/ui/scan/ScanFragment.kt +++ b/app/src/main/java/com/pbd/psi/ui/scan/ScanFragment.kt @@ -1,60 +1,162 @@ package com.pbd.psi.ui.scan +import android.Manifest +import android.app.Activity +import android.app.AlertDialog +import android.content.Intent +import android.graphics.BitmapFactory +import android.graphics.drawable.BitmapDrawable +import android.net.Uri import android.os.Bundle -import androidx.fragment.app.Fragment +import android.os.Handler +import android.os.Looper +import android.provider.MediaStore +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.pbd.psi.R - -// TODO: Rename parameter arguments, choose names that match -// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER -private const val ARG_PARAM1 = "param1" -private const val ARG_PARAM2 = "param2" - -/** - * A simple [Fragment] subclass. - * Use the [ScanFragment.newInstance] factory method to - * create an instance of this fragment. - */ +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.camera.core.CameraSelector +import androidx.camera.core.ImageCapture +import androidx.camera.core.Preview +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import com.pbd.psi.databinding.FragmentScanBinding + class ScanFragment : Fragment() { - // TODO: Rename and change types of parameters - private var param1: String? = null - private var param2: String? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - arguments?.let { - param1 = it.getString(ARG_PARAM1) - param2 = it.getString(ARG_PARAM2) + + private var _binding: FragmentScanBinding? = null + private val binding get() = _binding!! + + private var imageCapture: ImageCapture? = null + + private var previewFrozen: Boolean = false + private var cameraProvider: ProcessCameraProvider? = null + + private val filePickerLauncher = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val selectedImageUri = result.data?.data + selectedImageUri?.let { uri -> + loadSelectedImage(uri) + } } } override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, + inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_scan, container, false) + ): View { + _binding = FragmentScanBinding.inflate(inflater, container, false) + val root: View = binding.root + + val permissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted -> + if (isGranted) { + startCamera() + } + } + + permissionLauncher.launch(Manifest.permission.CAMERA) + + imageCapture = ImageCapture.Builder().build() + + binding.scanButton?.setOnClickListener { + previewMask() + } + + binding.uploadImage?.setOnClickListener{ + openFileExplorer() + } + + return root + } + + private fun startCamera() { + val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext()) + cameraProviderFuture.addListener({ + + cameraProvider = cameraProviderFuture.get() + + val preview = Preview.Builder().build().also { + mPreview -> + if (!previewFrozen) { + mPreview.setSurfaceProvider(binding.scanView?.surfaceProvider) + } else { + mPreview.setSurfaceProvider(null) + } + } + + imageCapture = ImageCapture.Builder().build() + + val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA + + try { + cameraProvider?.unbindAll() + cameraProvider?.bindToLifecycle(this, cameraSelector, preview!!) + } catch (e: Exception) { + Log.d("CameraX", "startCamera Failed:", e) + } + }, ContextCompat.getMainExecutor(requireContext())) + } + + private fun previewMask() { + binding.scanButton?.isEnabled = false + previewFrozen = !previewFrozen + startCamera() + + Handler(Looper.getMainLooper()).postDelayed({ + // TO DO: Add modal + val builder: AlertDialog.Builder = AlertDialog.Builder(context) + builder + .setMessage("Do you want to retake the picture?") + .setPositiveButton("Yes") { dialog, which -> + dialog.dismiss() + binding.scanButton?.isEnabled = true + previewFrozen = !previewFrozen + startCamera() + } + .setNegativeButton("No") { dialog, which -> + // TO DO : send a froze preview to the server as img form data + dialog.dismiss() + } + + val dialog: AlertDialog = builder.create() + dialog.show() + }, 1000) + } + + private fun openFileExplorer() { + val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + filePickerLauncher.launch(intent) } - companion object { - /** - * Use this factory method to create a new instance of - * this fragment using the provided parameters. - * - * @param param1 Parameter 1. - * @param param2 Parameter 2. - * @return A new instance of fragment ScanFragment. - */ - // TODO: Rename and change types and number of parameters - @JvmStatic - fun newInstance(param1: String, param2: String) = - ScanFragment().apply { - arguments = Bundle().apply { - putString(ARG_PARAM1, param1) - putString(ARG_PARAM2, param2) + private fun loadSelectedImage(uri: Uri) { + try { + requireContext().contentResolver.openInputStream(uri)?.use { inputStream -> + val bitmap = BitmapFactory.decodeStream(inputStream) + if (bitmap != null) { + val drawable = BitmapDrawable(resources, bitmap) + binding.scanView?.background = drawable + } else { + Toast.makeText(requireContext(), "Failed to decode image", Toast.LENGTH_SHORT).show() + Log.e("ScanFragment", "Failed to decode image") } } + } catch (e: Exception) { + Toast.makeText(requireContext(), "Failed to load image", Toast.LENGTH_SHORT).show() + Log.e("ScanFragment", "Failed to load image", e) + } + } + + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } } \ No newline at end of file diff --git a/app/src/main/java/com/pbd/psi/ui/scan/ScanViewModel.kt b/app/src/main/java/com/pbd/psi/ui/scan/ScanViewModel.kt new file mode 100644 index 0000000..3fb5128 --- /dev/null +++ b/app/src/main/java/com/pbd/psi/ui/scan/ScanViewModel.kt @@ -0,0 +1,13 @@ +package com.pbd.psi.ui.twibbon + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class ScanViewModel : ViewModel() { + + private val _text = MutableLiveData<String>().apply { + value = "This is Scan Fragment" + } + val text: LiveData<String> = _text +} \ No newline at end of file diff --git a/app/src/main/res/drawable/scan_button.png b/app/src/main/res/drawable/scan_button.png new file mode 100644 index 0000000000000000000000000000000000000000..f3a65e62f1681264fc21b5a5ac2a2bfce2b3548d GIT binary patch literal 10675 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout-land/fragment_twibbon.xml b/app/src/main/res/layout-land/fragment_twibbon.xml index c00eeb4..4e4ec75 100644 --- a/app/src/main/res/layout-land/fragment_twibbon.xml +++ b/app/src/main/res/layout-land/fragment_twibbon.xml @@ -64,7 +64,7 @@ android:background="@drawable/capture_button" android:layout_marginTop="10dp" android:layout_marginLeft="40dp" - android:layout_width="142dip" + android:layout_width="159dip" android:layout_height="52dip" android:contentDescription="@string/capture" app:layout_constraintEnd_toStartOf="@id/changeButton" @@ -78,7 +78,7 @@ android:background="@drawable/change_button" android:layout_marginTop="10dp" android:layout_marginRight="40dp" - android:layout_width="142dip" + android:layout_width="159dip" android:layout_height="52dip" android:contentDescription="@string/change" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/activity_scan.xml b/app/src/main/res/layout/activity_scan.xml new file mode 100644 index 0000000..40df589 --- /dev/null +++ b/app/src/main/res/layout/activity_scan.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/payment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingTop="0dp" + tools:context=".ScanActivity"> + + <FrameLayout + android:id="@+id/placeholderPayment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginStart="0dp" + android:layout_marginEnd="0dp" + android:background="?android:attr/windowBackground" + app:itemBackground="@color/primaryDarkest" + app:itemIconTint="@color/white" + app:itemTextColor="@color/white" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent"> + </FrameLayout> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_scan.xml b/app/src/main/res/layout/dialog_scan.xml new file mode 100644 index 0000000..30de4c2 --- /dev/null +++ b/app/src/main/res/layout/dialog_scan.xml @@ -0,0 +1,41 @@ +<!-- res/layout/dialog_retake_image.xml --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp" + android:id="@+id/dialog_scan"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Do you want to retake the image?" + android:textSize="18sp" + android:textColor="@android:color/black" + android:layout_gravity="center_horizontal"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="16dp"> + + <Button + android:id="@+id/btnRetake" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Retake" + android:textColor="@android:color/white" + android:background="@color/primaryDarkest"/> + + <Button + android:id="@+id/btnUse" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Use" + android:textColor="@android:color/white" + android:background="@color/primaryDarkest"/> + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/fragment_scan.xml b/app/src/main/res/layout/fragment_scan.xml index bab875d..4c64d8b 100644 --- a/app/src/main/res/layout/fragment_scan.xml +++ b/app/src/main/res/layout/fragment_scan.xml @@ -52,6 +52,19 @@ android:layout_width="50dip" android:layout_height="50dip" android:contentDescription="@string/upload_image" + app:layout_constraintStart_toEndOf="@id/scan_button" + app:layout_constraintTop_toBottomOf="@+id/guideline"/> + + <ImageButton + android:id="@+id/scan_button" + android:layout_marginVertical="20dp" + android:layout_marginStart="10dp" + android:fontFamily="@font/montserrat" + android:gravity="center_horizontal" + android:background="@drawable/scan_button" + android:layout_width="50dip" + android:layout_height="50dip" + android:contentDescription="@string/upload_image" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/guideline"/> @@ -78,7 +91,13 @@ app:layout_constraintBottom_toTopOf="@+id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/scan_header" /> + app:layout_constraintTop_toBottomOf="@+id/scan_header"> + + <androidx.camera.view.PreviewView + android:id="@+id/scan_view" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + </FrameLayout> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_twibbon.xml b/app/src/main/res/layout/fragment_twibbon.xml index 975295f..3adadb3 100644 --- a/app/src/main/res/layout/fragment_twibbon.xml +++ b/app/src/main/res/layout/fragment_twibbon.xml @@ -66,7 +66,7 @@ android:gravity="center_horizontal" android:background="@drawable/capture_button" android:layout_marginTop="10dp" - android:layout_width="142dip" + android:layout_width="159dip" android:layout_height="52dip" android:contentDescription="@string/capture" app:layout_constraintEnd_toStartOf="@id/changeButton" @@ -79,7 +79,7 @@ android:gravity="center_horizontal" android:background="@drawable/change_button" android:layout_marginTop="10dp" - android:layout_width="142dip" + android:layout_width="159dip" android:layout_height="52dip" android:contentDescription="@string/change" app:layout_constraintEnd_toEndOf="parent" -- GitLab