-
Notifications
You must be signed in to change notification settings - Fork 527
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Initial file introduction * ViewModel amnd ViewPager introduction * Basic implementation finished * Added images * New implementation * Button click listener added * Skip button functionality added * Final implememntation * Added test cases * Self review nit changes * Updated test cases- Not perfect * Indicator dots implementation change and test cases updated * Added TODO * Nit change * Changes as per Ben's suggestion * Nit changes to OnboardingSlideViewModel * Added contentDescription * Updates image test cases * All test cases fixed * Nit change * Merge branch 'develop' of https://github.com/oppia/oppia-android into material-cardview-issue-fix-approach-2 # Conflicts: # app/build.gradle * nit * nit * change in package structure, and changed on-board to single word onboard, onboarding proto * changed on-boarded to single word onboarded * changed on-board to single word onboard in text class method names * changed on-board to single word onboard in comments * nit * Onboarding flow full lowfi implementation * Updated test cases Co-authored-by: nikitamarysolomanpvt <[email protected]>
- Loading branch information
1 parent
4409ca7
commit d705580
Showing
30 changed files
with
1,438 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
app/src/main/java/org/oppia/app/onboarding/OnboadingSlideViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import android.content.Context | ||
import androidx.databinding.ObservableField | ||
import androidx.lifecycle.ViewModel | ||
import org.oppia.app.R | ||
import org.oppia.app.viewmodel.ObservableViewModel | ||
|
||
const val TOTAL_NUMBER_OF_SLIDES = 4 | ||
|
||
/** [ViewModel] for slide in onboarding flow. */ | ||
class OnboardingSlideViewModel(val context: Context, viewPagerSlide: ViewPagerSlide) : ObservableViewModel() { | ||
val slideImage = ObservableField<Int>(R.drawable.ic_onboarding_0) | ||
val contentDescription = ObservableField<String>(context.resources.getString(R.string.onboarding_slide_0_title)) | ||
val title = ObservableField<String>(context.resources.getString(R.string.onboarding_slide_0_title)) | ||
val description = ObservableField<String>(context.resources.getString(R.string.onboarding_slide_0_description)) | ||
|
||
init { | ||
initializingSlide(viewPagerSlide) | ||
} | ||
|
||
private fun initializingSlide(viewPagerSlide: ViewPagerSlide) { | ||
when (viewPagerSlide) { | ||
ViewPagerSlide.SLIDE_0 -> { | ||
slideImage.set(R.drawable.ic_onboarding_0) | ||
contentDescription.set(context.resources.getString(R.string.onboarding_slide_0_title)) | ||
title.set(context.resources.getString(R.string.onboarding_slide_0_title)) | ||
description.set(context.resources.getString(R.string.onboarding_slide_0_description)) | ||
} | ||
ViewPagerSlide.SLIDE_1 -> { | ||
slideImage.set(R.drawable.ic_onboarding_1) | ||
contentDescription.set(context.resources.getString(R.string.onboarding_slide_1_title)) | ||
title.set(context.resources.getString(R.string.onboarding_slide_1_title)) | ||
description.set(context.resources.getString(R.string.onboarding_slide_1_description)) | ||
} | ||
ViewPagerSlide.SLIDE_2 -> { | ||
slideImage.set(R.drawable.ic_onboarding_2) | ||
contentDescription.set(context.resources.getString(R.string.onboarding_slide_2_title)) | ||
title.set(context.resources.getString(R.string.onboarding_slide_2_title)) | ||
description.set(context.resources.getString(R.string.onboarding_slide_2_description)) | ||
} | ||
ViewPagerSlide.SLIDE_3 -> { | ||
slideImage.set(R.drawable.ic_onboarding_3) | ||
contentDescription.set(context.resources.getString(R.string.onboarding_slide_3_title)) | ||
title.set(context.resources.getString(R.string.onboarding_slide_3_title)) | ||
description.set(context.resources.getString(R.string.onboarding_slide_3_description)) | ||
} | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
app/src/main/java/org/oppia/app/onboarding/OnboadingViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import androidx.databinding.ObservableField | ||
import androidx.lifecycle.ViewModel | ||
import org.oppia.app.viewmodel.ObservableViewModel | ||
import javax.inject.Inject | ||
|
||
/** [ViewModel] for [OnboardingFragment]. */ | ||
class OnboardingViewModel @Inject constructor() : ObservableViewModel() { | ||
val slideNumber = ObservableField<Int>(0) | ||
val totalNumberOfSlides = TOTAL_NUMBER_OF_SLIDES | ||
|
||
fun slideChanged(viewPagerSlide: ViewPagerSlide) { | ||
slideNumber.set(viewPagerSlide.ordinal) | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
app/src/main/java/org/oppia/app/onboarding/OnboardingActivity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import android.content.Context | ||
import android.content.Intent | ||
import android.os.Bundle | ||
import org.oppia.app.activity.InjectableAppCompatActivity | ||
import org.oppia.app.profile.ProfileActivity | ||
import javax.inject.Inject | ||
|
||
/** Activity that contains the onboarding flow for learners. */ | ||
class OnboardingActivity : InjectableAppCompatActivity(), RouteToProfileListListener { | ||
@Inject lateinit var onboardingActivityPresenter: OnboardingActivityPresenter | ||
|
||
companion object { | ||
fun createOnboardingActivity(context: Context): Intent { | ||
val intent = Intent(context, OnboardingActivity::class.java) | ||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) | ||
return intent | ||
} | ||
} | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
activityComponent.inject(this) | ||
onboardingActivityPresenter.handleOnCreate() | ||
} | ||
|
||
override fun routeToProfileList() { | ||
startActivity(ProfileActivity.createProfileActivity(this)) | ||
finish() | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
app/src/main/java/org/oppia/app/onboarding/OnboardingActivityPresenter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import androidx.appcompat.app.AppCompatActivity | ||
import org.oppia.app.R | ||
import org.oppia.app.activity.ActivityScope | ||
import javax.inject.Inject | ||
|
||
/** The presenter for [OnboardingActivity]. */ | ||
@ActivityScope | ||
class OnboardingActivityPresenter @Inject constructor(private val activity: AppCompatActivity) { | ||
fun handleOnCreate() { | ||
activity.setContentView(R.layout.onboarding_activity) | ||
if (getOnboardingFragment() == null) { | ||
activity.supportFragmentManager.beginTransaction().add( | ||
R.id.onboarding_fragment_placeholder, | ||
OnboardingFragment() | ||
).commitNow() | ||
} | ||
} | ||
|
||
private fun getOnboardingFragment(): OnboardingFragment? { | ||
return activity.supportFragmentManager.findFragmentById(R.id.onboarding_fragment_placeholder) as OnboardingFragment? | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
app/src/main/java/org/oppia/app/onboarding/OnboardingFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import android.content.Context | ||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import org.oppia.app.fragment.InjectableFragment | ||
import javax.inject.Inject | ||
|
||
/** Fragment that contains an onboarding flow of the app. */ | ||
class OnboardingFragment : InjectableFragment() { | ||
@Inject lateinit var onboardingFragmentPresenter: OnboardingFragmentPresenter | ||
|
||
override fun onAttach(context: Context) { | ||
super.onAttach(context) | ||
fragmentComponent.inject(this) | ||
} | ||
|
||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||
return onboardingFragmentPresenter.handleCreateView(inflater, container) | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
app/src/main/java/org/oppia/app/onboarding/OnboardingFragmentPresenter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.ImageView | ||
import android.widget.LinearLayout | ||
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.fragment.app.Fragment | ||
import androidx.viewpager.widget.ViewPager | ||
import org.oppia.app.R | ||
import org.oppia.app.databinding.OnboardingFragmentBinding | ||
import org.oppia.app.fragment.FragmentScope | ||
import org.oppia.app.viewmodel.ViewModelProvider | ||
import org.oppia.domain.onboarding.OnboardingFlowController | ||
import javax.inject.Inject | ||
|
||
/** The presenter for [OnboardingFragment]. */ | ||
@FragmentScope | ||
class OnboardingFragmentPresenter @Inject constructor( | ||
private val activity: AppCompatActivity, | ||
private val fragment: Fragment, | ||
private val onboardingFlowController: OnboardingFlowController, | ||
private val viewModelProvider: ViewModelProvider<OnboardingViewModel> | ||
) { | ||
private val dotsList = ArrayList<ImageView>() | ||
private lateinit var onboardingPagerAdapter: OnboardingPagerAdapter | ||
private val routeToProfileListener = activity as RouteToProfileListListener | ||
private lateinit var binding: OnboardingFragmentBinding | ||
|
||
fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { | ||
binding = OnboardingFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) | ||
// NB: Both the view model and lifecycle owner must be set in order to correctly bind LiveData elements to | ||
// data-bound view models. | ||
binding.let { | ||
it.lifecycleOwner = fragment | ||
it.presenter = this | ||
it.viewModel = getOnboardingViewModel() | ||
} | ||
setUpViewPager() | ||
addDots() | ||
return binding.root | ||
} | ||
|
||
private fun setUpViewPager() { | ||
onboardingPagerAdapter = OnboardingPagerAdapter(fragment.requireContext()) | ||
binding.onboardingSlideViewPager.adapter = onboardingPagerAdapter | ||
binding.onboardingSlideViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { | ||
override fun onPageScrollStateChanged(state: Int) { | ||
} | ||
|
||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { | ||
} | ||
|
||
override fun onPageSelected(position: Int) { | ||
getOnboardingViewModel().slideChanged(ViewPagerSlide.getSlideForPosition(position)) | ||
selectDot(position) | ||
} | ||
}) | ||
} | ||
|
||
fun clickOnGetStarted() { | ||
onboardingFlowController.markOnboardingFlowCompleted() | ||
routeToProfileListener.routeToProfileList() | ||
} | ||
|
||
fun clickOnSkip() { | ||
getOnboardingViewModel().slideChanged(ViewPagerSlide.SLIDE_3) | ||
binding.onboardingSlideViewPager.currentItem = ViewPagerSlide.SLIDE_3.ordinal | ||
} | ||
|
||
private fun getOnboardingViewModel(): OnboardingViewModel { | ||
return viewModelProvider.getForFragment(fragment, OnboardingViewModel::class.java) | ||
} | ||
|
||
private fun addDots() { | ||
val dotsLayout = binding.slideDotsContainer | ||
val dotIdList = ArrayList<Int>() | ||
dotIdList.add(R.id.onboarding_dot_0) | ||
dotIdList.add(R.id.onboarding_dot_1) | ||
dotIdList.add(R.id.onboarding_dot_2) | ||
dotIdList.add(R.id.onboarding_dot_3) | ||
for (index in 0 until TOTAL_NUMBER_OF_SLIDES) { | ||
val dotView = ImageView(activity) | ||
dotView.id = dotIdList[index] | ||
dotView.setImageResource(R.drawable.onboarding_dot_active) | ||
|
||
val params = LinearLayout.LayoutParams( | ||
activity.resources.getDimensionPixelSize(R.dimen.dot_width_height), | ||
activity.resources.getDimensionPixelSize(R.dimen.dot_width_height) | ||
) | ||
params.setMargins( | ||
activity.resources.getDimensionPixelSize(R.dimen.dot_gap), | ||
0, | ||
activity.resources.getDimensionPixelSize(R.dimen.dot_gap), | ||
0 | ||
) | ||
dotsLayout.addView(dotView, params) | ||
dotsList.add(dotView) | ||
} | ||
selectDot(0) | ||
} | ||
|
||
private fun selectDot(position: Int) { | ||
for (index in 0 until TOTAL_NUMBER_OF_SLIDES) { | ||
val alphaValue = if (index == position) 1.0F else 0.3F | ||
dotsList[index].alpha = alphaValue | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
app/src/main/java/org/oppia/app/onboarding/OnboardingPagerAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package org.oppia.app.onboarding | ||
|
||
import android.content.Context | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.viewpager.widget.PagerAdapter | ||
import org.oppia.app.databinding.OnboardingSlideBinding | ||
|
||
/** Adapter to control the slide details in onboarding flow. */ | ||
class OnboardingPagerAdapter(val context: Context) : PagerAdapter() { | ||
override fun instantiateItem(container: ViewGroup, position: Int): Any { | ||
val binding = OnboardingSlideBinding.inflate(LayoutInflater.from(context), container, false) | ||
val onboardingSlideViewModel = OnboardingSlideViewModel(context, ViewPagerSlide.getSlideForPosition(position)) | ||
binding.viewModel = onboardingSlideViewModel | ||
container.addView(binding.root) | ||
return binding.root | ||
} | ||
|
||
override fun getCount(): Int { | ||
return TOTAL_NUMBER_OF_SLIDES | ||
} | ||
|
||
override fun isViewFromObject(view: View, `object`: Any): Boolean { | ||
return view == `object` | ||
} | ||
|
||
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { | ||
container.removeView(`object` as ConstraintLayout) | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
app/src/main/java/org/oppia/app/onboarding/RouteToProfileListListener.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.oppia.app.onboarding | ||
|
||
/** Listener for when an activity should route to [ProfileActivity]. */ | ||
interface RouteToProfileListListener { | ||
fun routeToProfileList() | ||
} |
18 changes: 18 additions & 0 deletions
18
app/src/main/java/org/oppia/app/onboarding/ViewPagerSlide.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.oppia.app.onboarding | ||
|
||
/** Enum to store the slides of [OnboardingFragment] and get slide by position. */ | ||
enum class ViewPagerSlide(private var position: Int) { | ||
SLIDE_0(position = 0), | ||
SLIDE_1(position = 1), | ||
SLIDE_2(position = 2), | ||
SLIDE_3(position = 3); | ||
|
||
companion object { | ||
fun getSlideForPosition(position: Int): ViewPagerSlide { | ||
val ordinal = checkNotNull(values().map(ViewPagerSlide::position)[position]) { | ||
"No tab corresponding to position: $position" | ||
} | ||
return values()[ordinal] | ||
} | ||
} | ||
} |
Oops, something went wrong.