Fullscreen view of pictures

This commit is contained in:
leca 2024-10-01 17:54:23 +03:00
parent 743c74b2f2
commit 23549344d4
12 changed files with 178 additions and 33 deletions

View File

@ -1,15 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> android:name="android.hardware.camera"
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> android:required="true"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:authorities="org.foxarmy.barcodescannerforemployees.providers"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
@ -17,11 +23,17 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.BarcodeScannerForEmployees" android:theme="@style/Theme.BarcodeScannerForEmployees"
android:authorities="org.foxarmy.barcodescannerforemployees.providers"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".FullscreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="false"
android:label="@string/title_activity_fullscreen"
android:theme="@style/Theme.BarcodeScannerForEmployees.Fullscreen"/>
<provider <provider
android:authorities="com.google.firebase.components.MainActivity.provider"
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="com.google.firebase.components.MainActivity.provider;com.google.firebase.components.FullscreenActivity.provider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">
<meta-data <meta-data
@ -30,16 +42,19 @@
</provider> </provider>
<meta-data <meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES" android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="barcode_ui" > android:value="barcode_ui">
</meta-data> </meta-data>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:theme="@style/Theme.BarcodeScannerForEmployees"> android:theme="@style/Theme.BarcodeScannerForEmployees">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
</manifest> </manifest>

View File

