The FoodDetailsFragment
is a core component designed to display detailed information about a selected food item, including its name, icon, calories, macronutrients, and a list of micronutrients. Users can adjust serving sizes and quantities to view nutrient values accordingly.
The primary components in FoodDetailsFragment
include:
Food Item Information : Displays the name, icon, and serving size details.
Serving Size Selector : Allows users to select a preferred serving size or unit.
Nutritional Information : Shows calorie count and macronutrient breakdown (Carbs, Protein, Fat).
Micronutrient List : Provides detailed nutrient information for vitamins, minerals, and other nutrients.
PassioFoodItem
The PassioFoodItem
model is the foundation of food details and includes the following properties:
Unique identifier for the food item.
Reference code for the item.
Description/details of the food.
ID for loading the food icon.
Serving size and unit info.
List of ingredients in the food.
Example:
The food item name, icon, and details are rendered using PassioFoodItem
's properties.
Copy kotlinCopy codebinding.tvFoodName.text = foodItem.name
binding.foodIcon. loadPassioIcon (foodItem.iconId)
PassioFoodAmount
This model defines possible serving sizes and units. PassioFoodAmount
includes:
Available serving sizes for the food
Units available for the food item
Example:
The servingSizes
property is used to populate the RecyclerView adapter ServingSizeAdapter
, allowing users to select different serving sizes.
PassioServingSize
and PassioServingUnit
These classes are components of PassioFoodAmount
that define the quantity and units for serving sizes:
PassioServingSize
PassioServingUnit
Linked to the PassioServingSize
Weight in grams or other units
Setting Serving Size Quantity
The setQuantityAndUnit
function allows users to specify a desired serving quantity and unit, updating the displayed nutrient values dynamically.
Copy foodItem. setQuantityAndUnit (quantity, foodItem.amount.selectedUnit)
FoodDetailsFragment.kt
Copy package com.passioai.quickstart.ui.details
import ai.passio.passiosdk.passiofood.data.model.PassioFoodItem
import ai.passio.passiosdk.passiofood.data.model.PassioServingSize
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.KeyEvent
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import com.passioai.quickstart.databinding.FragmentFoodDetailsBinding
import com.passioai.quickstart.ui.details.MicroNutrient.Companion.getMicroNutrients
import com.passioai.quickstart.util.loadPassioIcon
import com.passioai.quickstart.util.twoDecimal
class FoodDetailsFragment : Fragment () {
private lateinit var _binding: FragmentFoodDetailsBinding
private val binding get () = _binding
private val foodItem = passioFoodItem?. copy ()
companion object {
private var passioFoodItem: PassioFoodItem ? = null
fun setPassioFoodItem (passioFoodItem: PassioFoodItem ) {
this .passioFoodItem = passioFoodItem
}
}
override fun onCreateView (
inflater: LayoutInflater , container: ViewGroup ?,
savedInstanceState: Bundle ?
): View {
_binding = FragmentFoodDetailsBinding. inflate (inflater, container, false )
return binding.root
}
override fun onViewCreated (view: View , savedInstanceState: Bundle ?) {
super . onViewCreated (view, savedInstanceState)
if (foodItem == null )
return
with (binding)
{
servingQty. setOnEditorActionListener { _, actionId, event ->
// Check if the action is "done" or if the action is triggered by the keyboard
if (actionId == EditorInfo.IME_ACTION_DONE ||
(event != null && event.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN)
) {
// Handle the done action here
try {
val quantity = servingQty.text. toString (). toDouble ()
foodItem. setQuantityAndUnit (
quantity,
foodItem.amount.selectedUnit
)
showFoodDetails ()
} catch (e: Exception ) {
e. printStackTrace ()
}
// You can do something with inputText, like showing a Toast
// Optionally clear the text
true // Return true to indicate the action was handled
} else {
false // Return false to indicate the action was not handled
}
}
rvServingSizes.adapter =
ServingSizeAdapter (
foodItem.amount.servingSizes,
foodItem.amount.selectedUnit,
:: onServingSizeSelected
)
}
showFoodDetails ()
}
private fun onServingSizeSelected (passioServingSize: PassioServingSize ) {
foodItem?. setQuantityAndUnit (passioServingSize.quantity, passioServingSize.unitName)
showFoodDetails ()
}
@SuppressLint ( "SetTextI18n" )
private fun showFoodDetails () {
if (foodItem == null ) return
val passioNutrients = foodItem. nutrientsSelectedSize ()
with (binding)
{
tvFoodName.text = foodItem.name
servingSizeValue.text = "( ${ foodItem.amount. weightGrams () } g)"
servingQty. setText (foodItem.amount.selectedQuantity. toString ())
foodIcon. loadPassioIcon (foodItem.iconId)
tvCaloriesVal.text =
" ${ passioNutrients. calories ()?. value ?. twoDecimal () } ${ passioNutrients. calories ()?.unit?.symbol } "
tvCarbsVal.text = " ${ passioNutrients. carbs ()?. gramsValue ()?. twoDecimal () } g"
tvProteinVal.text = " ${ passioNutrients. protein ()?. gramsValue ()?. twoDecimal () } g"
tvFatVal.text = " ${ passioNutrients. fat ()?. gramsValue ()?. twoDecimal () } g"
rvNutrients.adapter = NutrientsAdapter (passioNutrients. getMicroNutrients ())
}
}
}
Check out the full code here. FULL CODE