50.001 1D Project
A POC Recipe Android Application using Google Mediapipe Hands Tracking model for smart touchless scrolling.
Deliverables:
- Tran Nguyen Bao Long @TNBL: Project Lead
- define software architecture
- documentation
- Li Xueqing @cnmnrll: Project Design
- set basic
Recipe
,Ingredients
andInstructions
modelsmodel
- documentation
- set basic
- Melodie Chew En Qi @melmelchew: Marketing + Frontend
RecyclerView
andNavigationView
adapter
forRecyclerView
- Melvin Lim Boon Han @melvinlimbh: Marketing + Frontend
- Fragments for different cuisines
home
- Fragments for creating recipes RecipeCreate
- all resources and layouts
res
- Fragments for different cuisines
- Han Jin @dlmszhhh: Backend Acitivity
- basic recipe activities
acitivity
- basic recipe activities
- Wang Zhouran @wzrwzr23: Backend Database
- Liang Junyi @LiangJunyi-010 Backend HandTracking
- implement HandTracking using Google Mediapipe Hands model for touchless scrolling in
ViewRecipeActivity
- implement HandTracking using Google Mediapipe Hands model for touchless scrolling in
Overview of Design Pattern used:
- Adapter Design Pattern (for SQLite database and RecyclerView)
- Singleton Design Pattern (for SQLite database)
- Observer Design Pattern (for
CreateRecipeActivity
)- Factory Design Pattern (for Cuisine Fragment)
- Template Method Design Pattern (for Create Recipe Fragment)
0. Model
- Utilize
Parcelable
interface:- speed up data transfer using Java Serializable
- easily pass data as
Bundle
object through Activity
Recipe
:id
: primary key for SQLitename
: name of recipedescription
: short description of recipecategory
: category/cuisine (Vietnamese/Chinese)mealType
: type of meals (Breakfast, Dinner,...)time
: estimated to prepare the dishimagePath
: local URI path to Recipe imageingredients
: list of ingredientsinstructions
: list of instructions
Instruction
:id
: primary key for SQLiterecipeID
: foreign keycontent
: instruction body
Ingredient
- We use local database SQLite and utilize abstract class
SQLiteOpenHelper
to create and manage our database inSQLiteDbCRUD
- Adapter in
DatabaseAdapter
- using Adapter Design Pattern as main API for Recipe CRUD operations
- using Singleton Design Pattern to create a single instance of our database to be shared within all activities
- Data Access Objects (DAO):
- Both
MainActivity
andViewRecipeActivity
inherits aToolbar
(explain in section B5a) from abstract classMenuActivity
MainActivity
- implements interface
BaseFragment.FragmentListener
that define blueprint for methods to:- display recipe:
onShowRecipe
which navigates toViewRecipeActivity
(an Explicit Intent) - delete recipe:
onDeleteRecipe
- display recipe:
- consists of 3 main views:
- implements interface
ViewRecipeActivity
:- display chosen recipe from the data passed as parcel from
MainActivity
- where HandsTracking feature (explain in section B3) is located
- display chosen recipe from the data passed as parcel from
CreateRecipeActivity
- This feature is implemented in
ViewRecipeActivity
- 2 main Buttons
Start Tracking
andStop Tracking
to enable/disable the feature, which open up aglSurfaceView
in theRelativeLayout at the bottom of the page
glSurfaceView
is an instance ofSolutionGlSurfaceView<HandsResult>
provided by Mediapipe Library, similar to OpenGL that allows writing words and drawing on webcam output.- we detect whether the index finger is pointing up or down and from there, post a
Runnable
to ourScrollView
(that is displaying the Ingredients and Instructions) to perform a smooth scroll correspoding to the gesture.
- 2 main Buttons
a. Cuisine Fragment under fragment/home
- Both
ChineseFragment
andVietnameseFragment
extends from abstract classBaseFragment
- using Factory Design Pattern (
BaseFragment
is the factory,ChineseFragment
andVietnameseFragment
are the products) allow us to easily scale to multiple cuisines in the future - the only abstract method is
getFragmentLayout
that each product should define to generate its own correct fragment - both using
RecyclerView
to display its recipes (explain in section B5c)
- using Factory Design Pattern (
b. Recipe Create Fragment under fragment/recipe
- 3 fragments correspond to 3 steps in creating a new Recipe:
RecipeCreateImageFragment
: (1st step) to add image, description, choose meal type and timeRecipeCreateIngredientFragment
: (2nd step) to add ingredientsRecipeCreateInstructionFragment
: (3rd step) to add instructions
- All 3 Create Recipe Fragments extends the abstract class
NavigableFragment
:- blueprint for method
onNext
that define which fragment to navigate to after completing each creating new recipe step - using Template Method Design Pattern with
NavigableFragment
as the template
- blueprint for method
RecipeCreateImageFragment
can access the local storage to upload new image for recipe (an Implicit Intent)
- Both
MainActivity
andViewRecipeActivity
needs to define its own Toolbar according to the blueprint defined in the abstract classMenuActivity
MainActivity
Toolbar:- includes
NavigationView
(explain in section B5b below) - includes menu to add a "New recipe"
- includes
ViewRecipeActivity
Toolbar:- support Edit and Delete recipe functionalities
- make use of a
switch
case to switch to a different cuisine insideMainActivity
- once a new cuisine is selected, the corresponding Fragment (
ChineseFragment
orVietnameseFragment
) will be added intoNestedScrollView
to show recipeCardView
- We user
RecyclerView
at 2 places:- to display recipes in the Cuisine Fragment (
BaseFragment
) - to display the added ingredients and instructions when creating new recipe in Recipe Create Fragment
- to display recipes in the Cuisine Fragment (
- To implement
RecyclerView
we need to implement the corresponding adapter as shown inadapter/recipe
(Adapter Design Pattern)- the 3 main functions in each adapter to override are:
onCreateViewHolder
that inflate a new view in the parent layout to allow for display of listed itemsonBindViewHolder
that binds the data to be displayed in as listed itemsgetItemCount
that return the size of all the items to be displayed
- in the corresponding Fragment, before we set the above adapter, we also need to set a
LinearLayoutManager
for theRecyclerView
to reside in - code examples:
- the 3 main functions in each adapter to override are:
private RecyclerView instructionRecyclerView;
instructionRecyclerView.setHasFixedSize(true);
instructionRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
instructionRecyclerView.setAdapter(instructionAdapter);
- We made use of a some very useful Youtube tutorials + Github repos to build a normal Cooking Recipe app before adding modifications and our hand tracking feature: