Recent in Technology

Bridging the Gap: Recipe App Development : Basic structure

To get started, you'll need to follow these steps:

  1. Create a new Android project in Android Studio and give it name - Receipe app or you can use chatgpt to get the name.
  2. Design your app's user interface by creating XML layout files. For displaying recipes, you might want to create a layout file for the recipe list and another for the recipe details.
  3. In your main activity class, retrieve the recipe data from a data source. You can use a dummy list of recipes for now or fetch data from an API or a local database.
  4. Create a custom adapter class that extends the RecyclerView.Adapter class to handle the display of recipes in a list or grid format.
  5. In your activity, initialize a RecyclerView object and set the custom adapter to display the list of recipes.
  6. Implement any necessary callbacks or listeners to handle user interactions, such as tapping on a recipe to view its details.









Detailed steps:

Here are the steps to create a new Android project and reach the point where you can see the Java and XML code:

Step 1: Open Android Studio

  • Launch Android Studio on your computer.

Step 2: Create a New Project

  • Click on "Start a new Android Studio project" or go to "File" > "New" > "New Project".

Step 3: Configure Your Project

  • Choose a project template, such as "Phone and Tablet" or "Empty Activity".
  • Enter the project name, package name, and choose the location to save the project.
  • Select the minimum SDK version and language (Java or Kotlin).
  • Click on "Finish" to create the project.

Step 4: Explore Project Structure

  • Once the project is created, Android Studio will display the project structure.
  • Navigate to the "app" folder and expand it to see the different directories and files.

Step 5: Open XML Layout File

  • Inside the "res" folder, navigate to the "layout" directory.
  • Double-click on the XML layout file (e.g., "activity_main.xml") to open it in the Android Studio editor.
  • This is where you define the structure and appearance of the app's user interface.

Step 6: Open Java Class File

  • Inside the "java" folder, navigate to the package directory you specified during project creation.
  • Open the Java class file (e.g., "MainActivity.java") associated with your main activity.
  • This is where you write the Java code that controls the app's behavior.

At this point, you should be able to see and edit the Java and XML code in Android Studio. The XML code defines the layout of your app's UI, while the Java code handles the logic and functionality of the app.



Update your Java code as per below

MainActivity.java code:

import android.os.Bundle; import android.widget.LinearLayout; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private RecipeAdapter recipeAdapter; private List<Recipe> recipeList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerView); recipeList = new ArrayList<>(); recipeAdapter = new RecipeAdapter(recipeList); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recipeAdapter); // Populate recipe list with dummy data (replace with your own data retrieval logic) populateRecipeList(); } private void populateRecipeList() { // Add dummy recipes to the list recipeList.add(new Recipe("Recipe 1", "Description 1", "Image URL 1")); recipeList.add(new Recipe("Recipe 2", "Description 2", "Image URL 2")); recipeList.add(new Recipe("Recipe 3", "Description 3", "Image URL 3")); // Notify the adapter that the data set has changed recipeAdapter.notifyDataSetChanged(); } }


Code breakdown:

  • Import statements: These statements import necessary classes and packages for the code to compile and run successfully.
  • MainActivity class: This is the main activity of your app, which extends the AppCompatActivity class provided by Android.
  • Variables: private RecyclerView recyclerView, private RecipeAdapter recipeAdapter, and private List<Recipe> recipeList are declared as private instance variables.
  • onCreate method: This method is called when the activity is created. It sets the content view to the layout defined in activity_main.xml.
  • Finding views: The recyclerView is initialized by finding the view with the id recyclerView from the activity's layout.
  • Initializing adapter and layout manager: The recipeAdapter is created with an empty recipeList. A LinearLayoutManager is created and set on the recyclerView to manage the layout of the items.
  • Setting adapter: The recipeAdapter is set on the recyclerView.
  • populateRecipeList method: This method populates the recipeList with dummy recipe data. It adds three dummy Recipe objects to the list.
  • Notifying adapter: After adding the dummy data, recipeAdapter.notifyDataSetChanged() is called to notify the adapter that the data set has changed.

Overall, this code sets up the main activity, initializes the RecyclerView and its adapter, sets the layout manager, populates the recipe list with dummy data, and notifies the adapter of the changes.

Expand app then java then right click the option for the app without test. Select new then java class and give it the name below.

RecipeAdapter.java code:

import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import java.util.List; public class RecipeAdapter extends RecyclerView.Adapter<RecipeAdapter.RecipeViewHolder> { private List<Recipe> recipeList; public RecipeAdapter(List<Recipe> recipeList) { this.recipeList = recipeList; } @NonNull @Override public RecipeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recipe_item_layout, parent, false); return new RecipeViewHolder(view); } @Override public void onBindViewHolder(@NonNull RecipeViewHolder holder, int position) { Recipe recipe = recipeList.get(position); holder.titleTextView.setText(recipe.getTitle()); holder.descriptionTextView.setText(recipe.getDescription()); Glide.with(holder.itemView.getContext()) .load(recipe.getImageUrl()) .into(holder.imageView); } @Override public int getItemCount() { return recipeList.size(); } static class RecipeViewHolder extends RecyclerView.ViewHolder { TextView titleTextView; TextView descriptionTextView; ImageView imageView; RecipeViewHolder(@NonNull View itemView) { super(itemView); titleTextView = itemView.findViewById(R.id.titleTextView); descriptionTextView = itemView.findViewById(R.id.descriptionTextView); imageView = itemView.findViewById(R.id.imageView); } } }

Code breakdown:
  • Import statements: These statements import necessary classes and packages for the code to compile and run successfully.
  • RecipeAdapter class: This class extends the RecyclerView.Adapter class and is responsible for binding data to the views in the RecyclerView.
  • recipeList variable: This variable holds the list of Recipe objects that will be displayed in the RecyclerView.
  • Constructor: The constructor takes a List<Recipe> as a parameter and assigns it to the recipeList variable.
  • onCreateViewHolder method: This method is called when the RecyclerView needs a new ViewHolder to represent an item. It inflates the layout for the item using LayoutInflater and returns a new instance of RecipeViewHolder.
  • onBindViewHolder method: This method is called to bind data to the views of a specific ViewHolder. It gets the recipe at the specified position from the recipeList, and sets the title, description, and image using the corresponding views in the ViewHolder. It uses the Glide library to load the image from the provided URL into the ImageView.
  • getItemCount method: This method returns the number of items in the recipeList.
  • RecipeViewHolder class: This is a static inner class that extends RecyclerView.ViewHolder and represents a single item view in the RecyclerView.
  • ViewHolder initialization: In the RecipeViewHolder constructor, the views (titleTextView, descriptionTextView, and imageView) are initialized by finding them in the itemView (the inflated layout).

The RecipeAdapter class is responsible for managing the creation of ViewHolder objects and binding data to them. The RecipeViewHolder class holds references to the views in the item layout, which can be accessed and updated in the onBindViewHolder method.


Make sure to include below layout files in your project's res/layout directory.

activity_main.xml: Layout file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" tools:context=".MainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>


Code breakdown:

Here's a breakdown of the XML layout code:

  • 1. LinearLayout: The root element of the layout file is a LinearLayout. It is a ViewGroup that arranges its child views in a vertical orientation.

    • xmlns:android="http://schemas.android.com/apk/res/android": This attribute sets the XML namespace for Android.
    • xmlns:tools="http://schemas.android.com/tools": This attribute sets the XML namespace for tools.
    • android:layout_width="match_parent": This attribute sets the width of the LinearLayout to match the parent's width.
    • android:layout_height="match_parent": This attribute sets the height of the LinearLayout to match the parent's height.
    • android:orientation="vertical": This attribute sets the orientation of the LinearLayout to vertical, meaning its child views will be arranged vertically.
    • android:padding="16dp": This attribute sets the padding of the LinearLayout to 16dp on all sides.
    • tools:context=".MainActivity": This attribute sets the context for the layout preview in the Android Studio layout editor.
  • 2. RecyclerView: Inside the LinearLayout, there is a RecyclerView, which is a ViewGroup that displays a scrolling list of items efficiently.

    • android:id="@+id/recyclerView": This attribute sets the id of the RecyclerView to "recyclerView", which can be used to reference it in the Java code.
    • android:layout_width="match_parent": This attribute sets the width of the RecyclerView to match the parent's width.
    • android:layout_height="match_parent": This attribute sets the height of the RecyclerView to match the parent's height.

The LinearLayout acts as a container for the RecyclerView, allowing you to position it and add other views if needed. The RecyclerView will be populated with the list of recipes in the Java code.


For the recipe layout below, right click layout folder and create new layout resource file with the same name.


recipe_item_layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="8dp"> <ImageView android:id="@+id/imageView" android:layout_width="80dp" android:layout_height="80dp" android:scaleType="centerCrop" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginStart="16dp"> <TextView android:id="@+id/titleTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:textStyle="bold" /> <TextView android:id="@+id/descriptionTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" /> </LinearLayout> </LinearLayout>


These layouts define the structure and appearance of the main activity and the individual recipe item views within the RecyclerView. You can customize the layout further by adjusting the dimensions, styles, and other properties to match your app's design.

Here's a breakdown of the XML layout code:

  • LinearLayout: The root element of the layout file is a LinearLayout. It is a ViewGroup that arranges its child views in a horizontal orientation.

    • xmlns:android="http://schemas.android.com/apk/res/android": This attribute sets the XML namespace for Android.
    • android:layout_width="match_parent": This attribute sets the width of the LinearLayout to match the parent's width.
    • android:layout_height="wrap_content": This attribute sets the height of the LinearLayout to wrap its content.
    • android:orientation="horizontal": This attribute sets the orientation of the LinearLayout to horizontal, meaning its child views will be arranged horizontally.
    • android:padding="8dp": This attribute sets the padding of the LinearLayout to 8dp on all sides.
  • ImageView: Inside the LinearLayout, there is an ImageView, which displays an image.

    • android:id="@+id/imageView": This attribute sets the id of the ImageView to "imageView", which can be used to reference it in the Java code.
    • android:layout_width="80dp": This attribute sets the width of the ImageView to 80dp.
    • android:layout_height="80dp": This attribute sets the height of the ImageView to 80dp.
    • android:scaleType="centerCrop": This attribute sets the scale type of the image to centerCrop, ensuring it fills the ImageView while maintaining the aspect ratio.
  • LinearLayout: Inside the LinearLayout, there is another LinearLayout acting as a container for the TextViews.

    • android:layout_width="0dp": This attribute sets the width of the LinearLayout to 0dp, allowing it to take the remaining space.
    • android:layout_height="wrap_content": This attribute sets the height of the LinearLayout to wrap its content.
    • android:layout_weight="1": This attribute sets the weight of the LinearLayout to 1, distributing the remaining space proportionally.
    • android:orientation="vertical": This attribute sets the orientation of the LinearLayout to vertical, meaning its child views will be arranged vertically.
    • android:layout_marginStart="16dp": This attribute sets the start margin of the LinearLayout to 16dp.
  • TextView: Inside the inner LinearLayout, there is a TextView displaying the title of the recipe.

    • android:id="@+id/titleTextView": This attribute sets the id of the TextView to "titleTextView", which can be used to reference it in the Java code.
    • android:layout_width="match_parent": This attribute sets the width of the TextView to match the parent's width.
    • android:layout_height="wrap_content": This attribute sets the height of the TextView to wrap its content.
    • android:textSize="18sp": This attribute sets the text size of the TextView to 18sp.
    • android:textStyle="bold": This attribute sets the text style of the TextView to bold.
  • TextView: Inside the inner LinearLayout, there is another TextView displaying the description of the recipe.

    • android:id="@+id/descriptionTextView": This attribute sets the id of the TextView to "descriptionTextView", which can be used to reference it in the Java code.
    • android:layout_width="match_parent": This attribute sets the width of the TextView to match the parent's width.
    • android:layout_height="wrap_content": This attribute sets the height of the TextView to wrap its content.
    • android:layout_marginTop="8dp": This attribute sets the top margin of the TextView to 8dp.

The LinearLayout acts as a container for the ImageView and the inner LinearLayout, allowing you to position them horizontally. The inner LinearLayout serves as a container for the TextViews, arranging them vertically.



Also add this java class, Recipe.java and replace the code with below

public class Recipe { private String title; private String description; private String imageUrl; public Recipe(String title, String description, String imageUrl) { this.title = title; this.description = description; this.imageUrl = imageUrl; } // Getter method for title public String getTitle() { return title; } // Getter method for description public String getDescription() { return description; } // Getter method for imageUrl public String getImageUrl() { return imageUrl; } // You can also add setter methods if needed }


Explanation:

  1. public class Recipe { ... }: This is a simple Java class named Recipe, which represents a recipe object in the app.

  2. private String title;: This is a private member variable of the Recipe class. It holds the title of the recipe, such as "Chocolate Cake" or "Pasta Carbonara."

  3. private String description;: This is another private member variable that holds the description or summary of the recipe. It might contain information like the preparation time, cooking steps, or any other relevant details.

  4. private String imageUrl;: This is the third private member variable, which holds the URL of the recipe's image. This URL points to an image file that visually represents the recipe.

  5. public Recipe(String title, String description, String imageUrl) { ... }: This is the constructor of the Recipe class. It is responsible for creating a new Recipe object with the provided title, description, and image URL. When you create a new Recipe object, you pass these values to the constructor, and it initializes the corresponding fields of the Recipe object.

  6. public String getTitle() { ... }: This is a getter method for the title field. It allows other classes to access the value of the title field of a Recipe object. By calling recipe.getTitle(), where recipe is a Recipe object, you can retrieve the title of that recipe.

