UI changes
This commit is contained in:
parent
6de6ef8bf8
commit
7f24f1cae1
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownSettings">
|
||||
<option name="previewPanelProviderInfo">
|
||||
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -45,6 +45,7 @@ dependencies {
|
|||
val cameraxVersion = "1.5.1"
|
||||
implementation("androidx.appcompat:appcompat:1.7.0")
|
||||
implementation("androidx.cardview:cardview:1.0.0")
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("androidx.camera:camera-core:$cameraxVersion")
|
||||
implementation("androidx.camera:camera-camera2:$cameraxVersion")
|
||||
implementation("androidx.camera:camera-lifecycle:$cameraxVersion")
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
|
@ -13,7 +16,8 @@
|
|||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.AnimalRating">
|
||||
android:theme="@style/Theme.AnimalRating"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
|
||||
<activity
|
||||
android:name=".HomeActivity"
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import androidx.camera.view.PreviewView
|
|||
import androidx.core.content.ContextCompat
|
||||
import com.example.animalrating.ml.CowAnalyzer
|
||||
import com.example.animalrating.ui.SilhouetteOverlay
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
|
|
@ -73,6 +74,10 @@ class CameraProcessor : AppCompatActivity(), CowAnalyzer.CowListener {
|
|||
segmentationOverlay = findViewById(R.id.segmentationOverlay)
|
||||
savedMaskOverlay = findViewById(R.id.savedMaskOverlay)
|
||||
|
||||
findViewById<MaterialButton>(R.id.btnExit).setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
frameProcessor = FrameProcessor()
|
||||
|
||||
val silhouetteId = intent.getIntExtra("SILHOUETTE_ID", 0)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,30 @@
|
|||
package com.example.animalrating
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.Button
|
||||
import android.widget.GridLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FileWriter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
|
@ -21,12 +33,57 @@ class CowSelectionActivity : AppCompatActivity() {
|
|||
|
||||
private var currentCowName: String? = null
|
||||
private lateinit var imagesContainer: LinearLayout
|
||||
private val storagePermissionCode = 101
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_cow_selection)
|
||||
|
||||
// Initialize StringProvider
|
||||
StringProvider.initialize(this)
|
||||
|
||||
// Set UI text from StringProvider
|
||||
findViewById<TextView>(R.id.tvToolbarTitle)?.text = StringProvider.getString("title_cow_selection")
|
||||
findViewById<TextView>(R.id.tvAddCowDetails)?.text = StringProvider.getString("title_add_cow_details")
|
||||
|
||||
findViewById<TextInputLayout>(R.id.tilSpecies)?.hint = StringProvider.getString("hint_species")
|
||||
findViewById<TextInputLayout>(R.id.tilBreed)?.hint = StringProvider.getString("hint_breed")
|
||||
findViewById<TextInputLayout>(R.id.tilAge)?.hint = StringProvider.getString("hint_age")
|
||||
findViewById<TextInputLayout>(R.id.tilMilk)?.hint = StringProvider.getString("hint_milk_yield")
|
||||
findViewById<TextInputLayout>(R.id.tilCalving)?.hint = StringProvider.getString("hint_calving_number")
|
||||
findViewById<TextInputLayout>(R.id.tilDescription)?.hint = StringProvider.getString("hint_description")
|
||||
|
||||
findViewById<TextView>(R.id.tvReproductiveStatus)?.text = StringProvider.getString("label_reproductive_status")
|
||||
findViewById<RadioButton>(R.id.rbPregnant)?.text = StringProvider.getString("radio_pregnant")
|
||||
findViewById<RadioButton>(R.id.rbCalved)?.text = StringProvider.getString("radio_calved")
|
||||
findViewById<RadioButton>(R.id.rbNone)?.text = StringProvider.getString("radio_none")
|
||||
|
||||
findViewById<TextView>(R.id.tvUploadPhotos)?.text = StringProvider.getString("label_upload_photos")
|
||||
findViewById<Button>(R.id.btnNewCow)?.text = StringProvider.getString("btn_save_profile")
|
||||
findViewById<Button>(R.id.btnCancel)?.text = StringProvider.getString("btn_cancel")
|
||||
|
||||
findViewById<TextView>(R.id.tvFrontView)?.text = StringProvider.getString("text_front_view")
|
||||
findViewById<TextView>(R.id.tvRearView)?.text = StringProvider.getString("text_rear_view")
|
||||
findViewById<TextView>(R.id.tvLeftSide)?.text = StringProvider.getString("text_left_side")
|
||||
findViewById<TextView>(R.id.tvRightSide)?.text = StringProvider.getString("text_right_side")
|
||||
findViewById<TextView>(R.id.tvAngleView)?.text = StringProvider.getString("text_angle_view")
|
||||
|
||||
// Setup Toolbar Navigation Click (Exit instead of Back)
|
||||
val toolbar = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
|
||||
// NOTE: The navigation icon is set in XML (@drawable/ic_back_arrow).
|
||||
// We handle the click here.
|
||||
toolbar.setNavigationOnClickListener {
|
||||
// Exit behavior: Finish this activity.
|
||||
// If "Exit" means close app, use finishAffinity() but user likely means exit this screen.
|
||||
// Given "except home activity", finish() goes back to home or previous screen.
|
||||
finish()
|
||||
}
|
||||
|
||||
initializeDefaultMasks()
|
||||
setupDropdowns()
|
||||
|
||||
imagesContainer = findViewById(R.id.currentCowImagesContainer)
|
||||
|
||||
|
|
@ -37,26 +94,38 @@ class CowSelectionActivity : AppCompatActivity() {
|
|||
generateNewCowName()
|
||||
}
|
||||
|
||||
// Try to load existing data if we are editing an existing cow
|
||||
if (intent.hasExtra("COW_NAME")) {
|
||||
loadCowDetails(currentCowName!!)
|
||||
}
|
||||
|
||||
updateCowNameDisplay()
|
||||
refreshCowImages()
|
||||
|
||||
findViewById<Button>(R.id.btnNewCow).setOnClickListener {
|
||||
generateNewCowName()
|
||||
updateCowNameDisplay()
|
||||
refreshCowImages()
|
||||
if (checkStoragePermissions()) {
|
||||
saveProfile()
|
||||
} else {
|
||||
requestStoragePermissions()
|
||||
}
|
||||
}
|
||||
|
||||
findViewById<Button>(R.id.btnCancel).setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
val buttons = mapOf(
|
||||
R.id.btnLeft to Pair(R.drawable.left, "left"),
|
||||
R.id.btnRight to Pair(R.drawable.right, "right"),
|
||||
R.id.btnTop to Pair(R.drawable.angle, "angle"), // Placeholder if no image yet
|
||||
R.id.btnTop to Pair(R.drawable.angle, "angle"),
|
||||
R.id.btnFront to Pair(R.drawable.front, "front"),
|
||||
R.id.btnBack to Pair(R.drawable.back, "back")
|
||||
)
|
||||
|
||||
buttons.forEach { (btnId, pair) ->
|
||||
val (drawableId, orientation) = pair
|
||||
findViewById<Button>(btnId).setOnClickListener {
|
||||
// Cast to View generic, as it is now a LinearLayout (clickable) in XML
|
||||
findViewById<View>(btnId).setOnClickListener {
|
||||
val intent = Intent(this, CameraProcessor::class.java)
|
||||
intent.putExtra("SILHOUETTE_ID", drawableId)
|
||||
intent.putExtra("COW_NAME", currentCowName)
|
||||
|
|
@ -66,6 +135,208 @@ class CowSelectionActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun checkStoragePermissions(): Boolean {
|
||||
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||
android.os.Environment.isExternalStorageManager()
|
||||
} else {
|
||||
val write = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
val read = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
write == PackageManager.PERMISSION_GRANTED && read == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestStoragePermissions() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||
try {
|
||||
val intent = Intent(android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
|
||||
val uri = android.net.Uri.fromParts("package", packageName, null)
|
||||
intent.data = uri
|
||||
startActivity(intent)
|
||||
} catch (_: Exception) {
|
||||
val intent = Intent(android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
|
||||
startActivity(intent)
|
||||
}
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE),
|
||||
storagePermissionCode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveProfile() {
|
||||
// Get displayed values
|
||||
val speciesDisplay = findViewById<AutoCompleteTextView>(R.id.spinnerSpecies).text.toString()
|
||||
val breedDisplay = findViewById<AutoCompleteTextView>(R.id.spinnerBreed).text.toString()
|
||||
|
||||
// Convert to English for storage if needed (using reverse lookup or StringProvider helper)
|
||||
// Assuming keys like "species_cow" map to "Cow" in English and something else in Hindi
|
||||
// We try to find the key for the displayed value, then get the English value for that key.
|
||||
// If not found (e.g. custom input), fallback to displayed value.
|
||||
|
||||
val speciesKey = StringProvider.getKeyForValue(speciesDisplay)
|
||||
val species = if (speciesKey != null) StringProvider.getStringEnglish(speciesKey) else speciesDisplay
|
||||
|
||||
val breedKey = StringProvider.getKeyForValue(breedDisplay)
|
||||
val breed = if (breedKey != null) StringProvider.getStringEnglish(breedKey) else breedDisplay
|
||||
|
||||
val ageInput = findViewById<TextInputEditText>(R.id.etAge).text.toString()
|
||||
val milkInput = findViewById<TextInputLayout>(R.id.tilMilk).editText?.text.toString()
|
||||
val calvingInput = findViewById<TextInputLayout>(R.id.tilCalving).editText?.text.toString()
|
||||
val descriptionInput = findViewById<TextInputLayout>(R.id.tilDescription).editText?.text.toString()
|
||||
|
||||
val rgReproductive = findViewById<RadioGroup>(R.id.rgReproductiveStatus)
|
||||
val reproductiveStatusKey = when(rgReproductive?.checkedRadioButtonId) {
|
||||
R.id.rbPregnant -> "radio_pregnant"
|
||||
R.id.rbCalved -> "radio_calved"
|
||||
R.id.rbNone -> "radio_none"
|
||||
else -> null
|
||||
}
|
||||
val reproductiveStatus = if (reproductiveStatusKey != null) StringProvider.getStringEnglish(reproductiveStatusKey) else ""
|
||||
|
||||
val csvHeader = "CowID,Species,Breed,Age,MilkYield,CalvingNumber,ReproductiveStatus,Description\n"
|
||||
val csvRow = "$currentCowName,$species,$breed,$ageInput,$milkInput,$calvingInput,$reproductiveStatus,$descriptionInput\n"
|
||||
|
||||
val csvFile = File(filesDir, "cow_profiles.csv")
|
||||
|
||||
try {
|
||||
val fileExists = csvFile.exists()
|
||||
val lines = if (fileExists) csvFile.readLines().toMutableList() else mutableListOf()
|
||||
|
||||
if (!fileExists) {
|
||||
lines.add(csvHeader.trim())
|
||||
}
|
||||
|
||||
// Check if we are updating
|
||||
val existingIndex = lines.indexOfFirst { it.startsWith("$currentCowName,") }
|
||||
|
||||
if (existingIndex != -1) {
|
||||
lines[existingIndex] = csvRow.trim()
|
||||
} else {
|
||||
lines.add(csvRow.trim())
|
||||
}
|
||||
|
||||
FileWriter(csvFile).use { writer ->
|
||||
lines.forEach { line ->
|
||||
writer.write(line + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
// Also export to public storage if needed
|
||||
saveCsvToPublicStorage(lines)
|
||||
|
||||
Toast.makeText(this, StringProvider.getString("toast_profile_saved"), Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(this, StringProvider.getString("toast_error_saving_profile") + " ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveCsvToPublicStorage(lines: List<String>) {
|
||||
// Saving to public Documents folder
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
if (android.os.Environment.isExternalStorageManager()) {
|
||||
val publicFile = File(android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOCUMENTS), "AnimalRating_Profiles.csv")
|
||||
FileWriter(publicFile).use { writer ->
|
||||
lines.forEach { line ->
|
||||
writer.write(line + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val publicFile = File(android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOCUMENTS), "AnimalRating_Profiles.csv")
|
||||
FileWriter(publicFile).use { writer ->
|
||||
lines.forEach { line ->
|
||||
writer.write(line + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCowDetails(cowId: String) {
|
||||
val csvFile = File(filesDir, "cow_profiles.csv")
|
||||
if (!csvFile.exists()) return
|
||||
|
||||
try {
|
||||
val lines = csvFile.readLines()
|
||||
// Removed unused header variable
|
||||
val record = lines.find { it.startsWith("$cowId,") }?.split(",") ?: return
|
||||
|
||||
// Simple mapping based on known order
|
||||
// CowID,Species,Breed,Age,MilkYield,CalvingNumber,ReproductiveStatus,Description
|
||||
if (record.size >= 8) {
|
||||
// Data is stored in English. Find key for English value, then get display string for that key.
|
||||
val storedSpecies = record[1]
|
||||
val speciesKey = StringProvider.getKeyForEnglishValue(storedSpecies)
|
||||
val displaySpecies = if (speciesKey != null) StringProvider.getString(speciesKey) else storedSpecies
|
||||
findViewById<AutoCompleteTextView>(R.id.spinnerSpecies).setText(displaySpecies, false)
|
||||
|
||||
val storedBreed = record[2]
|
||||
val breedKey = StringProvider.getKeyForEnglishValue(storedBreed)
|
||||
val displayBreed = if (breedKey != null) StringProvider.getString(breedKey) else storedBreed
|
||||
findViewById<AutoCompleteTextView>(R.id.spinnerBreed).setText(displayBreed, false)
|
||||
|
||||
findViewById<TextInputEditText>(R.id.etAge).setText(record[3])
|
||||
findViewById<TextInputLayout>(R.id.tilMilk).editText?.setText(record[4])
|
||||
findViewById<TextInputLayout>(R.id.tilCalving).editText?.setText(record[5])
|
||||
|
||||
val storedStatus = record[6]
|
||||
// Find which key matches this English value
|
||||
val statusKey = StringProvider.getKeyForEnglishValue(storedStatus)
|
||||
|
||||
// We need to check radio buttons.
|
||||
// Radio buttons text is set from StringProvider in onCreate.
|
||||
// So we need to find which RadioButton corresponds to 'statusKey'.
|
||||
|
||||
// "radio_pregnant" -> R.id.rbPregnant
|
||||
// "radio_calved" -> R.id.rbCalved
|
||||
// "radio_none" -> R.id.rbNone
|
||||
|
||||
when(statusKey) {
|
||||
"radio_pregnant" -> findViewById<RadioButton>(R.id.rbPregnant).isChecked = true
|
||||
"radio_calved" -> findViewById<RadioButton>(R.id.rbCalved).isChecked = true
|
||||
"radio_none" -> findViewById<RadioButton>(R.id.rbNone).isChecked = true
|
||||
// Fallback if stored directly as text or unknown key
|
||||
else -> {
|
||||
// If stored directly as English "Pregnant" etc.
|
||||
when (storedStatus) {
|
||||
"Pregnant" -> findViewById<RadioButton>(R.id.rbPregnant).isChecked = true
|
||||
"Calved" -> findViewById<RadioButton>(R.id.rbCalved).isChecked = true
|
||||
"None" -> findViewById<RadioButton>(R.id.rbNone).isChecked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findViewById<TextInputLayout>(R.id.tilDescription).editText?.setText(record[7])
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDropdowns() {
|
||||
val species = listOf(
|
||||
StringProvider.getString("species_cow"),
|
||||
StringProvider.getString("species_buffalo")
|
||||
)
|
||||
val speciesAdapter = ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, species)
|
||||
findViewById<AutoCompleteTextView>(R.id.spinnerSpecies).setAdapter(speciesAdapter)
|
||||
|
||||
val breeds = listOf(
|
||||
StringProvider.getString("breed_holstein"),
|
||||
StringProvider.getString("breed_jersey"),
|
||||
StringProvider.getString("breed_sahiwal"),
|
||||
StringProvider.getString("breed_gir"),
|
||||
StringProvider.getString("breed_red_sindhi"),
|
||||
StringProvider.getString("breed_murrah"),
|
||||
StringProvider.getString("breed_surti")
|
||||
)
|
||||
val breedAdapter = ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, breeds)
|
||||
findViewById<AutoCompleteTextView>(R.id.spinnerBreed).setAdapter(breedAdapter)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
refreshCowImages()
|
||||
|
|
@ -124,7 +395,8 @@ class CowSelectionActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun updateCowNameDisplay() {
|
||||
findViewById<TextView>(R.id.tvCowName).text = "Current Cow: $currentCowName"
|
||||
// Cow Name is now in Toolbar title if needed, but we hide title.
|
||||
// findViewById<TextView>(R.id.tvCowName).text = "Current Cow: $currentCowName"
|
||||
}
|
||||
|
||||
private fun refreshCowImages() {
|
||||
|
|
@ -148,63 +420,61 @@ class CowSelectionActivity : AppCompatActivity() {
|
|||
private fun addOrientationSection(orientationStr: String, files: List<File>) {
|
||||
// Orientation Header
|
||||
val orientationHeader = TextView(this).apply {
|
||||
text = orientationStr.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
val key = when(orientationStr.lowercase(Locale.getDefault())) {
|
||||
"front" -> "text_front_view"
|
||||
"back" -> "text_rear_view"
|
||||
"left" -> "text_left_side"
|
||||
"right" -> "text_right_side"
|
||||
"angle" -> "text_angle_view"
|
||||
else -> ""
|
||||
}
|
||||
val label = if (key.isNotEmpty()) StringProvider.getString(key) else orientationStr.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
text = label
|
||||
|
||||
textSize = 16f
|
||||
setTypeface(null, android.graphics.Typeface.BOLD)
|
||||
setPadding(16, 8, 0, 8)
|
||||
}
|
||||
imagesContainer.addView(orientationHeader)
|
||||
|
||||
// Images for this orientation
|
||||
files.forEach { file ->
|
||||
val imageRow = LinearLayout(this).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
// Grid for thumbnails
|
||||
val gridLayout = GridLayout(this).apply {
|
||||
columnCount = 3
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
200 // Smaller height for images
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
setMargins(16, 0, 0, 16)
|
||||
setMargins(16, 0, 16, 16)
|
||||
}
|
||||
}
|
||||
|
||||
val imageView = ImageView(this).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
0,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
1f
|
||||
)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
setImageBitmap(BitmapFactory.decodeFile(file.absolutePath))
|
||||
setOnClickListener {
|
||||
val intent = Intent(context, FullScreenImageActivity::class.java)
|
||||
// Images for this orientation
|
||||
files.forEach { file ->
|
||||
val thumbnailView = layoutInflater.inflate(R.layout.item_image_thumbnail, gridLayout, false)
|
||||
|
||||
val imageView = thumbnailView.findViewById<ImageView>(R.id.ivThumbnail)
|
||||
val deleteButton = thumbnailView.findViewById<View>(R.id.btnDelete)
|
||||
|
||||
imageView.setImageBitmap(BitmapFactory.decodeFile(file.absolutePath))
|
||||
|
||||
imageView.setOnClickListener {
|
||||
val intent = Intent(this@CowSelectionActivity, FullScreenImageActivity::class.java)
|
||||
intent.putExtra("IMAGE_PATH", file.absolutePath)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
val deleteButton = Button(this).apply {
|
||||
text = "Delete"
|
||||
textSize = 12f
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
setMargins(16,0,0,0)
|
||||
}
|
||||
setOnClickListener {
|
||||
deleteButton.setOnClickListener {
|
||||
if (file.delete()) {
|
||||
Toast.makeText(context, "Image deleted", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this@CowSelectionActivity, StringProvider.getString("toast_image_deleted"), Toast.LENGTH_SHORT).show()
|
||||
refreshCowImages()
|
||||
} else {
|
||||
Toast.makeText(context, "Error deleting image", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
Toast.makeText(this@CowSelectionActivity, StringProvider.getString("toast_error_deleting_image"), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
imageRow.addView(imageView)
|
||||
imageRow.addView(deleteButton)
|
||||
imagesContainer.addView(imageRow)
|
||||
gridLayout.addView(thumbnailView)
|
||||
}
|
||||
imagesContainer.addView(gridLayout)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
package com.example.animalrating
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Bundle
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
|
|
@ -20,7 +22,30 @@ class GalleryActivity : AppCompatActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_gallery)
|
||||
|
||||
// Initialize StringProvider
|
||||
StringProvider.initialize(this)
|
||||
|
||||
// Setup Back Button
|
||||
val toolbar = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
|
||||
// Set Toolbar title
|
||||
findViewById<TextView>(R.id.tvToolbarTitle)?.text = StringProvider.getString("title_gallery")
|
||||
|
||||
toolbar.setNavigationOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
container = findViewById(R.id.galleryContainer)
|
||||
|
||||
findViewById<FloatingActionButton>(R.id.fabAddCow).setOnClickListener {
|
||||
val intent = Intent(this, CowSelectionActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
refreshGallery()
|
||||
}
|
||||
|
||||
|
|
@ -35,12 +60,23 @@ class GalleryActivity : AppCompatActivity() {
|
|||
if (parts.size >= 2) "${parts[0]}_${parts[1]}" else "unknown"
|
||||
} ?: emptyMap()
|
||||
|
||||
val csvFile = File(filesDir, "cow_profiles.csv")
|
||||
val cowDetails = if (csvFile.exists()) {
|
||||
csvFile.readLines().associate { line ->
|
||||
val parts = line.split(",")
|
||||
if (parts.isNotEmpty()) parts[0] to parts else "" to emptyList()
|
||||
}
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
groupedFiles.forEach { (cowName, cowFiles) ->
|
||||
addCowSection(cowName, cowFiles)
|
||||
val details = cowDetails[cowName] ?: emptyList()
|
||||
addCowSection(cowName, cowFiles, details)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addCowSection(cowName: String, cowFiles: List<File>) {
|
||||
private fun addCowSection(cowName: String, cowFiles: List<File>, details: List<String>) {
|
||||
// Cow Name Header and Retake Button
|
||||
val headerLayout = LinearLayout(this).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
|
|
@ -53,8 +89,10 @@ class GalleryActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
val nameView = TextView(this).apply {
|
||||
text = cowName
|
||||
text = if (details.isNotEmpty()) "${StringProvider.getString("text_cow_id")} $cowName" else cowName
|
||||
textSize = 20f
|
||||
setTypeface(null, android.graphics.Typeface.BOLD)
|
||||
setTextColor(android.graphics.Color.parseColor("#3E2723"))
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
0,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
|
|
@ -62,10 +100,21 @@ class GalleryActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
val retakeButton = Button(this).apply {
|
||||
text = "Retake"
|
||||
val retakeButton = MaterialButton(this).apply {
|
||||
text = StringProvider.getString("btn_edit")
|
||||
textSize = 12f
|
||||
setTypeface(null, android.graphics.Typeface.BOLD)
|
||||
setTextColor(android.graphics.Color.parseColor("#5D4037"))
|
||||
cornerRadius = (12 * resources.displayMetrics.density).toInt()
|
||||
backgroundTintList = ColorStateList.valueOf(android.graphics.Color.parseColor("#EFEBE9"))
|
||||
strokeWidth = (1 * resources.displayMetrics.density).toInt()
|
||||
strokeColor = ColorStateList.valueOf(android.graphics.Color.parseColor("#5D4037"))
|
||||
minHeight = 0
|
||||
minimumHeight = 0
|
||||
setPadding(24, 20, 24, 20)
|
||||
|
||||
setOnClickListener {
|
||||
val intent = Intent(context, CowSelectionActivity::class.java)
|
||||
val intent = Intent(this@GalleryActivity, CowSelectionActivity::class.java)
|
||||
intent.putExtra("COW_NAME", cowName)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
|
@ -75,6 +124,48 @@ class GalleryActivity : AppCompatActivity() {
|
|||
headerLayout.addView(retakeButton)
|
||||
container.addView(headerLayout)
|
||||
|
||||
// Display details if available
|
||||
// Header: CowID,Species,Breed,Age,MilkYield,CalvingNumber,ReproductiveStatus,Description
|
||||
if (details.size >= 7) {
|
||||
val detailsLayout = LinearLayout(this).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
setMargins(0, 0, 0, 16)
|
||||
}
|
||||
setPadding(24, 24, 24, 24)
|
||||
background = android.graphics.drawable.GradientDrawable().apply {
|
||||
setColor(android.graphics.Color.parseColor("#FAFAFA"))
|
||||
cornerRadius = 16f
|
||||
setStroke(2, android.graphics.Color.parseColor("#EEEEEE"))
|
||||
}
|
||||
}
|
||||
|
||||
val infoText = StringBuilder()
|
||||
// Note: Values like "Cow", "Holstein" stored in CSV are currently displayed as is.
|
||||
// To translate stored values, we'd need a reverse lookup map or similar logic if the CSV stores English keys.
|
||||
// For now, we translate the labels.
|
||||
|
||||
infoText.append("${StringProvider.getString("label_species")} ${details.getOrElse(1) { "-" }} ")
|
||||
infoText.append("${StringProvider.getString("label_breed")} ${details.getOrElse(2) { "-" }}\n")
|
||||
infoText.append("${StringProvider.getString("label_age")} ${details.getOrElse(3) { "-" }} ${StringProvider.getString("unit_years")} ")
|
||||
infoText.append("${StringProvider.getString("label_milk_yield")} ${details.getOrElse(4) { "-" }} ${StringProvider.getString("unit_liters")}\n")
|
||||
infoText.append("${StringProvider.getString("label_calving_no")} ${details.getOrElse(5) { "-" }} ")
|
||||
infoText.append("${StringProvider.getString("label_status")} ${details.getOrElse(6) { "-" }}")
|
||||
|
||||
val detailsView = TextView(this).apply {
|
||||
text = infoText.toString()
|
||||
textSize = 14f
|
||||
setTextColor(android.graphics.Color.parseColor("#5D4037"))
|
||||
setLineSpacing(10f, 1f)
|
||||
}
|
||||
|
||||
detailsLayout.addView(detailsView)
|
||||
container.addView(detailsLayout)
|
||||
}
|
||||
|
||||
// Group files by orientation (e.g., left, right, etc.)
|
||||
val filesByOrientation = cowFiles.groupBy { file ->
|
||||
val parts = file.name.split("_")
|
||||
|
|
@ -101,63 +192,60 @@ class GalleryActivity : AppCompatActivity() {
|
|||
private fun addOrientationSection(orientationStr: String, files: List<File>) {
|
||||
// Orientation Header
|
||||
val orientationHeader = TextView(this).apply {
|
||||
text = orientationStr.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
val key = when(orientationStr.lowercase(Locale.getDefault())) {
|
||||
"front" -> "text_front_view"
|
||||
"back" -> "text_rear_view"
|
||||
"left" -> "text_left_side"
|
||||
"right" -> "text_right_side"
|
||||
"angle" -> "text_angle_view"
|
||||
else -> ""
|
||||
}
|
||||
val label = if (key.isNotEmpty()) StringProvider.getString(key) else orientationStr.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
text = label
|
||||
textSize = 16f
|
||||
setTypeface(null, android.graphics.Typeface.BOLD)
|
||||
setPadding(16, 8, 0, 8)
|
||||
}
|
||||
container.addView(orientationHeader)
|
||||
|
||||
// Images for this orientation
|
||||
files.forEach { file ->
|
||||
val imageRow = LinearLayout(this).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
// Grid for thumbnails
|
||||
val gridLayout = android.widget.GridLayout(this).apply {
|
||||
columnCount = 3
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
200
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
setMargins(32, 0, 0, 16)
|
||||
setMargins(16, 0, 16, 16)
|
||||
}
|
||||
}
|
||||
|
||||
val imageView = ImageView(this).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
0,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
1f
|
||||
)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
setImageBitmap(BitmapFactory.decodeFile(file.absolutePath))
|
||||
setOnClickListener {
|
||||
val intent = Intent(context, FullScreenImageActivity::class.java)
|
||||
// Images for this orientation
|
||||
files.forEach { file ->
|
||||
val thumbnailView = layoutInflater.inflate(R.layout.item_image_thumbnail, gridLayout, false)
|
||||
|
||||
val imageView = thumbnailView.findViewById<ImageView>(R.id.ivThumbnail)
|
||||
val deleteButton = thumbnailView.findViewById<android.view.View>(R.id.btnDelete)
|
||||
|
||||
imageView.setImageBitmap(BitmapFactory.decodeFile(file.absolutePath))
|
||||
|
||||
imageView.setOnClickListener {
|
||||
val intent = Intent(this@GalleryActivity, FullScreenImageActivity::class.java)
|
||||
intent.putExtra("IMAGE_PATH", file.absolutePath)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
val deleteButton = Button(this).apply {
|
||||
text = "Delete"
|
||||
textSize = 12f
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
setMargins(16,0,0,0)
|
||||
}
|
||||
setOnClickListener {
|
||||
deleteButton.setOnClickListener {
|
||||
if (file.delete()) {
|
||||
Toast.makeText(context, "Image deleted", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this@GalleryActivity, StringProvider.getString("toast_image_deleted"), Toast.LENGTH_SHORT).show()
|
||||
refreshGallery()
|
||||
} else {
|
||||
Toast.makeText(context, "Error deleting image", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
Toast.makeText(this@GalleryActivity, StringProvider.getString("toast_error_deleting_image"), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
imageRow.addView(imageView)
|
||||
imageRow.addView(deleteButton)
|
||||
container.addView(imageRow)
|
||||
gridLayout.addView(thumbnailView)
|
||||
}
|
||||
container.addView(gridLayout)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,21 @@
|
|||
package com.example.animalrating
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.button.MaterialButton
|
||||
|
||||
class HomeActivity : AppCompatActivity() {
|
||||
|
||||
|
|
@ -15,22 +23,103 @@ class HomeActivity : AppCompatActivity() {
|
|||
const val ALGORITHM_HAMMING = "Hamming Distance"
|
||||
const val ALGORITHM_EUCLIDEAN = "Euclidean Distance"
|
||||
const val ALGORITHM_JACCARD = "Jaccard Similarity"
|
||||
private const val PERMISSION_REQUEST_CODE = 101
|
||||
private const val PREF_COW_ILLUSTRATION_INDEX = "COW_ILLUSTRATION_INDEX"
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_home)
|
||||
|
||||
StringProvider.initialize(this)
|
||||
|
||||
setupUI()
|
||||
checkAndRequestPermissions()
|
||||
}
|
||||
|
||||
private fun checkAndRequestPermissions() {
|
||||
val permissions = mutableListOf<String>()
|
||||
|
||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(android.Manifest.permission.CAMERA)
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(android.Manifest.permission.READ_MEDIA_IMAGES)
|
||||
}
|
||||
} else {
|
||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (permissions.isNotEmpty()) {
|
||||
ActivityCompat.requestPermissions(this, permissions.toTypedArray(), PERMISSION_REQUEST_CODE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUI() {
|
||||
// Language Spinner
|
||||
val languageSpinner = findViewById<Spinner>(R.id.spinnerLanguage)
|
||||
val languages = StringProvider.getLanguages()
|
||||
val languageAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, languages)
|
||||
languageAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
languageSpinner.adapter = languageAdapter
|
||||
|
||||
val prefs = getSharedPreferences("AnimalRatingPrefs", MODE_PRIVATE)
|
||||
val savedLang = prefs.getString("LANGUAGE", "English")
|
||||
languageSpinner.setSelection(languages.indexOf(savedLang))
|
||||
|
||||
languageSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
val selectedLanguage = languages[position]
|
||||
val currentLang = prefs.getString("LANGUAGE", "English")
|
||||
|
||||
// Only update and recreate if language actually changed
|
||||
if (selectedLanguage != currentLang) {
|
||||
saveSettings() // Save UI state so it's not lost
|
||||
StringProvider.setLanguage(selectedLanguage, this@HomeActivity)
|
||||
// Post recreate to avoid WindowLeaked (allows spinner popup to close)
|
||||
android.os.Handler(android.os.Looper.getMainLooper()).post {
|
||||
recreate()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
|
||||
// Set text from StringProvider
|
||||
findViewById<TextView>(R.id.tvTitle).text = StringProvider.getString("title_home")
|
||||
findViewById<MaterialButton>(R.id.btnViewGallery).text = StringProvider.getString("btn_view_gallery")
|
||||
findViewById<MaterialButton>(R.id.btnSelectCow).text = StringProvider.getString("btn_select_cow")
|
||||
findViewById<TextView>(R.id.tvAlgorithmLabel).text = StringProvider.getString("label_algorithm")
|
||||
findViewById<TextView>(R.id.tvThresholdLabel).text = StringProvider.getString("label_match_threshold")
|
||||
|
||||
// Cow Illustration and Logic
|
||||
val ivCowIllustration = findViewById<ImageView>(R.id.ivCowIllustration)
|
||||
val savedIndex = prefs.getInt(PREF_COW_ILLUSTRATION_INDEX, 0)
|
||||
setCowIllustration(ivCowIllustration, savedIndex)
|
||||
|
||||
ivCowIllustration.setOnClickListener { view ->
|
||||
showIllustrationPopup(view, ivCowIllustration)
|
||||
}
|
||||
|
||||
// Navigation buttons
|
||||
findViewById<Button>(R.id.btnViewGallery).setOnClickListener {
|
||||
findViewById<MaterialButton>(R.id.btnViewGallery).setOnClickListener {
|
||||
startActivity(Intent(this, GalleryActivity::class.java))
|
||||
}
|
||||
|
||||
findViewById<Button>(R.id.btnSelectCow).setOnClickListener {
|
||||
findViewById<MaterialButton>(R.id.btnSelectCow).setOnClickListener {
|
||||
saveSettingsAndStart()
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +131,6 @@ class HomeActivity : AppCompatActivity() {
|
|||
spinner.adapter = adapter
|
||||
|
||||
// Set default selection from preferences or intent
|
||||
val prefs = getSharedPreferences("AnimalRatingPrefs", MODE_PRIVATE)
|
||||
val savedAlg = prefs.getString("ALGORITHM", ALGORITHM_HAMMING)
|
||||
spinner.setSelection(algorithms.indexOf(savedAlg))
|
||||
|
||||
|
|
@ -63,11 +151,54 @@ class HomeActivity : AppCompatActivity() {
|
|||
})
|
||||
}
|
||||
|
||||
private fun saveSettingsAndStart() {
|
||||
private fun showIllustrationPopup(anchor: View, imageView: ImageView) {
|
||||
val popup = PopupMenu(this, anchor)
|
||||
for (i in 0..4) {
|
||||
popup.menu.add(0, i, i, "Illustration $i")
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
val index = item.itemId
|
||||
setCowIllustration(imageView, index)
|
||||
|
||||
// Save preference
|
||||
getSharedPreferences("AnimalRatingPrefs", MODE_PRIVATE).edit()
|
||||
.putInt(PREF_COW_ILLUSTRATION_INDEX, index)
|
||||
.apply()
|
||||
true
|
||||
}
|
||||
popup.show()
|
||||
}
|
||||
|
||||
private fun setCowIllustration(imageView: ImageView, index: Int) {
|
||||
// Map index to drawable resource
|
||||
// We assume resources are named cow_illustration (for index 0 or default) or similar logic if strictly named
|
||||
// But user said "cow_illustration_{n}, where n=0,1,2,3,4"
|
||||
// However, currently we likely only have 'cow_illustration' in drawable from previous step, or user implies they exist.
|
||||
// We will try to find resources dynamically.
|
||||
|
||||
val resName = "cow_illustration_$index"
|
||||
val resId = resources.getIdentifier(resName, "drawable", packageName)
|
||||
|
||||
if (resId != 0) {
|
||||
imageView.setImageResource(resId)
|
||||
} else {
|
||||
// Fallback to default if specific one not found
|
||||
if (index == 0) {
|
||||
// Maybe it's just "cow_illustration" without suffix if n=0 is base?
|
||||
// Or user provided 5 distinct files. We try 'cow_illustration' as fallback.
|
||||
val defaultId = resources.getIdentifier("cow_illustration", "drawable", packageName)
|
||||
if (defaultId != 0) imageView.setImageResource(defaultId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSettings() {
|
||||
val spinner = findViewById<Spinner>(R.id.spinnerAlgorithm)
|
||||
val seekBar = findViewById<SeekBar>(R.id.seekBarThreshold)
|
||||
|
||||
val selectedAlgorithm = spinner.selectedItem.toString()
|
||||
if (spinner != null && seekBar != null) {
|
||||
val selectedAlgorithm = spinner.selectedItem?.toString() ?: ALGORITHM_HAMMING
|
||||
val threshold = seekBar.progress
|
||||
|
||||
// Save to preferences
|
||||
|
|
@ -77,7 +208,11 @@ class HomeActivity : AppCompatActivity() {
|
|||
putInt("THRESHOLD", threshold)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSettingsAndStart() {
|
||||
saveSettings()
|
||||
startActivity(Intent(this, CowSelectionActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package com.example.animalrating
|
||||
|
||||
import android.content.Context
|
||||
import org.json.JSONObject
|
||||
import java.io.InputStream
|
||||
|
||||
object StringProvider {
|
||||
|
||||
private var stringData: JSONObject? = null
|
||||
private var currentLanguage = "English"
|
||||
private const val DEFAULT_LANGUAGE = "English"
|
||||
|
||||
fun initialize(context: Context) {
|
||||
if (stringData == null) {
|
||||
try {
|
||||
val inputStream: InputStream = context.resources.openRawResource(R.raw.strings)
|
||||
val jsonString = inputStream.bufferedReader().use { it.readText() }
|
||||
stringData = JSONObject(jsonString)
|
||||
|
||||
// Load saved language
|
||||
val prefs = context.getSharedPreferences("AnimalRatingPrefs", Context.MODE_PRIVATE)
|
||||
currentLanguage = prefs.getString("LANGUAGE", DEFAULT_LANGUAGE) ?: DEFAULT_LANGUAGE
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
// Handle error, maybe load default strings or log
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setLanguage(language: String, context: Context) {
|
||||
currentLanguage = language
|
||||
// Save selected language
|
||||
val prefs = context.getSharedPreferences("AnimalRatingPrefs", Context.MODE_PRIVATE)
|
||||
prefs.edit().putString("LANGUAGE", language).apply()
|
||||
}
|
||||
|
||||
fun getLanguages(): List<String> {
|
||||
return stringData?.keys()?.asSequence()?.toList() ?: listOf(DEFAULT_LANGUAGE)
|
||||
}
|
||||
|
||||
fun getString(key: String): String {
|
||||
return getStringForLanguage(key, currentLanguage)
|
||||
}
|
||||
|
||||
fun getStringEnglish(key: String): String {
|
||||
return getStringForLanguage(key, DEFAULT_LANGUAGE)
|
||||
}
|
||||
|
||||
private fun getStringForLanguage(key: String, language: String): String {
|
||||
return try {
|
||||
stringData?.getJSONObject(language)?.getString(key) ?: ""
|
||||
} catch (e: Exception) {
|
||||
// Fallback to English if key not found in current language
|
||||
try {
|
||||
if (language != DEFAULT_LANGUAGE) {
|
||||
stringData?.getJSONObject(DEFAULT_LANGUAGE)?.getString(key) ?: ""
|
||||
} else {
|
||||
""
|
||||
}
|
||||
} catch (e2: Exception) {
|
||||
"" // Return empty if not found anywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getKeyForValue(value: String): String? {
|
||||
// Helper to find the key for a given localized value in current language
|
||||
// This is expensive, but useful if we need to reverse lookup
|
||||
val langData = stringData?.optJSONObject(currentLanguage) ?: return null
|
||||
val keys = langData.keys()
|
||||
while (keys.hasNext()) {
|
||||
val key = keys.next()
|
||||
if (langData.getString(key) == value) {
|
||||
return key
|
||||
}
|
||||
}
|
||||
// Also check English just in case it was stored as English
|
||||
val englishData = stringData?.optJSONObject(DEFAULT_LANGUAGE) ?: return null
|
||||
val engKeys = englishData.keys()
|
||||
while (engKeys.hasNext()) {
|
||||
val key = engKeys.next()
|
||||
if (englishData.getString(key) == value) {
|
||||
return key
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getKeyForEnglishValue(value: String): String? {
|
||||
val englishData = stringData?.optJSONObject(DEFAULT_LANGUAGE) ?: return null
|
||||
val engKeys = englishData.keys()
|
||||
while (engKeys.hasNext()) {
|
||||
val key = engKeys.next()
|
||||
if (englishData.getString(key) == value) {
|
||||
return key
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#EFEBE9" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 337 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 616 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 157 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8l8,8l1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="40dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="40"
|
||||
android:viewportHeight="40">
|
||||
|
||||
<!-- Circle Background -->
|
||||
<path
|
||||
android:fillColor="#EFEBE9"
|
||||
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"/>
|
||||
|
||||
<!-- Arrow Icon (Centered and Scaled) -->
|
||||
<group
|
||||
android:scaleX="1.0"
|
||||
android:scaleY="1.0"
|
||||
android:translateX="8.0"
|
||||
android:translateY="8.0">
|
||||
<path
|
||||
android:fillColor="#5D4037"
|
||||
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8l8,8l1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</group>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#EFEBE9" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
|
|
@ -1,56 +1,224 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5">
|
||||
android:orientation="vertical"
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="#FFFFFF"
|
||||
app:navigationIcon="@drawable/ic_round_back_button">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvToolbarTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Cow Selection"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"/>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
android:padding="24dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
<TextView
|
||||
android:id="@+id/tvAddCowDetails"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Add Cow Details"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"
|
||||
android:layout_marginBottom="24dp"/>
|
||||
|
||||
<!-- Form Fields -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilSpecies"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeColor="#6D4C41"
|
||||
android:hint="Species">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/spinnerSpecies"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilBreed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeColor="#6D4C41"
|
||||
android:hint="Breed">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/spinnerBreed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilAge"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeColor="#6D4C41"
|
||||
android:hint="Age (Years)">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etAge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilMilk"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeColor="#6D4C41"
|
||||
android:hint="Milk Yield (L)">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberDecimal"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilCalving"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeColor="#6D4C41"
|
||||
android:hint="Calving Number">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvReproductiveStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Reproductive Status"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rgReproductiveStatus"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbPregnant"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Pregnant"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbCalved"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Calved"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbNone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="None"/>
|
||||
</RadioGroup>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="4dp"
|
||||
app:contentPadding="16dp">
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeColor="#6D4C41"
|
||||
android:hint="Description">
|
||||
|
||||
<LinearLayout
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="3"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Upload Photos -->
|
||||
<TextView
|
||||
android:id="@+id/tvCowName"
|
||||
android:id="@+id/tvUploadPhotos"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#333333"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnNewCow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Capture New Cow"
|
||||
android:backgroundTint="#2196F3"
|
||||
android:textColor="#FFFFFF"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Select Orientation"
|
||||
android:textSize="20sp"
|
||||
android:text="Upload Photos"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<GridLayout
|
||||
|
|
@ -60,74 +228,224 @@
|
|||
android:rowCount="3"
|
||||
android:alignmentMode="alignMargins"
|
||||
android:columnOrderPreserved="false"
|
||||
android:layout_marginBottom="32dp">
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<!-- Left -->
|
||||
<Button
|
||||
android:id="@+id/btnLeft"
|
||||
<!-- Front View -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="100dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:text="Left"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="#FF5722"
|
||||
android:textColor="#FFFFFF"/>
|
||||
|
||||
<!-- Right -->
|
||||
<Button
|
||||
android:id="@+id/btnRight"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:text="Right"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="#FF5722"
|
||||
android:textColor="#FFFFFF"/>
|
||||
|
||||
<!-- Front -->
|
||||
<Button
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
<LinearLayout
|
||||
android:id="@+id/btnFront"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#F5F5F5"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
app:tint="#5D4037"/>
|
||||
<TextView
|
||||
android:id="@+id/tvFrontView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:text="Front"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="#FF5722"
|
||||
android:textColor="#FFFFFF"/>
|
||||
android:text="Front View"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Back -->
|
||||
<Button
|
||||
<!-- Rear View (Back) -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
<LinearLayout
|
||||
android:id="@+id/btnBack"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#F5F5F5"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
app:tint="#5D4037"/>
|
||||
<TextView
|
||||
android:id="@+id/tvRearView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:text="Back"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="#FF5722"
|
||||
android:textColor="#FFFFFF"/>
|
||||
android:text="Rear View"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Top (Centered in last row) -->
|
||||
<Button
|
||||
android:id="@+id/btnTop"
|
||||
<!-- Left Side -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="100dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
<LinearLayout
|
||||
android:id="@+id/btnLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#F5F5F5"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
app:tint="#5D4037"/>
|
||||
<TextView
|
||||
android:id="@+id/tvLeftSide"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Left Side"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Right Side -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
<LinearLayout
|
||||
android:id="@+id/btnRight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#F5F5F5"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
app:tint="#5D4037"/>
|
||||
<TextView
|
||||
android:id="@+id/tvRightSide"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Right Side"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Angle View -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_gravity="fill_horizontal"
|
||||
android:layout_columnSpan="2"
|
||||
android:text="Angle"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="#FF5722"
|
||||
android:textColor="#FFFFFF"/>
|
||||
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
<LinearLayout
|
||||
android:id="@+id/btnTop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#F5F5F5"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
app:tint="#5D4037"/>
|
||||
<TextView
|
||||
android:id="@+id/tvAngleView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Angle View"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</GridLayout>
|
||||
|
||||
<!-- Container for displaying current cow's images -->
|
||||
<!-- Container for showing captured thumbnails -->
|
||||
<LinearLayout
|
||||
android:id="@+id/currentCowImagesContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"/>
|
||||
android:layout_marginBottom="24dp"/>
|
||||
|
||||
<!-- Bottom Buttons -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnNewCow"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Save Profile"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="12dp"
|
||||
app:backgroundTint="#6D4C41"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Cancel"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#5D4037"
|
||||
app:cornerRadius="12dp"
|
||||
app:backgroundTint="#EFEBE9"
|
||||
app:strokeColor="#5D4037"
|
||||
app:strokeWidth="1dp"
|
||||
android:layout_marginStart="8dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Hidden TextView for Cow Name logic compatibility -->
|
||||
<TextView
|
||||
android:id="@+id/tvCowName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#000000">
|
||||
|
|
@ -12,13 +13,16 @@
|
|||
android:scaleType="fitCenter"
|
||||
android:contentDescription="Full Screen Image" />
|
||||
|
||||
<Button
|
||||
<ImageButton
|
||||
android:id="@+id/btnBack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="Back" />
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_round_back_button"
|
||||
android:background="@android:color/transparent"
|
||||
android:scaleType="centerInside"
|
||||
android:contentDescription="Back" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
@ -1,26 +1,101 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#FFFFFF"
|
||||
app:elevation="0dp">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="#FFFFFF"
|
||||
app:navigationIcon="@drawable/ic_round_back_button">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Saved Cow Profiles"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"/>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:boxBackgroundColor="#F5F5F5"
|
||||
app:boxCornerRadiusTopStart="24dp"
|
||||
app:boxCornerRadiusTopEnd="24dp"
|
||||
app:boxCornerRadiusBottomStart="24dp"
|
||||
app:boxCornerRadiusBottomEnd="24dp"
|
||||
app:boxStrokeWidth="0dp"
|
||||
app:startIconDrawable="@android:drawable/ic_menu_search"
|
||||
app:startIconTint="#8D6E63"
|
||||
android:hint="Search profiles...">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginStart="12dp"
|
||||
app:icon="@android:drawable/ic_menu_sort_by_size"
|
||||
app:iconTint="#5D4037"
|
||||
app:backgroundTint="#EFEBE9"
|
||||
app:cornerRadius="12dp"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/galleryContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
android:padding="16dp"/>
|
||||
|
||||
<TextView
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabAddCow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Captured Images"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#333333"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="24dp"/>
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="24dp"
|
||||
app:srcCompat="@android:drawable/ic_input_add"
|
||||
app:tint="#FFFFFF"
|
||||
app:backgroundTint="#6D4C41"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -1,84 +1,187 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:background="#F5F5F5">
|
||||
android:background="#F7F7F7"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<!-- Language Selection (Top Right) -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerLanguage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Animal Rating"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#333333"
|
||||
android:layout_marginBottom="32dp"/>
|
||||
android:padding="8dp"
|
||||
android:background="@drawable/bg_spinner_rounded"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Cow Illustration - Circular Logo -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="180dp"
|
||||
app:cardCornerRadius="90dp"
|
||||
app:cardElevation="8dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivCowIllustration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:src="@drawable/cow_illustration_0"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="Cow Illustration"/>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Cow Data Collector"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<!-- Subtitle -->
|
||||
<TextView
|
||||
android:id="@+id/tvSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Record and manage cow information easily."
|
||||
android:textSize="16sp"
|
||||
android:textColor="#6D4C41"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginBottom="40dp"/>
|
||||
|
||||
<!-- Main Buttons Container -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="32dp">
|
||||
|
||||
<!-- Add New Cow Profile Button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnSelectCow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:text="Add New Cow Profile"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="16dp"
|
||||
app:backgroundTint="#6D4C41"
|
||||
app:icon="@android:drawable/ic_input_add"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="12dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:elevation="4dp"/>
|
||||
|
||||
<!-- View Saved Profiles Button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnViewGallery"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:text="View Saved Profiles"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#5D4037"
|
||||
app:cornerRadius="16dp"
|
||||
app:backgroundTint="#EFEBE9"
|
||||
app:strokeColor="#5D4037"
|
||||
app:strokeWidth="1dp"
|
||||
app:icon="@android:drawable/ic_menu_gallery"
|
||||
app:iconTint="#5D4037"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="12dp"
|
||||
android:elevation="4dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Settings Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="4dp"
|
||||
app:contentPadding="16dp">
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Settings"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Algorithm Selection -->
|
||||
<TextView
|
||||
android:id="@+id/tvAlgorithmLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Algorithm"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#5D4037"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_spinner_rounded"
|
||||
android:padding="4dp"
|
||||
android:layout_marginBottom="20dp">
|
||||
<Spinner
|
||||
android:id="@+id/spinnerAlgorithm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"/>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- Threshold Slider -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Algorithm:"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerAlgorithm"
|
||||
android:id="@+id/tvThresholdLabel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Threshold: "/>
|
||||
android:layout_weight="1"
|
||||
android:text="Match Threshold"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#5D4037"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvThresholdValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="75%"/>
|
||||
android:text="75%"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#3E2723"/>
|
||||
</LinearLayout>
|
||||
|
||||
<SeekBar
|
||||
|
|
@ -86,37 +189,10 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="100"
|
||||
android:progress="75"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Start New Rating"
|
||||
android:textSize="18sp"
|
||||
android:textColor="#666666"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSelectCow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Select Cow"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:backgroundTint="#FF5722"
|
||||
android:textColor="#FFFFFF"/>
|
||||
android:progressTint="#6D4C41"
|
||||
android:thumbTint="#6D4C41"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnViewGallery"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="View Collected Images"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:backgroundTint="#2196F3"
|
||||
android:textColor="#FFFFFF"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
|
@ -29,4 +30,25 @@
|
|||
android:alpha="0.9"
|
||||
android:elevation="10dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnExit"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="top|start"
|
||||
android:layout_margin="16dp"
|
||||
style="@style/Widget.MaterialComponents.Button.Icon"
|
||||
app:icon="@drawable/ic_back_arrow"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="#FFFFFF"
|
||||
app:backgroundTint="#80000000"
|
||||
app:cornerRadius="24dp"
|
||||
android:padding="0dp"
|
||||
android:insetLeft="0dp"
|
||||
android:insetTop="0dp"
|
||||
android:insetRight="0dp"
|
||||
android:insetBottom="0dp"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp"
|
||||
android:gravity="center"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?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"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivThumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="#E0E0E0"/>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnDelete"
|
||||
style="@style/Widget.MaterialComponents.Button.Icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="top|end"
|
||||
android:layout_margin="4dp"
|
||||
app:icon="@android:drawable/ic_delete"
|
||||
app:iconSize="14dp"
|
||||
app:iconTint="#FFFFFF"
|
||||
android:backgroundTint="#C62828"
|
||||
app:cornerRadius="12dp"
|
||||
android:padding="0dp"
|
||||
android:insetLeft="0dp"
|
||||
android:insetTop="0dp"
|
||||
android:insetRight="0dp"
|
||||
android:insetBottom="0dp"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp"
|
||||
android:gravity="center"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
{
|
||||
"English": {
|
||||
"app_name": "Animal Rating",
|
||||
"title_home": "Animal Rating",
|
||||
"title_gallery": "Saved Cow Profiles",
|
||||
"title_add_cow_details": "Add Cow Details",
|
||||
"title_cow_selection": "Cow Selection",
|
||||
"btn_view_gallery": "View Saved Cow Profiles",
|
||||
"btn_select_cow": "Select a Cow",
|
||||
"label_algorithm": "Algorithm",
|
||||
"label_match_threshold": "Match Threshold",
|
||||
"btn_edit": "Edit",
|
||||
"hint_search_profiles": "Search profiles...",
|
||||
"toast_image_deleted": "Image deleted",
|
||||
"toast_error_deleting_image": "Error deleting image",
|
||||
"text_cow_id": "Cow ID:",
|
||||
"label_species": "Species:",
|
||||
"label_breed": "Breed:",
|
||||
"label_age": "Age:",
|
||||
"unit_years": "years",
|
||||
"label_milk_yield": "Milk Yield:",
|
||||
"unit_liters": "L",
|
||||
"label_calving_no": "Calving #:",
|
||||
"label_status": "Status:",
|
||||
"hint_species": "Species",
|
||||
"hint_breed": "Breed",
|
||||
"hint_age": "Age (Years)",
|
||||
"hint_milk_yield": "Milk Yield (L)",
|
||||
"hint_calving_number": "Calving Number",
|
||||
"label_reproductive_status": "Reproductive Status",
|
||||
"radio_pregnant": "Pregnant",
|
||||
"radio_calved": "Calved",
|
||||
"radio_none": "None",
|
||||
"hint_description": "Description",
|
||||
"label_upload_photos": "Upload Photos",
|
||||
"text_front_view": "Front View",
|
||||
"text_rear_view": "Rear View",
|
||||
"text_left_side": "Left Side",
|
||||
"text_right_side": "Right Side",
|
||||
"text_angle_view": "Angle View",
|
||||
"btn_save_profile": "Save Profile",
|
||||
"btn_cancel": "Cancel",
|
||||
"toast_profile_saved": "Profile Saved!",
|
||||
"toast_error_saving_profile": "Error saving profile:",
|
||||
"toast_capture_failed": "Photo capture failed",
|
||||
"toast_saved_as": "Saved as",
|
||||
"toast_error_saving_image": "Error saving image",
|
||||
"content_desc_back": "Back",
|
||||
"content_desc_full_screen_image": "Full Screen Image",
|
||||
"species_cow": "Cow",
|
||||
"species_buffalo": "Buffalo",
|
||||
"breed_holstein": "Holstein Friesian",
|
||||
"breed_jersey": "Jersey",
|
||||
"breed_sahiwal": "Sahiwal",
|
||||
"breed_gir": "Gir",
|
||||
"breed_red_sindhi": "Red Sindhi",
|
||||
"breed_murrah": "Murrah",
|
||||
"breed_surti": "Surti"
|
||||
},
|
||||
"Hindi": {
|
||||
"app_name": "पशु रेटिंग",
|
||||
"title_home": "पशु रेटिंग",
|
||||
"title_gallery": "सहेजे गए गाय प्रोफाइल",
|
||||
"title_add_cow_details": "गाय का विवरण जोड़ें",
|
||||
"title_cow_selection": "गाय का चयन",
|
||||
"btn_view_gallery": "सहेजे गए प्रोफाइल देखें",
|
||||
"btn_select_cow": "एक गाय का चयन करें",
|
||||
"label_algorithm": "एल्गोरिदम",
|
||||
"label_match_threshold": "मैच थ्रेसहोल्ड",
|
||||
"btn_edit": "संपादित करें",
|
||||
"hint_search_profiles": "प्रोफ़ाइल खोजें...",
|
||||
"toast_image_deleted": "छवि हटा दी गई",
|
||||
"toast_error_deleting_image": "छवि हटाने में त्रुटि",
|
||||
"text_cow_id": "गाय आईडी:",
|
||||
"label_species": "प्रजाति:",
|
||||
"label_breed": "नस्ल:",
|
||||
"label_age": "आयु:",
|
||||
"unit_years": "वर्ष",
|
||||
"label_milk_yield": "दूध की उपज:",
|
||||
"unit_liters": "L",
|
||||
"label_calving_no": "बछड़ों की संख्या:",
|
||||
"label_status": "स्थिति:",
|
||||
"hint_species": "प्रजाति",
|
||||
"hint_breed": "नस्ल",
|
||||
"hint_age": "आयु (वर्ष)",
|
||||
"hint_milk_yield": "दूध की उपज (L)",
|
||||
"hint_calving_number": "बछड़ों की संख्या",
|
||||
"label_reproductive_status": "प्रजनन स्थिति",
|
||||
"radio_pregnant": "गर्भवती",
|
||||
"radio_calved": "बछड़ा हुआ",
|
||||
"radio_none": "कोई नहीं",
|
||||
"hint_description": "विवरण",
|
||||
"label_upload_photos": "तस्वीरें अपलोड करें",
|
||||
"text_front_view": "सामने का दृश्य",
|
||||
"text_rear_view": "पीछे का दृश्य",
|
||||
"text_left_side": "बाईं ओर",
|
||||
"text_right_side": "दाईं ओर",
|
||||
"text_angle_view": "कोणीय दृश्य",
|
||||
"btn_save_profile": "प्रोफ़ाइल सहेजें",
|
||||
"btn_cancel": "रद्द करें",
|
||||
"toast_profile_saved": "प्रोफ़ाइल सहेजा गया!",
|
||||
"toast_error_saving_profile": "प्रोफ़ाइल सहेजने में त्रुटि:",
|
||||
"toast_capture_failed": "फोटो कैप्चर विफल",
|
||||
"toast_saved_as": "के रूप में सहेजा गया",
|
||||
"toast_error_saving_image": "छवि सहेजने में त्रुटि",
|
||||
"content_desc_back": "वापस",
|
||||
"content_desc_full_screen_image": "पूर्ण स्क्रीन छवि",
|
||||
"species_cow": "गाय",
|
||||
"species_buffalo": "भैंस",
|
||||
"breed_holstein": "होल्सटीन फ्राइज़ियन",
|
||||
"breed_jersey": "जर्सी",
|
||||
"breed_sahiwal": "साहिवाल",
|
||||
"breed_gir": "गिर",
|
||||
"breed_red_sindhi": "लाल सिंधी",
|
||||
"breed_murrah": "मुर्रा",
|
||||
"breed_surti": "सुरती"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.AnimalRating" parent="Theme.AppCompat.Light.NoActionBar" />
|
||||
<style name="Theme.AnimalRating" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">#6D4C41</item>
|
||||
<item name="colorPrimaryVariant">#5D4037</item>
|
||||
<item name="colorOnPrimary">#FFFFFF</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">#FF5722</item>
|
||||
<item name="colorSecondaryVariant">#E64A19</item>
|
||||
<item name="colorOnSecondary">#FFFFFF</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1 @@
|
|||
Adobe Stock - https://stock.adobe.com/
|
||||
Loading…
Reference in New Issue