@ -2,10 +2,15 @@ package org.foxarmy.barcodescannerforemployees
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat.startActivity
import java.io.File import java.io.File
class AbstractProductView: LinearLayout { class AbstractProductView: LinearLayout {
@ -15,7 +20,7 @@ class AbstractProductView: LinearLayout {
private var categoryField: TextView private var categoryField: TextView
private var unitField: TextView private var unitField: TextView
constructor(activity: Activity, context: Context, productImageFile: String, productName: String, netWeight: Double, category: Int) : super(context) { constructor(activity: Activity, context: Context, productImageHash: String, productName: String, netWeight: Double, category: Int) : super(context) {
val inflater:LayoutInflater = activity.layoutInflater val inflater:LayoutInflater = activity.layoutInflater
inflater.inflate(R.layout.abstract_product_view, this) inflater.inflate(R.layout.abstract_product_view, this)
@ -26,14 +31,31 @@ class AbstractProductView: LinearLayout {
categoryField = findViewById(R.id.categoryView) categoryField = findViewById(R.id.categoryView)
unitField = findViewById(R.id.unitView) unitField = findViewById(R.id.unitView)
val picturesDir = File(context.filesDir, "pictures") val thumbnailsDir = File(context.cacheDir, "thumbnails")
picturesDir.mkdirs() thumbnailsDir.mkdirs()
val imageUri = getImageUri(activity, File(picturesDir, productImageFile)) val imageUri = getImageUri(activity, File(thumbnailsDir, "$productImageHash.webp"))
Log.d("QWERTYUIOP", "${productPicture.minimumWidth}x${productPicture.minimumHeight}")
productPicture.setImageURI(imageUri) productPicture.setImageURI(imageUri)
productPicture.rotation = 90f
productPicture.setOnClickListener {
Log.d("QWERTYUIOP", productImageHash)
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
val extras = Bundle()
extras.putString("imagehash", productImageHash)
fullscreenIntent.putExtras(extras)
startActivity(context, fullscreenIntent, extras)
}
productNameField.text = productName productNameField.text = productName
netWeightField.text = netWeight.toString() netWeightField.text = netWeight.toString()
//TODO: category and units //TODO: category and units
findViewById<ConstraintLayout>(R.id.productLayout).setOnClickListener {
Log.d("QWERTYUIOP", "Clicked layout")
} }
}
} }

View File

@ -1,6 +1,8 @@
package org.foxarmy.barcodescannerforemployees package org.foxarmy.barcodescannerforemployees
import android.content.ContentValues import android.content.ContentValues
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@ -10,6 +12,7 @@ import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.graphics.scale
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.barcode.common.Barcode
@ -17,6 +20,7 @@ import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
import org.foxarmy.barcodescannerforemployees.databinding.AddProductFragmentBinding import org.foxarmy.barcodescannerforemployees.databinding.AddProductFragmentBinding
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
@ -40,12 +44,20 @@ class AddProductFragment : Fragment() {
return binding.root return binding.root
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.R)
val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean -> val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean ->
if (success) { if (success) {
//Move picture to a proper directory according to its calculated hash //Move picture to a proper directory according to its calculated hash
val tempfile = File(requireContext().filesDir, "image.png") val tempfile = File(requireContext().filesDir, "image.png")
val imageHash = tempfile.inputStream().readBytes().toString(Charsets.UTF_8).md5() val imageContent = tempfile.inputStream().readBytes()
val imageHash = imageContent.toString(Charsets.UTF_8).md5()
val thumbnailsDir = File(requireContext().cacheDir, "thumbnails")
thumbnailsDir.mkdirs()
val thumbnailFile = File(thumbnailsDir, "$imageHash.webp")
var img = BitmapFactory.decodeByteArray(imageContent, 0, imageContent.size)
img = img.scale(img.width/4,img.height/4)
img.compress(Bitmap.CompressFormat.WEBP_LOSSY, 25, FileOutputStream(thumbnailFile))
pictureFile = File(picturesPath, "$imageHash.png") pictureFile = File(picturesPath, "$imageHash.png")
Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING) Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
tempfile.delete() tempfile.delete()
@ -56,7 +68,7 @@ class AddProductFragment : Fragment() {
} }
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.R)
fun getPicture () { fun getPicture () {
//Saving picture to a temp file for further hash calculation and moving to a proper directory //Saving picture to a temp file for further hash calculation and moving to a proper directory
val imageFile = File(requireContext().filesDir, "image.png") val imageFile = File(requireContext().filesDir, "image.png")
@ -67,7 +79,7 @@ class AddProductFragment : Fragment() {
takePicture.launch(imageUri) takePicture.launch(imageUri)
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.R)
val requestPermissionLauncher = val requestPermissionLauncher =
registerForActivityResult( registerForActivityResult(
ActivityResultContracts.RequestPermission() ActivityResultContracts.RequestPermission()
@ -104,7 +116,7 @@ class AddProductFragment : Fragment() {
val values = ContentValues().apply { val values = ContentValues().apply {
put(ProductContract.ProductEntry.PRODUCT_NAME, productName) put(ProductContract.ProductEntry.PRODUCT_NAME, productName)
put(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString()) put(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString())
put(ProductContract.ProductEntry.IMAGE_FILENAME, pictureFile.name) put(ProductContract.ProductEntry.IMAGE_FILENAME, pictureFile.nameWithoutExtension)
} }
db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values) db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values)

View File

@ -0,0 +1,43 @@
package org.foxarmy.barcodescannerforemployees
import android.app.Activity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.ImageView
import android.widget.LinearLayout
import org.foxarmy.barcodescannerforemployees.databinding.ActivityFullscreenBinding
import java.io.File
class FullscreenActivity : Activity() {
private lateinit var binding: ActivityFullscreenBinding
private lateinit var fullscreenImageView: ImageView
private lateinit var fullscreenContentControls: LinearLayout
private val hideHandler = Handler(Looper.myLooper()!!)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fullscreen)
fullscreenImageView = findViewById(R.id.fullscreenImageView)
val extras = intent.extras
val imageHash = extras!!.get("imagehash") as String? //extras!!.getParcelable<Parcelable>("imagehash") as String?
val picturesDir = File(filesDir, "pictures")
picturesDir.mkdirs()
Log.d("QWERTYUIOP", imageHash.toString())
val fullscreenImageFile = File(picturesDir, "$imageHash.png")
// crash. change activity
fullscreenImageView.setImageURI(getImageUri(this, fullscreenImageFile))
fullscreenImageView.setOnClickListener {
this.finish()
}
}
}

View File

@ -2,6 +2,7 @@ package org.foxarmy.barcodescannerforemployees
import android.os.Bundle import android.os.Bundle
import android.provider.BaseColumns import android.provider.BaseColumns
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -39,18 +40,22 @@ class StorageFragment : Fragment() {
while(moveToNext()) { while(moveToNext()) {
val productName = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NAME)) val productName = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NAME))
val netWeight = getDouble(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT)) val netWeight = getDouble(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT))
val pictureFilename = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME)) val productImageHash = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME))
getView()?.findViewById<GridLayout>(R.id.contentGridLayout)?.addView(
AbstractProductView( val abstractProduct = AbstractProductView(
requireActivity(), requireActivity(),
requireContext(), requireContext(),
productImageFile = pictureFilename, productImageHash,
productName = productName, productName,
netWeight = netWeight, netWeight,
category = 1 1
)
) )
getView()?.findViewById<GridLayout>(R.id.contentGridLayout)?.addView(abstractProduct)
abstractProduct.setOnClickListener {
Log.d("QWERTYUIOP", "Clicked view")
}
// getView()?.findViewById<GridView>(R.id.contentGridLayout)? // getView()?.findViewById<GridView>(R.id.contentGridLayout)?
} }
} }

View File