  7. public String getDescription() { ... }: This is a getter method for the description field, similar to the getTitle() method. It allows you to access the description of a Recipe object.

  8. public String getImageUrl() { ... }: This is a getter method for the imageUrl field. Like the previous two methods, it allows you to access the image URL of a Recipe object.

The Recipe class serves as a blueprint for creating recipe objects, each containing the title, description, and image URL of a specific recipe. By creating multiple Recipe objects and storing them in a list (as shown in the previous code snippets), you can display a list of recipes in your app, making it functional and informative for users who want to explore various recipes.


You need to add the Glide library to your Android project. Here's how you can do it:

  1. Open your app's build.gradle file:

    • If you are using Android Studio, go to the "Project" view, navigate to your app module, and open the build.gradle file for that module.
    • If you are using a text editor, locate the build.gradle file in your app module's directory.
  2. Add the Glide dependency to the dependencies block of the build.gradle file

    dependencies { // Other dependencies... implementation 'com.github.bumptech.glide:glide:4.12.0' }
  3. After adding the Glide dependency, you need to sync your project to download the library and make it available for your app. In Android Studio, click on the "Sync Now" button that appears at the top right corner of the window.

Once the project sync is complete, the error related to com.bumptech.glide.Glide should be resolved, and you can use Glide to load images in your app without any issues. Make sure you have an internet connection during the sync process, as it will download the required Glide library files from the internet.


To add images to the res folder for use in the XML layout, follow these steps: 1. Create a new folder named "drawable" under the "res" directory if it doesn't already exist. This folder is used to store drawable resources, including images. 2. Place the images you want to use in your layout inside the "drawable" folder. You can do this by simply dragging and dropping the images into the folder from your file explorer. Make sure the images are 50 by 50 px or less but you can adjust to desired size depending on what you want to achieve. 3. Rename the images to have lowercase filenames with no spaces or special characters. For example, if you have an image named "Image URL 1.png," rename it to something like "image_url_1.png." 4. Now, you can reference these images in your XML layout using the `@drawable/` prefix followed by the image file name without the extension. For example, if you have an image named "image_url_1.png," you can reference it like this: ```xml <ImageView android:id="@+id/imageView" android:layout_width="80dp" android:layout_height="80dp" android:scaleType="centerCrop" android:src="@drawable/image_url_1" /> ``` 5. In your Java code, when adding recipes to the `recipeList`, use the image file names without the file extension: ```java

private void populateRecipeList() {
// Add dummy recipes to the list with correct image resource IDs
recipeList.add(new Recipe("Recipe 1", "Description 1", R.drawable.image_url_1));
recipeList.add(new Recipe("Recipe 2", "Description 2", R.drawable.image_url_2));
recipeList.add(new Recipe("Recipe 3", "Description 3", R.drawable.image_url_3));

// Notify the adapter that the data set has changed
recipeAdapter.notifyDataSetChanged();
}

and also

public void onBindViewHolder(@NonNull RecipeViewHolder holder, int position) {
Recipe recipe = recipeList.get(position);
holder.titleTextView.setText(recipe.getTitle());
holder.descriptionTextView.setText(recipe.getDescription());
holder.imageView.setImageResource(recipe.getImageResource());

}

and also

package com.peterc.kitchenwhiz;
import android.os.Bundle;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private RecyclerView recyclerView;
private RecipeAdapter recipeAdapter;
private List<Recipe> recipeList;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

recyclerView = findViewById(R.id.recyclerView);
recipeList = new ArrayList<>();
recipeAdapter = new RecipeAdapter(recipeList);

LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recipeAdapter);

// Populate recipe list with dummy data (replace with your own data retrieval logic)
populateRecipeList();
}

private void populateRecipeList() {
// Add dummy recipes to the list with correct image resource IDs
recipeList.add(new Recipe("Recipe 1", "Description 1", R.drawable.image_url_1));
recipeList.add(new Recipe("Recipe 2", "Description 2", R.drawable.image_url_2));
recipeList.add(new Recipe("Recipe 3", "Description 3", R.drawable.image_url_3));

// Notify the adapter that the data set has changed
recipeAdapter.notifyDataSetChanged();
}

}

By following these steps, your images will be accessible from the "drawable" folder and can be used in the XML layout and Java code as needed.


This is the basic implementation on which we will build our app. Remember to change activity and associated java file to match the name you selected. Where possible maintain the naming as in this code to avoid error at early stages of your learning.

Run this on emulator or on the phone. Once the app loads, you can then start adding layout and arranging to your liking. Follow the next article for next steps.






Post a Comment

0 Comments