From 26ed80edea1d512476dcdc69855d2082d3473818 Mon Sep 17 00:00:00 2001 From: Vishwajith Shettigar <76042077+Vishwajith-Shettigar@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:07:54 +0530 Subject: [PATCH] Fix #4739 Talkback does not read the expected text (#5152) ## Explanation Fix #4739, edittext requesting focus only when reader is off will resolve this issue. ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only Before fix https://github.com/oppia/oppia-android/assets/76042077/41bc96b4-3fe1-4688-a77b-02bfdbd22782 After fix Talkback On https://github.com/oppia/oppia-android/assets/76042077/a01da3dc-8848-4632-a8c0-17ce3e409beb Talkback Off https://github.com/oppia/oppia-android/assets/76042077/beac309e-16d8-496f-bc09-af8de634536b If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide)) - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing --- .../profile/PinPasswordActivityPresenter.kt | 10 ++++++++- .../app/profile/PinPasswordActivityTest.kt | 21 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/profile/PinPasswordActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/profile/PinPasswordActivityPresenter.kt index a3e262baf63..57c999e2586 100644 --- a/app/src/main/java/org/oppia/android/app/profile/PinPasswordActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/profile/PinPasswordActivityPresenter.kt @@ -15,6 +15,7 @@ import org.oppia.android.app.utility.lifecycle.LifecycleSafeTimerFactory import org.oppia.android.app.viewmodel.ViewModelProvider import org.oppia.android.databinding.PinPasswordActivityBinding import org.oppia.android.domain.profile.ProfileManagementController +import org.oppia.android.util.accessibility.AccessibilityService import org.oppia.android.util.data.AsyncResult import org.oppia.android.util.data.DataProviders.Companion.toLiveData import javax.inject.Inject @@ -31,6 +32,7 @@ class PinPasswordActivityPresenter @Inject constructor( private val viewModelProvider: ViewModelProvider, private val resourceHandler: AppLanguageResourceHandler ) { + @Inject lateinit var accessibilityService: AccessibilityService private val pinViewModel by lazy { getPinPasswordViewModel() } @@ -69,7 +71,13 @@ class PinPasswordActivityPresenter @Inject constructor( ) } } - binding.pinPasswordInputPinEditText.requestFocus() + + // If the screen reader is off, the EditText will receive focus. + // If the screen reader is on, the EditText won't receive focus. + // This is needed because requesting focus on the EditText when the screen reader is on gives TalkBack priority over other views in the screen, ignoring view hierachy. + if (!accessibilityService.isScreenReaderEnabled()) + binding.pinPasswordInputPinEditText.requestFocus() + // [onTextChanged] is a extension function defined at [TextInputEditTextHelper] binding.pinPasswordInputPinEditText.onTextChanged { pin -> pin?.let { inputtedPin -> diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt index f1afe3b1393..16ce38b184e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt @@ -98,6 +98,7 @@ import org.oppia.android.testing.threading.TestCoroutineDispatchers import org.oppia.android.testing.threading.TestDispatcherModule import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule +import org.oppia.android.util.accessibility.FakeAccessibilityService import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule import org.oppia.android.util.gcsresource.GcsResourceModule @@ -147,6 +148,9 @@ class PinPasswordActivityTest { @Inject lateinit var editTextInputAction: EditTextInputAction + @Inject + lateinit var fakeAccessibilityService: FakeAccessibilityService + private val adminPin = "12345" private val adminId = 0 private val userId = 1 @@ -181,7 +185,8 @@ class PinPasswordActivityTest { } @Test - fun testPinPassword_withAdmin_keyboardIsVisibleByDefault() { + fun testPinPassword_withAdmin_screenReaderOff_keyboardIsVisible() { + fakeAccessibilityService.setScreenReaderEnabled(false) ActivityScenario.launch( PinPasswordActivity.createPinPasswordActivityIntent( context = context, @@ -193,6 +198,20 @@ class PinPasswordActivityTest { } } + @Test + fun testPinPassword_withAdmin_screenReaderOn_keyboardIsNotVisible() { + fakeAccessibilityService.setScreenReaderEnabled(true) + ActivityScenario.launch( + PinPasswordActivity.createPinPasswordActivityIntent( + context = context, + adminPin = adminPin, + profileId = adminId + ) + ).use { + onView(withId(R.id.pin_password_input_pin_edit_text)).check(matches(not(hasFocus()))) + } + } + @Test fun testPinPassword_withAdmin_inputCorrectPin_opensHomeActivity() { ActivityScenario.launch(