Skip to content

Commit c214c98

Browse files
committed
Use custom tab item views for accessibility.
Affects: https://ebce-lyrasis.atlassian.net/browse/PP-3994
1 parent 9bec785 commit c214c98

4 files changed

Lines changed: 107 additions & 15 deletions

File tree

README-CHANGES.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@
11221122
</c:change>
11231123
</c:changes>
11241124
</c:release>
1125-
<c:release date="2026-04-06T12:57:14+00:00" is-open="true" ticket-system="org.lyrasis.jira" version="1.27.0">
1125+
<c:release date="2026-04-07T09:55:16+00:00" is-open="true" ticket-system="org.lyrasis.jira" version="1.27.0">
11261126
<c:changes>
11271127
<c:change date="2026-03-19T00:00:00+00:00" summary="Increase book details metadata text.">
11281128
<c:tickets>
@@ -1151,11 +1151,16 @@
11511151
</c:tickets>
11521152
</c:change>
11531153
<c:change date="2026-04-02T00:00:00+00:00" summary="Fix a missing sync on startup."/>
1154-
<c:change date="2026-04-06T12:57:14+00:00" summary="Improve screen reader behaviour for search results.">
1154+
<c:change date="2026-04-06T00:00:00+00:00" summary="Improve screen reader behaviour for search results.">
11551155
<c:tickets>
11561156
<c:ticket id="PP-3982"/>
11571157
</c:tickets>
11581158
</c:change>
1159+
<c:change date="2026-04-07T09:55:16+00:00" summary="Use custom tab item views for accessibility.">
1160+
<c:tickets>
1161+
<c:ticket id="PP-3994"/>
1162+
</c:tickets>
1163+
</c:change>
11591164
</c:changes>
11601165
</c:release>
11611166
</c:releases>

palace-ui/src/main/java/org/nypl/simplified/ui/main/MainTabsFragment.kt

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import android.view.LayoutInflater
55
import android.view.View
66
import android.view.ViewGroup
77
import android.widget.FrameLayout
8+
import android.widget.ImageView
9+
import android.widget.TextView
810
import androidx.fragment.app.Fragment
911
import com.google.android.material.tabs.TabLayout
1012
import com.io7m.jmulticlose.core.CloseableCollection
@@ -39,10 +41,10 @@ class MainTabsFragment : Fragment(), MainBackButtonConsumerType {
3941
private const val TAB_INDEX_SETTINGS = 3
4042
}
4143

