Commit b479ca4c authored by Wenyu Fu's avatar Wenyu Fu Committed by Commit Bot

Announce title for a11y when page changed in pager

Due to issues in Android ViewPager, screen reader can lose a11y focus
sometimes when switching between pages.

As work around, this CL adds an interface for each FirstRunFragment to
specify a11y focus when each page is populated on the screen.

Bug: 1094064
Change-Id: I44a3162834744980bc0a2a72c192b465d3c2211f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2458880
Commit-Queue: Wenyu Fu <wenyufu@chromium.org>
Auto-Submit: Wenyu Fu <wenyufu@chromium.org>
Reviewed-by: default avatarSky Malice <skym@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816868}
parent 8898fe3c
...@@ -11,6 +11,7 @@ import android.view.LayoutInflater; ...@@ -11,6 +11,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
...@@ -91,6 +92,12 @@ public class DataReductionProxyFirstRunFragment extends Fragment implements Firs ...@@ -91,6 +92,12 @@ public class DataReductionProxyFirstRunFragment extends Fragment implements Firs
view.getContext(), enableDataSaverSwitch.isChecked()); view.getContext(), enableDataSaverSwitch.isChecked());
} }
@Override
public void setInitialA11yFocus() {
final View title = getView().findViewById(R.id.title);
title.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
......
...@@ -8,6 +8,7 @@ import android.os.Bundle; ...@@ -8,6 +8,7 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button; import android.widget.Button;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
...@@ -68,6 +69,12 @@ public class DefaultSearchEngineFirstRunFragment extends Fragment implements Fir ...@@ -68,6 +69,12 @@ public class DefaultSearchEngineFirstRunFragment extends Fragment implements Fir
return rootView; return rootView;
} }
@Override
public void setInitialA11yFocus() {
final View title = getView().findViewById(R.id.chooser_title);
title.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
@Override @Override
public void setUserVisibleHint(boolean isVisibleToUser) { public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser); super.setUserVisibleHint(isVisibleToUser);
......
...@@ -378,7 +378,7 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa ...@@ -378,7 +378,7 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa
if (mPager.getCurrentItem() == 0) { if (mPager.getCurrentItem() == 0) {
abortFirstRunExperience(); abortFirstRunExperience();
} else { } else {
mPager.setCurrentItem(mPager.getCurrentItem() - 1, false); setCurrentItemForPager(mPager.getCurrentItem() - 1);
} }
} }
...@@ -545,12 +545,34 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa ...@@ -545,12 +545,34 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa
if (!didAcceptTermsOfService()) { if (!didAcceptTermsOfService()) {
return position == 0; return position == 0;
} }
if (!setCurrentItemForPager(position)) {
return false;
}
recordFreProgressHistogram(mFreProgressStates.get(position));
return true;
}
private boolean setCurrentItemForPager(int position) {
if (position >= mPagerAdapter.getCount()) { if (position >= mPagerAdapter.getCount()) {
completeFirstRunExperience(); completeFirstRunExperience();
return false; return false;
} }
mPager.setCurrentItem(position, false); mPager.setCurrentItem(position, false);
recordFreProgressHistogram(mFreProgressStates.get(position));
// Set A11y focus if possible. See https://crbug.com/1094064 for more context.
// * Screen reader can lose focus when switching between pages with ViewPager;
// * FragmentPagerStateAdapter is trying to limit access for the real fragment that we are
// creating / created;
// * Note that despite the function name and javadoc,
// FragmentPagerStateAdapter#instantiateItem returns cached fragments when possible. This
// should always be the case here as ViewPager#setCurrentItem will trigger instantiation if
// needed. This function call to #instantiateItem is not creating new fragment here but
// rather reading the ones already created.
Object currentFragment = mPagerAdapter.instantiateItem(mPager, position);
if (currentFragment instanceof FirstRunFragment) {
((FirstRunFragment) currentFragment).setInitialA11yFocus();
}
return true; return true;
} }
......
...@@ -27,6 +27,16 @@ public interface FirstRunFragment { ...@@ -27,6 +27,16 @@ public interface FirstRunFragment {
*/ */
FragmentActivity getActivity(); FragmentActivity getActivity();
/**
* Set the a11y focus when the fragment is shown on the screen.
*
* Android ViewPager cannot always assign the correct a11y focus automatically when switching
* between pages.
*
* See https://crbug.com/1094064 for more detail.
*/
void setInitialA11yFocus();
/** /**
* Convenience method to get {@link FirstRunPageDelegate}. * Convenience method to get {@link FirstRunPageDelegate}.
*/ */
......
...@@ -6,6 +6,8 @@ package org.chromium.chrome.browser.firstrun; ...@@ -6,6 +6,8 @@ package org.chromium.chrome.browser.firstrun;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
...@@ -83,4 +85,10 @@ public class SigninFirstRunFragment extends SigninFragmentBase implements FirstR ...@@ -83,4 +85,10 @@ public class SigninFirstRunFragment extends SigninFragmentBase implements FirstR
protected int getNegativeButtonTextId() { protected int getNegativeButtonTextId() {
return R.string.no_thanks; return R.string.no_thanks;
} }
@Override
public void setInitialA11yFocus() {
final View title = getView().findViewById(R.id.signin_title);
title.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
} }
...@@ -11,6 +11,7 @@ import android.view.LayoutInflater; ...@@ -11,6 +11,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.TextView; import android.widget.TextView;
...@@ -135,6 +136,11 @@ public class ToSAndUMAFirstRunFragment extends Fragment implements FirstRunFragm ...@@ -135,6 +136,11 @@ public class ToSAndUMAFirstRunFragment extends Fragment implements FirstRunFragm
} }
} }
@Override
public void setInitialA11yFocus() {
mTitle.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
@Override @Override
public void setUserVisibleHint(boolean isVisibleToUser) { public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser); super.setUserVisibleHint(isVisibleToUser);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment