Skip to content

Commit 6291ad3

Browse files
authored
Merge in Material Sprint feature branch to master (android#472)
* Update Material version to 1.1.0-alpha07 (android#431) * Add button to navigate to Plant List When the user's garden is empty, add a button prompting them to navigate to the Plant List. This also adds a new string and some placeholder string translations. Updated styling will be implemented in a future commit. * Change Plant List Page to use GridLayout (android#433) * Changed Plant List page to grid Layout with 2 columns * Changed garden fragment to gridlayoutmanager with 2 columns * changed appSpan count to use an integer dimension * Turning Plant List Grid into Material Themed Cards (android#437) * Initial commit to turn plant list grid into cards * added dimension variable for card corner radius * Style changes for CI * Changed to staggered gridlayout * Code review Changes * Convert from drawer layout to tab layout (android#438) * WIP commit - converting to ViewPager * Update logic when tapping the "Add Plant" button Also removes action from the navigation graph and adds descriptive constants for the ViewPager page index. * run spotless * Use childFragmentManager to preserve fragments when returning to ViewPager * Update navigation direction for navigating from garden to plan details. Also removes unused fragment and action entries in the nav graph. * Clean up unused code and imports * Add imports back * Remove unused resources * Add comment for getCount() * Created Material-themed cards for My Garden Page (android#440) * Initial commit. still work to be done with strings.xml files * Translation placeholders and cleaned code * replaced translations * cleaned strings and switched to variables * code review changes * Add collapsing title to ViewPager (android#439) * Add title to ViewPager Also add a large font dimension for use in new and old code * Collapse toolbar Also some formatting fixes * Maintain toolbar scroll/collapse state when navigating back to ViewPager This requires an ID for both CoordinatorLayout and the AppBarLayout - added a comment to clarify. * Add CollapsingToolbarLayout Toolbar now collapses on both the My Garden and Plant List pages. Also added fitsSystemWindows to the app bar so that the text isn't drawn under the system bar. * Theme (android#441) * initial commit * formatting changes * circleCI * formatting * Add app bar to plant detail page Also moves FAB anchor to app bar and increase header image height * grid with to integers file * changed shape of fab * changed shape and color of add button (android#455) * changed colors to use ?attr * consolidate texts and colors to use material style guide * Added available plants header and padding to My Garden Page (android#457) * added available plants header * moved available plants strings * changed available plants title to be scrollable * Comments and cleaned code * spotlessApply * fixed padding in plant list page (android#464) * fixed padding in plant list page * margin end added * Update tests for the new UI interface Ignoring share button test for now, while the button is being redesigned. * Add icons to the tab layout (android#468) * Add icons to the tab layout The icons are programmatically set based on the selected tab. * Use color resources instead of hard coding color values * Added Dark Theme (android#467) * dark theme * spotless * cleaned code and changed icon color * Update dark mode yellow * watering needs changes * Fix bug where FAB does not hide when clicked * Detail Collapsing Toolbar (android#470) * initial commit for detail menu items * spotlessApply * spotlessApply * removed unused methods * removed unused imports * navbar code review * fixed overlap * Theming Changes (android#471) * initial commit for detail menu items * spotlessApply * spotlessApply * removed unused methods * removed unused imports * final theming changes * styling changes to tab icons * theme code review * changed to requireContext * Changed Theme and Shape Format * Code Readability Changes (android#478) * readability initial changes * readability changes * removed unused imports * Removed use of .tag and Renamed ViewPager (android#482) * updated viewpager name and removed tag * removed passing of context * switched to HashMap * cached fragments instead of loading everytime * declaritive hashmap * removed null check * Show Toolbar Animation using StateListAnimator (android#479) * using animator * comment formatting * Code Style and Efficiency Changes (android#481) * efficiency and theming changes * clean * Use StateListDrawable for Tabs (android#480) * added StateListDrawable for tabs * updated to homeviewpager * changed to homeviewpager for merge conflict * fixed toolbar text color * Convert ViewPager to ViewPager2 (android#456) * Convert ViewPager to ViewPager2 Require TabLayoutMediator to set up ViewPager2 and TabLayout; this file is taken from the ViewPager2 sample https://github.com/googlesamples/android-viewpager2. * Programmatically set menu visibility This is a temporary workaround; see https://issuetracker.google.com/issues/124183800 for more details. * Use TabLayoutMediator provided by Material 1.1.0-alpha07 * Update to ViewPager version 1.0.0-alpha06 This update also fixes a bug (https://issuetracker.google.com/issues/124183800 ) and removes the need for the temporary workaround. * Update callback to use ViewPager2's callback when a tab is selected * Remove temporary workaround for menu visibility Also add comment for tab text * Return String instead of CharSequence * Add TODO for data binding * Update ViewPager2 version to 1.0.0-beta02 * Address PR comments + refactor * Address PR comments - Create new Fragment instead of fetching existing Fragment - Bump VP2 version to 1.0.0-beta03 * Update Turkish string resources Also removed duplicate app_name in Italian string resources * Remove canvas nullability and related usage * Update comment * Address PR comments - update Material Version to 1.1.0-alpha09 - add newlines to layout - remove explicit clickable/focusable - not needed since onClick is set - use ?attr where appropriate - use app:backgroundTint for backwards compatibility * Address PR comments - Rename CustomCardView to MaskedCardView * Update Gradle version * Address PR comments - extract tab icon logic to its own method - set plant name on the plant detail page in the layout - only set appbar and toolbar attributes when crossing a scrolling threshold * Merge layer-list for back icon into a single <vector> * Update ktlint and spotless versions * Update colors and themes - Change colors to use descriptive names - Add alternative style for dark theme * Merge layer-list for share icon into a single <vector> Also update the back icon's circle path data and whitespace formatting * Remove unused PopupOverlay styles * Add Traditional and Simplified string translations
1 parent f19dd1b commit 6291ad3

File tree

58 files changed

+1198
-466
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1198
-466
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ Third Party Content
153153
-------------------
154154
Select text used for describing the plants (in `plants.json`) are used from Wikipedia via CC BY-SA 3.0 US (license in `ASSETS_LICENSE`).
155155

156+
"[seed](https://thenounproject.com/search/?q=seed&i=1585971)" by [Aisyah](https://thenounproject.com/aisyahalmasyira/) is licensed under [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/us/legalcode)
157+
156158
License
157159
-------
158160

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ dependencies {
6464
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6565
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerViewVersion"
6666
implementation "androidx.room:room-runtime:$rootProject.roomVersion"
67+
implementation "androidx.viewpager2:viewpager2:$rootProject.viewPagerVersion"
6768
implementation "androidx.work:work-runtime-ktx:$rootProject.workVersion"
6869
implementation "com.github.bumptech.glide:glide:$rootProject.glideVersion"
6970
implementation "com.google.android.material:material:$rootProject.materialVersion"

app/src/androidTest/java/com/google/samples/apps/sunflower/GardenActivityTest.kt

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,12 @@
1616

1717
package com.google.samples.apps.sunflower
1818

19-
import android.view.Gravity
2019
import androidx.test.espresso.Espresso.onView
21-
import androidx.test.espresso.action.ViewActions
2220
import androidx.test.espresso.action.ViewActions.click
2321
import androidx.test.espresso.assertion.ViewAssertions.matches
24-
import androidx.test.espresso.contrib.DrawerMatchers.isClosed
25-
import androidx.test.espresso.contrib.DrawerMatchers.isOpen
26-
import androidx.test.espresso.contrib.NavigationViewActions.navigateTo
2722
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
28-
import androidx.test.espresso.matcher.ViewMatchers.isRoot
29-
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
3023
import androidx.test.espresso.matcher.ViewMatchers.withId
31-
import androidx.test.platform.app.InstrumentationRegistry
3224
import androidx.test.rule.ActivityTestRule
33-
import androidx.test.uiautomator.UiDevice
34-
import com.google.samples.apps.sunflower.utilities.getToolbarNavigationContentDescription
35-
import org.junit.Assert.assertEquals
3625
import org.junit.Rule
3726
import org.junit.Test
3827

@@ -41,57 +30,13 @@ class GardenActivityTest {
4130
@Rule @JvmField
4231
var activityTestRule = ActivityTestRule(GardenActivity::class.java)
4332

44-
@Test fun clickOnAndroidHomeIcon_OpensAndClosesNavigation() {
45-
// Check that drawer is closed at startup
46-
onView(withId(R.id.drawer_layout)).check(matches(isClosed(Gravity.START)))
33+
@Test fun clickAddPlant_OpensPlantList() {
34+
// Given that no Plants are added to the user's garden
4735

48-
clickOnHomeIconToOpenNavigationDrawer()
49-
checkDrawerIsOpen()
50-
}
51-
52-
@Test fun onRotate_NavigationStaysOpen() {
53-
clickOnHomeIconToOpenNavigationDrawer()
54-
55-
with(UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())) {
56-
// Rotate device to landscape
57-
setOrientationLeft()
58-
checkDrawerIsOpen()
59-
60-
// Rotate device back to portrait
61-
setOrientationRight()
62-
checkDrawerIsOpen()
63-
}
64-
}
65-
66-
@Test fun clickOnPlantListDrawerMenuItem_StartsPlantListActivity() {
67-
clickOnHomeIconToOpenNavigationDrawer()
36+
// When the "Add Plant" button is clicked
37+
onView(withId(R.id.add_plant)).perform(click())
6838

69-
// Press on Plant List navigation item
70-
onView(withId(R.id.navigation_view))
71-
.perform(navigateTo(R.id.plant_list_fragment))
72-
73-
// Check that the PlantListFragment is visible
39+
// Then the ViewPager should change to the Plant List page
7440
onView(withId(R.id.plant_list)).check(matches(isDisplayed()))
7541
}
76-
77-
@Test fun pressDeviceBack_CloseDrawer_Then_PressBack_Close_App() {
78-
clickOnHomeIconToOpenNavigationDrawer()
79-
onView(isRoot()).perform(ViewActions.pressBack())
80-
checkDrawerIsNotOpen()
81-
assertEquals(activityTestRule.activity.isFinishing, false)
82-
assertEquals(activityTestRule.activity.isDestroyed, false)
83-
}
84-
85-
private fun clickOnHomeIconToOpenNavigationDrawer() {
86-
onView(withContentDescription(getToolbarNavigationContentDescription(
87-
activityTestRule.activity, R.id.toolbar))).perform(click())
88-
}
89-
90-
private fun checkDrawerIsOpen() {
91-
onView(withId(R.id.drawer_layout)).check(matches(isOpen(Gravity.START)))
92-
}
93-
94-
private fun checkDrawerIsNotOpen() {
95-
onView(withId(R.id.drawer_layout)).check(matches(isClosed(Gravity.START)))
96-
}
9742
}

app/src/androidTest/java/com/google/samples/apps/sunflower/PlantDetailFragmentTest.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import android.accessibilityservice.AccessibilityService
2020
import android.content.Intent
2121
import android.os.Bundle
2222
import androidx.navigation.findNavController
23-
import androidx.test.ext.junit.runners.AndroidJUnit4
24-
import androidx.test.platform.app.InstrumentationRegistry
2523
import androidx.test.espresso.Espresso.onView
2624
import androidx.test.espresso.action.ViewActions.click
2725
import androidx.test.espresso.intent.Intents
@@ -30,11 +28,14 @@ import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
3028
import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra
3129
import androidx.test.espresso.intent.matcher.IntentMatchers.hasType
3230
import androidx.test.espresso.matcher.ViewMatchers.withId
31+
import androidx.test.ext.junit.runners.AndroidJUnit4
32+
import androidx.test.platform.app.InstrumentationRegistry
3333
import androidx.test.rule.ActivityTestRule
3434
import com.google.samples.apps.sunflower.utilities.chooser
3535
import com.google.samples.apps.sunflower.utilities.testPlant
3636
import org.hamcrest.CoreMatchers.allOf
3737
import org.junit.Before
38+
import org.junit.Ignore
3839
import org.junit.Rule
3940
import org.junit.Test
4041
import org.junit.runner.RunWith
@@ -51,11 +52,12 @@ class PlantDetailFragmentTest {
5152
activityTestRule.activity.apply {
5253
runOnUiThread {
5354
val bundle = Bundle().apply { putString("plantId", testPlant.plantId) }
54-
findNavController(R.id.garden_nav_fragment).navigate(R.id.plant_detail_fragment, bundle)
55+
findNavController(R.id.nav_host).navigate(R.id.plant_detail_fragment, bundle)
5556
}
5657
}
5758
}
5859

60+
@Ignore("Share button redesign pending")
5961
@Test
6062
fun testShareTextIntent() {
6163
val shareText = activityTestRule.activity.getString(R.string.share_text_plant, testPlant.name)

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
android:label="@string/app_name"
2828
android:roundIcon="@mipmap/ic_launcher_round"
2929
android:supportsRtl="true"
30-
android:theme="@style/AppTheme">
30+
android:theme="@style/Theme.Sunflower">
3131
<activity
3232
android:name=".GardenActivity"
33-
android:theme="@style/AppTheme.NoActionBar">
33+
android:theme="@style/Theme.Sunflower.NoActionBar">
3434
<intent-filter>
3535
<action android:name="android.intent.action.MAIN" />
3636

app/src/main/java/com/google/samples/apps/sunflower/GardenActivity.kt

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,50 +18,13 @@ package com.google.samples.apps.sunflower
1818

1919
import android.os.Bundle
2020
import androidx.appcompat.app.AppCompatActivity
21-
import androidx.core.view.GravityCompat
22-
import androidx.databinding.DataBindingUtil
23-
import androidx.drawerlayout.widget.DrawerLayout
24-
import androidx.navigation.NavController
25-
import androidx.navigation.findNavController
26-
import androidx.navigation.ui.AppBarConfiguration
27-
import androidx.navigation.ui.navigateUp
28-
import androidx.navigation.ui.setupActionBarWithNavController
29-
import androidx.navigation.ui.setupWithNavController
21+
import androidx.databinding.DataBindingUtil.setContentView
3022
import com.google.samples.apps.sunflower.databinding.ActivityGardenBinding
3123

3224
class GardenActivity : AppCompatActivity() {
3325

34-
private lateinit var drawerLayout: DrawerLayout
35-
private lateinit var appBarConfiguration: AppBarConfiguration
36-
private lateinit var navController: NavController
37-
3826
override fun onCreate(savedInstanceState: Bundle?) {
3927
super.onCreate(savedInstanceState)
40-
41-
val binding: ActivityGardenBinding = DataBindingUtil.setContentView(this,
42-
R.layout.activity_garden)
43-
drawerLayout = binding.drawerLayout
44-
45-
navController = findNavController(R.id.garden_nav_fragment)
46-
appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
47-
48-
// Set up ActionBar
49-
setSupportActionBar(binding.toolbar)
50-
setupActionBarWithNavController(navController, appBarConfiguration)
51-
52-
// Set up navigation menu
53-
binding.navigationView.setupWithNavController(navController)
54-
}
55-
56-
override fun onSupportNavigateUp(): Boolean {
57-
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
58-
}
59-
60-
override fun onBackPressed() {
61-
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
62-
drawerLayout.closeDrawer(GravityCompat.START)
63-
} else {
64-
super.onBackPressed()
65-
}
28+
setContentView<ActivityGardenBinding>(this, R.layout.activity_garden)
6629
}
6730
}

app/src/main/java/com/google/samples/apps/sunflower/GardenFragment.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@ import android.view.ViewGroup
2323
import androidx.fragment.app.Fragment
2424
import androidx.fragment.app.viewModels
2525
import androidx.lifecycle.observe
26+
import androidx.viewpager2.widget.ViewPager2
2627
import com.google.samples.apps.sunflower.adapters.GardenPlantingAdapter
28+
import com.google.samples.apps.sunflower.adapters.PLANT_LIST_PAGE_INDEX
2729
import com.google.samples.apps.sunflower.databinding.FragmentGardenBinding
2830
import com.google.samples.apps.sunflower.utilities.InjectorUtils
2931
import com.google.samples.apps.sunflower.viewmodels.GardenPlantingListViewModel
3032

3133
class GardenFragment : Fragment() {
3234

35+
private lateinit var binding: FragmentGardenBinding
36+
3337
private val viewModel: GardenPlantingListViewModel by viewModels {
3438
InjectorUtils.provideGardenPlantingListViewModelFactory(requireContext())
3539
}
@@ -39,9 +43,14 @@ class GardenFragment : Fragment() {
3943
container: ViewGroup?,
4044
savedInstanceState: Bundle?
4145
): View? {
42-
val binding = FragmentGardenBinding.inflate(inflater, container, false)
46+
binding = FragmentGardenBinding.inflate(inflater, container, false)
4347
val adapter = GardenPlantingAdapter()
4448
binding.gardenList.adapter = adapter
49+
50+
binding.addPlant.setOnClickListener {
51+
navigateToPlantListPage()
52+
}
53+
4554
subscribeUi(adapter, binding)
4655
return binding.root
4756
}
@@ -56,4 +65,9 @@ class GardenFragment : Fragment() {
5665
adapter.submitList(result)
5766
}
5867
}
68+
69+
// TODO: convert to data binding if applicable
70+
private fun navigateToPlantListPage() {
71+
requireActivity().findViewById<ViewPager2>(R.id.view_pager).currentItem = PLANT_LIST_PAGE_INDEX
72+
}
5973
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2019 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.samples.apps.sunflower
18+
19+
import android.os.Bundle
20+
import android.view.LayoutInflater
21+
import android.view.View
22+
import android.view.ViewGroup
23+
import androidx.appcompat.app.AppCompatActivity
24+
import androidx.fragment.app.Fragment
25+
import com.google.android.material.tabs.TabLayoutMediator
26+
import com.google.samples.apps.sunflower.adapters.MY_GARDEN_PAGE_INDEX
27+
import com.google.samples.apps.sunflower.adapters.PLANT_LIST_PAGE_INDEX
28+
import com.google.samples.apps.sunflower.adapters.SunflowerPagerAdapter
29+
import com.google.samples.apps.sunflower.databinding.FragmentViewPagerBinding
30+
31+
class HomeViewPagerFragment : Fragment() {
32+
33+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
34+
val binding = FragmentViewPagerBinding.inflate(inflater, container, false)
35+
val tabLayout = binding.tabs
36+
val viewPager = binding.viewPager
37+
38+
viewPager.adapter = SunflowerPagerAdapter(this)
39+
40+
// Set the icon and text for each tab
41+
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
42+
tab.setIcon(getTabIcon(position))
43+
tab.text = getTabTitle(position)
44+
}.attach()
45+
46+
(activity as AppCompatActivity).setSupportActionBar(binding.toolbar)
47+
48+
return binding.root
49+
}
50+
51+
private fun getTabIcon(position: Int): Int {
52+
return when (position) {
53+
MY_GARDEN_PAGE_INDEX -> R.drawable.garden_tab_selector
54+
PLANT_LIST_PAGE_INDEX -> R.drawable.plant_list_tab_selector
55+
else -> throw IndexOutOfBoundsException()
56+
}
57+
}
58+
59+
private fun getTabTitle(position: Int): String? {
60+
return when (position) {
61+
MY_GARDEN_PAGE_INDEX -> getString(R.string.my_garden_title)
62+
PLANT_LIST_PAGE_INDEX -> getString(R.string.plant_list_title)
63+
else -> null
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)