42-
private lateinit var tabSettingsView: View
43-
private lateinit var tabReservationsView: View
44-
private lateinit var tabBooksView: View
45-
private lateinit var tabCatalogView: View
44+
private lateinit var tabSettingsView: TabLayout.TabView
45+
private lateinit var tabReservationsView: TabLayout.TabView
46+
private lateinit var tabBooksView: TabLayout.TabView
47+
private lateinit var tabCatalogView: TabLayout.TabView
4648
private lateinit var root: ViewGroup
4749
private lateinit var tabBooks: TabLayout.Tab
4850
private lateinit var tabCatalog: TabLayout.Tab
@@ -77,14 +79,39 @@ class MainTabsFragment : Fragment(), MainBackButtonConsumerType {
7779
*/
7880

7981
val tabStrip = (this.tabLayout.getChildAt(0) as ViewGroup)
80-
this.tabCatalog = this.tabLayout.getTabAt(TAB_INDEX_CATALOG)!!
81-
this.tabCatalogView = tabStrip.getChildAt(TAB_INDEX_CATALOG)!!
82-
this.tabBooks = this.tabLayout.getTabAt(TAB_INDEX_BOOKS)!!
83-
this.tabBooksView = tabStrip.getChildAt(TAB_INDEX_BOOKS)!!
84-
this.tabReservations = this.tabLayout.getTabAt(TAB_INDEX_RESERVATIONS)!!
85-
this.tabReservationsView = tabStrip.getChildAt(TAB_INDEX_RESERVATIONS)!!
86-
this.tabSettings = this.tabLayout.getTabAt(TAB_INDEX_SETTINGS)!!
87-
this.tabSettingsView = tabStrip.getChildAt(TAB_INDEX_SETTINGS)!!
82+
this.tabCatalog =
83+
this.tabLayout.getTabAt(TAB_INDEX_CATALOG)!!
84+
this.tabBooks =
85+
this.tabLayout.getTabAt(TAB_INDEX_BOOKS)!!
86+
this.tabReservations =
87+
this.tabLayout.getTabAt(TAB_INDEX_RESERVATIONS)!!
88+
this.tabSettings =
89+
this.tabLayout.getTabAt(TAB_INDEX_SETTINGS)!!
90+
91+
/*
92+
* We're forced to use custom views for tab items to comply with accessibility regulations:
93+
* Android tab items will ellipsize text when the device font size is set to the largest
94+
* values, and there's no way to stop it ellipsizing.
95+
*/
96+
97+
this.tabCatalog.setCustomView(R.layout.tab_item)
98+
this.tabBooks.setCustomView(R.layout.tab_item)
99+
this.tabReservations.setCustomView(R.layout.tab_item)
100+
this.tabSettings.setCustomView(R.layout.tab_item)
101+
102+
this.tabCatalogView =
103+
tabStrip.getChildAt(TAB_INDEX_CATALOG)!! as TabLayout.TabView
104+
this.tabBooksView =
105+
tabStrip.getChildAt(TAB_INDEX_BOOKS)!! as TabLayout.TabView
106+
this.tabReservationsView =
107+
tabStrip.getChildAt(TAB_INDEX_RESERVATIONS)!! as TabLayout.TabView
108+
this.tabSettingsView =
109+
tabStrip.getChildAt(TAB_INDEX_SETTINGS)!! as TabLayout.TabView
110+
111+
this.setIconAndText(TAB_CATALOG, this.tabCatalogView)
112+
this.setIconAndText(TAB_BOOKS, this.tabBooksView)
113+
this.setIconAndText(TAB_RESERVATIONS, this.tabReservationsView)
114+
this.setIconAndText(TAB_SETTINGS, this.tabSettingsView)
88115

89116
/*
90117
* Naturally, because even the simplest things on Android are completely broken, it's
@@ -141,6 +168,35 @@ class MainTabsFragment : Fragment(), MainBackButtonConsumerType {
141168
return this.root
142169
}
143170

171+
private fun setIconAndText(
172+
category: MainTabCategory,
173+
view: TabLayout.TabView
174+
) {
175+
val textView =
176+
view.findViewById<TextView>(R.id.customTabText)
177+
val imageView =
178+
view.findViewById<ImageView>(R.id.customTabIcon)
179+
180+
when (category) {
181+
TAB_CATALOG -> {
182+
textView.text = resources.getString(R.string.tabCatalog)
183+
imageView.setImageResource(R.drawable.tab_catalog)
184+
}
185+
TAB_BOOKS -> {
186+
textView.text = resources.getString(R.string.tabBooks)
187+
imageView.setImageResource(R.drawable.tab_books)
188+
}
189+
TAB_RESERVATIONS -> {
190+
textView.text = resources.getString(R.string.tabHolds)
191+
imageView.setImageResource(R.drawable.tab_holds)
192+
}
193+
TAB_SETTINGS -> {
194+
textView.text = resources.getString(R.string.tabSettings)
195+
imageView.setImageResource(R.drawable.tab_settings)
196+
}
197+
}
198+
}
199+
144200
override fun onStart() {
145201
super.onStart()
146202

palace-ui/src/main/res/layout/main_tabs.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@
2525
<com.google.android.material.tabs.TabLayout
2626
android:id="@+id/mainTabs"
2727
android:layout_width="0dp"
28-
android:layout_height="80dp"
28+
android:layout_height="wrap_content"
2929
app:layout_constraintBottom_toBottomOf="parent"
3030
app:layout_constraintEnd_toEndOf="parent"
3131
app:layout_constraintStart_toStartOf="parent"
3232
app:tabTextAppearance="@style/Palace.BottomNavigationView.TextActive"
3333
app:tabGravity="fill"
34+
app:tabPadding="0dp"
3435
app:tabMaxWidth="0dp"
3536
app:tabMode="fixed">
3637

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
4+
xmlns:app="http://schemas.android.com/apk/res-auto"
5+
android:layout_width="wrap_content"
6+
android:layout_height="match_parent">
7+
8+
<ImageView
9+
android:id="@+id/customTabIcon"
10+
android:layout_width="24dp"
11+
android:layout_height="24dp"
12+
android:layout_marginTop="8dp"
13+
android:src="@drawable/error"
14+
app:layout_constraintEnd_toEndOf="parent"
15+
app:layout_constraintStart_toStartOf="parent"
16+
app:layout_constraintTop_toTopOf="parent" />
17+
18+
<TextView
19+
android:id="@+id/customTabText"
20+
android:layout_width="wrap_content"
21+
android:layout_height="wrap_content"
22+
android:layout_marginTop="8dp"
23+
android:text="Tab"
24+
android:hyphenationFrequency="fullFast"
25+
android:gravity="center"
26+
app:layout_constraintEnd_toEndOf="parent"
27+
app:layout_constraintStart_toStartOf="parent"
28+
app:layout_constraintTop_toBottomOf="@id/customTabIcon" />
29+
30+
</androidx.constraintlayout.widget.ConstraintLayout>

0 commit comments

Comments
 (0)