-
Notifications
You must be signed in to change notification settings - Fork 0
Home
We have a series of tasks for building out SeasonalClone, an Android app to help you get a list of seasonal fruits and veggies in your area (In these tasks, we'll be using California as an example).
Check out https://bit.ly/2J31WqQ to see the original app. It is only meant to work in the United States.
You can refer to the task walkthroughs on the right if necessary, but we recommend trying out each of these tasks on your own first.
There are links for relevant reading under each of the tasks to help you out.
Here, we just want to create a recyclerview and adapter and get it to work with some test data.
For this project, let's stick to portrait mode.
1. Create an item_produce.xml layout that shows produce name and produce type underneath in the recycler view. Something like this:
3. Create a data model for ProduceItem with name, type, and description. You will be needing this to populate a list of ProduceItems into the recyclerview.
4. Use bindView/Kotterknife for binding views using KotterKnife at https://github.com/JakeWharton/kotterknife
You can just copy ButterKnife.kt into your project: ButterKnife.kt
In your MainActivity, make sure you use it to bind to the RecyclerView.
-
Create the adapter for loading a list of ProduceItems.
-
We'll need to inflate view in our adapter, and it seems useful to create as an extension function if we'll be reusing it. Try creating an extension function for Context.inflate for the situation where you need to use
LayoutInflater.from(this).inflate(resource, root, attachToRoot)
in your adapter.
Set up MainActivity to populate your RecyclerView, and add some fake data through the adapter.
Here's some sample test data:
//set up test data
val items = listOf(ProduceItem("Apples", "Fruit", "Apples are red."),
ProduceItem("Bananas", "Fruit", "Bananas are tasty."),
ProduceItem("Broccoli", "Vegetable", "Broccoli looks like little trees."),
ProduceItem("Carrot", "Vegetable", "Bunnies like carrots."))
You should now have an app that loads these basic items in a recyclerview. Something that looks like:
Oh, you can remove the FAB. You won't need it.
We have a seasonal_metadata JSON file that contains data for produce items, and a seasonal_california json file for produce items specific to California. We want to use these files to load real produce items for California. Specifically, we only want to show items that are in-season for June!
-
seasonal_metadata.json: https://drive.google.com/file/d/1w5BQOje4-Hqk586gG5OWDH0O_LfPtnFo/view?usp=sharing
-
seasonal_california.json: https://drive.google.com/open?id=1D0NgqCuaQAr0ilATxE7uulXtgn0rSMVb
Check out both files and see the type of data they have and how they are connected.
3. Fill in your ProduceItem model to mimic the JSON files. Allow GSON to deserialize your JSON into fields using @SerializedName
for your client models.
val assetManager = context.assets
val metadataFile = assetManager.open("seasonal_metadata.json")
val metadata = metadataFile.readBytes().toString(Charset.defaultCharset())
In order to parse the JSON file, use GSONBuilder:
val gsonBuilder = GsonBuilder().setPrettyPrinting().create()
//parse seasonal_metadata
val produceItemList: List<ProduceItem> = gsonBuilder.fromJson(jsonString, object :
TypeToken<List<ProduceItem>>() {}.type)
5. Populate your RecyclerView with ProduceItems in June for California. All produce names and descriptions are in seasonal_metadata, and California items are in seasonal_california. You can connect them by id. Hint: try map and filter
At this point, if you run the app, you should be able to see a list of all of the ProduceItems from the metadata file.
Mimic the json structure, and you will be able to come up with data classes that encapsulate all of the JSON fields.
Then, fix your parsing method to parse seasonal_california and apply a map/filter to only show California items in June.
Run the app, and you should see a list of California produce items with either "Fruit" or "Vegetable" produce type.
We now want to show images of the produce next to the name/type of produce. Then, we will go ahead and divide the fruits and veggies into sections using a title, and display them in the recyclerview.
-
Add an ImageView to the item_produce.xml layout.
-
Add image property to ProduceItem if you haven't already.
-
Use Glide to populate your ImageViews. Make sure to add INTERNET permission to your Manifest!
How to Use Glide You can use glide version 4.4.0 instead.
If that all went well, you should see a list of produce items with images!
2. Group produce types “Herb”, “Legume”, “Nut”, and “Vegetable" all under Veggies section, and “Fruit” type into the Fruits section. The section headers should be “Fruits” and “Veggies”
- Create an item_header.xml layout for the section headers.
3. Modify your adapter to use getItemViewType and create a heterogeneous layout with Veggies section and Fruits section.
4. Oh no! Some puppy images got mixed into the produce images. Use a filter to only show items with display = true
value in metadata
Here's an example of what it should look like at the end:
*Bonus: Show items that are “new” this month as a separate section. Then, use month picker to dynamically load what's new this month based on the month selected.
This task will not have any functional difference from Task 3, but custom views are pretty common in most Android projects, so we'll be practicing them. Let's start by using custom views for item_produce.xml and item_header.xml.
1. Create a custom view called BrowseItemView that holds the items from item_produce. This new view can be used by RecyclerView/adapter to load data.
This should be pretty similar to your BrowseItemView in terms of setup.
3. Modify your adapter to use getItemViewType and create a heterogeneous layout with Veggies section and Fruits section. Look into using the SimpleViewHolder
class that we discussed so that you don't need to generate multiple ViewHolders.
Here's an example of what it should look like at the end: