From 2dd84ec50a518e063d0b3180bc3d46051ed536a8 Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Mon, 18 May 2026 23:30:21 +0500 Subject: [PATCH] countdown now starts after scoll --- .../ui/onboarding/OnboardingActivity.kt | 6 +- .../ui/onboarding/OnboardingFragment.kt | 30 ++++ .../main/res/layout/activity_onboarding.xml | 2 + .../res/layout/fragment_onboarding_slide.xml | 135 ++++++++++-------- app/src/main/res/values-b+dv/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 6 files changed, 111 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt index 14eb460..77c8e9f 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt @@ -42,6 +42,10 @@ class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback { if (isChecked) selectLanguage(if (checkedId == R.id.btnLangEnglish) "en" else "dv") } + supportFragmentManager.setFragmentResultListener(OnboardingFragment.RESULT_SCROLLED_TO_BOTTOM, this) { _, _ -> + startGetStartedCountdown() + } + binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { binding.languageSection.visibility = if (position == 0) View.VISIBLE else View.GONE @@ -51,7 +55,6 @@ class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback { else -> true } updateButtons(position, adapter.itemCount) - if (position == adapter.itemCount - 1) startGetStartedCountdown() } }) @@ -114,6 +117,7 @@ class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback { val isLast = position == count - 1 binding.btnGetStarted.visibility = if (isLast) View.VISIBLE else View.GONE + if (isLast) binding.btnGetStarted.isEnabled = false binding.btnNext.visibility = if (isLast) View.GONE else View.VISIBLE binding.btnNext.isEnabled = when (position) { diff --git a/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingFragment.kt index d146418..af815a4 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingFragment.kt @@ -4,6 +4,8 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.ViewTreeObserver +import android.widget.ScrollView import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import sh.sar.basedbank.databinding.FragmentOnboardingSlideBinding @@ -12,6 +14,7 @@ class OnboardingFragment : Fragment() { private var _binding: FragmentOnboardingSlideBinding? = null private val binding get() = _binding!! + private var scrolledToBottom = false override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = FragmentOnboardingSlideBinding.inflate(inflater, container, false) @@ -25,6 +28,7 @@ class OnboardingFragment : Fragment() { val isFirst = requireArguments().getBoolean(ARG_IS_FIRST, false) val isLast = requireArguments().getBoolean(ARG_IS_LAST, false) + binding.icon.visibility = if (isLast) View.GONE else View.VISIBLE binding.icon.setImageResource(icon) binding.title.text = getString(titleRes) binding.description.text = getString(descRes) @@ -32,6 +36,31 @@ class OnboardingFragment : Fragment() { // On the first slide, show the two placeholder cards for upcoming banks binding.placeholderCards.visibility = if (isFirst) View.VISIBLE else View.GONE + + if (isLast) setupScrollToBottomDetection() + } + + private fun setupScrollToBottomDetection() { + val scrollView = binding.scrollView + // If content fits without scrolling, fire immediately after layout + scrollView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + scrollView.viewTreeObserver.removeOnGlobalLayoutListener(this) + val child = scrollView.getChildAt(0) ?: return + if (child.height <= scrollView.height) notifyScrolledToBottom() + } + }) + scrollView.setOnScrollChangeListener { v, _, scrollY, _, _ -> + val sv = v as ScrollView + val child = sv.getChildAt(0) ?: return@setOnScrollChangeListener + if (scrollY + sv.height >= child.height) notifyScrolledToBottom() + } + } + + private fun notifyScrolledToBottom() { + if (scrolledToBottom) return + scrolledToBottom = true + parentFragmentManager.setFragmentResult(RESULT_SCROLLED_TO_BOTTOM, Bundle.EMPTY) } override fun onDestroyView() { @@ -40,6 +69,7 @@ class OnboardingFragment : Fragment() { } companion object { + const val RESULT_SCROLLED_TO_BOTTOM = "scroll_to_bottom" private const val ARG_TITLE = "title" private const val ARG_DESC = "desc" private const val ARG_ICON = "icon" diff --git a/app/src/main/res/layout/activity_onboarding.xml b/app/src/main/res/layout/activity_onboarding.xml index ba8178f..e60b7cc 100644 --- a/app/src/main/res/layout/activity_onboarding.xml +++ b/app/src/main/res/layout/activity_onboarding.xml @@ -79,6 +79,8 @@ android:background="@null" android:layout_gravity="center_horizontal" android:layout_marginBottom="24dp" + android:clickable="false" + android:focusable="false" app:tabBackground="@drawable/tab_indicator_selector" app:tabGravity="center" app:tabIndicatorHeight="0dp" diff --git a/app/src/main/res/layout/fragment_onboarding_slide.xml b/app/src/main/res/layout/fragment_onboarding_slide.xml index 2405f08..ac27175 100644 --- a/app/src/main/res/layout/fragment_onboarding_slide.xml +++ b/app/src/main/res/layout/fragment_onboarding_slide.xml @@ -1,87 +1,96 @@ - + android:orientation="vertical" + android:gravity="center_horizontal" + android:paddingHorizontal="32dp" + android:paddingTop="64dp" + android:paddingBottom="16dp"> - + + + android:textAppearance="?attr/textAppearanceHeadlineMedium" + android:textColor="?attr/colorOnSurface" + android:gravity="center" + android:layout_marginBottom="16dp" /> - + - - - - - + android:orientation="vertical"> + android:gravity="center" + android:lineSpacingMultiplier="1.4" /> - + + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginTop="40dp" + android:visibility="gone"> - + - + + + + + + + + - - + diff --git a/app/src/main/res/values-b+dv/strings.xml b/app/src/main/res/values-b+dv/strings.xml index 5bb8e6d..24268c7 100644 --- a/app/src/main/res/values-b+dv/strings.xml +++ b/app/src/main/res/values-b+dv/strings.xml @@ -10,7 +10,7 @@ އިތުރު ބޭންކްތައް ހިމެނެނީ އިތުރު ބޭންކްތަކަށް ސަޕޯޓް ލިބޭ ގޮތަށް ތައްޔާރުވަމުން ދަނީ. ދިވެހިރާއްޖޭގެ ބޭންކްތަކަށް ސަޕޯޓް ފަހި ވަމުން ދިޔަ ވަރަކަށް ހިމަނެމުން ދޭ. ފެށޭ ގޮތަށް ތައްޔާރު - ތިޔަ ބޭންކު ކްރެޑެންޝަލް ޖެހި، ތިޔަ އެކައުންޓްތައް ބަލާ. ތިޔަ ޑޭޓާ ހިފެހެއްޓޭ ތަނަކީ ހަމައެކަނި ތިޔަ ފޯނު. + ތިޔަ ބޭންކު ކްރެޑެންޝަލް ޖެހި، ތިޔަ އެކައުންޓްތައް ބަލާ. ތިޔަ ޑޭޓާ ހިފެހެއްޓޭ ތަނަކީ ހަމައެކަނި ތިޔަ ފޯނު.\n\nDhiraagu އާއި Ooredoo ގެ API ބޭނުންކޮށްގެން ފޯން ނަންބަރުގެ ތަފްސީލު ބެލޭ.\n\nމި އެޕް ތިޔައާ ބެހޭ ތަފްސީލެއް ނެހެދޭ، ޑިވެލޮޕަރަށް ވެސް ނުފޮނުވާ. ހުރިހާ ޑޭޓާ ހިފެހެއްޓޭ ތަނަކީ ހަމައެކަނި ތިޔަ ފޯނު. ފަހުން ލިބޭ ދެން ފަށާ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7234cb2..c8df139 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,7 +9,7 @@ More Banks Coming Support for additional banks is on the way. Stay tuned as we expand coverage across the Maldives. Before You Begin - BasedBank is an independent, third-party app. It is not affiliated with, endorsed by, or officially supported by any bank or financial institution.\n\nThis app works by logging into your internet banking services directly using your credentials and communicating with bank APIs. It is built using techniques derived from reverse-engineered official bank apps. Behaviour may change or break without notice if banks update their systems.\n\nDhiraagu and Ooredoo APIs are used for phone number and package lookups.\n\nBy tapping Get Started, you acknowledge and accept that:\n\n• Errors, failures, or service interruptions may occur at any time\n• Your bank may detect third-party access and apply restrictions or take other actions against your account\n• The developer of this app is not liable for any loss, damage, or consequences arising from your use of this app\n• You use this app entirely at your own risk + BasedBank is an independent, third-party app. It is not affiliated with, endorsed by, or officially supported by any bank or financial institution.\n\nThis app works by logging into your internet banking services directly using your credentials and communicating with bank APIs. It is built using techniques derived from reverse-engineered official bank apps. Behaviour may change or break without notice if banks update their systems.\n\nDhiraagu and Ooredoo APIs are used to look up details about phone numbers.\n\nThis app does not collect any analytics, telemetry, or personal data, and does not transmit any information about you or your usage to the developer. Everything stays entirely on your device.\n\nBy tapping Get Started, you acknowledge and accept that:\n\n• Errors, failures, or service interruptions may occur at any time\n• Your bank may detect third-party access and apply restrictions or take other actions against your account\n• The developer of this app is not liable for any loss, damage, or consequences arising from your use of this app\n• You use this app entirely at your own risk Coming Soon Next Get Started