@ -2,14 +2,15 @@
xmlns:android="http://schemas.android.com/apk/res/android" 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" android:layout_width="200dp" xmlns:tools="http://schemas.android.com/tools" android:layout_width="200dp"
android:layout_height="200dp"> android:layout_height="wrap_content" app:barrierMargin="1dp" android:clickable="false">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:id="@+id/productLayout" android:outlineProvider="bounds"> android:layout_height="wrap_content" android:id="@+id/productLayout" android:outlineProvider="bounds"
android:background="#00FFFEFE" android:clickable="true">
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="100dp" app:srcCompat="@android:drawable/ic_btn_speak_now" android:layout_height="200dp" app:srcCompat="@android:drawable/ic_btn_speak_now"
android:id="@+id/productPicture" android:id="@+id/productPicture"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
@ -19,8 +20,8 @@
android:layout_height="wrap_content" android:id="@+id/productNameView" android:layout_height="wrap_content" android:id="@+id/productNameView"
app:layout_constraintTop_toBottomOf="@+id/productPicture" app:layout_constraintTop_toBottomOf="@+id/productPicture"
android:layout_marginTop="15dp" app:layout_constraintStart_toStartOf="parent" android:layout_marginTop="15dp" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="25dp" android:fontFamily="monospace" android:textSize="20sp" android:fontFamily="monospace" android:textSize="20sp"
android:maxLines="2"/> android:maxLines="2" android:layout_marginStart="10dp"/>
<TextView <TextView
android:text="@string/sample_product_net_weight" android:text="@string/sample_product_net_weight"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -42,7 +43,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/categoryView" android:layout_height="wrap_content" android:id="@+id/categoryView"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="20dp" android:fontFamily="monospace" android:textSize="10sp" android:layout_marginEnd="25dp" android:fontFamily="monospace" android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="20dp"/> app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="20dp"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:theme="@style/ThemeOverlay.BarcodeScannerForEmployees.FullscreenContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".FullscreenActivity">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent" app:srcCompat="@android:drawable/alert_dark_frame"
android:id="@+id/fullscreenImageView" android:contentDescription="@string/fullscreen_image"/>
</FrameLayout>

View File

@ -4,4 +4,6 @@
<!-- Customize your dark theme here. --> <!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> --> <!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style> </style>
<style name="ThemeOverlay.BarcodeScannerForEmployees.FullscreenContainer" parent="">
</style>
</resources> </resources>

View File

@ -6,4 +6,8 @@
<color name="light_blue_600">#FF039BE5</color> <color name="light_blue_600">#FF039BE5</color>
<color name="gray_400">#FFBDBDBD</color> <color name="gray_400">#FFBDBDBD</color>
<color name="gray_600">#FF757575</color> <color name="gray_600">#FF757575</color>
<color name="light_blue_900">#FF01579B</color>
<color name="light_blue_A200">#FF40C4FF</color>
<color name="light_blue_A400">#FF00B0FF</color>
<color name="black_overlay">#66000000</color>
</resources> </resources>

View File

@ -17,4 +17,8 @@
<string name="sample_product_net_weight">1998</string> <string name="sample_product_net_weight">1998</string>
<string name="sample_unit">g</string> <string name="sample_unit">g</string>
<string name="sample_category">Sample category</string> <string name="sample_category">Sample category</string>
<string name="title_activity_fullscreen">FullscreenActivity</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="fullscreen_image">Fullscreen image</string>
</resources> </resources>

View File

@ -3,4 +3,12 @@
<item name="android:background">@color/gray_400</item> <item name="android:background">@color/gray_400</item>
<item name="exampleColor">@color/light_blue_400</item> <item name="exampleColor">@color/light_blue_400</item>
</style> </style>
<style name="Widget.Theme.BarcodeScannerForEmployees.ActionBar.Fullscreen" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<style name="Widget.Theme.BarcodeScannerForEmployees.ButtonBar.Fullscreen" parent="">
<item name="android:background">@color/black_overlay</item>
<item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item>
</style>
</resources> </resources>

View File

@ -6,4 +6,12 @@
</style> </style>
<style name="Theme.BarcodeScannerForEmployees" parent="Base.Theme.BarcodeScannerForEmployees"/> <style name="Theme.BarcodeScannerForEmployees" parent="Base.Theme.BarcodeScannerForEmployees"/>
<style name="Theme.BarcodeScannerForEmployees.Fullscreen" parent="Theme.BarcodeScannerForEmployees">
<item name="android:actionBarStyle">@style/Widget.Theme.BarcodeScannerForEmployees.ActionBar.Fullscreen</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
</style>
<style name="ThemeOverlay.BarcodeScannerForEmployees.FullscreenContainer" parent="">
</style>
</resources> </resources>