-
-
Notifications
You must be signed in to change notification settings - Fork 389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "Refresh" accessibility menu #3121
Conversation
Per https://developer.android.com/reference/androidx/swiperefreshlayout/widget/SwipeRefreshLayout the layout does not provide accessibility events, and a menu item should be provided as an alternative method for refreshing the content. In `TimelineFragment`: - Implement the `MenuProvider` interface so it can populate the action bar menu in activities that host the fragment - Create a "Refresh" menu item, and refresh the state when it is selected `MainActivity` has to change how the menu is created, so that fragments can add items to it. In `MainActivity`: - Call `setSupportActionBar` so `mainToolbar` participates in menus - Implement the `MenuProvider` interface, and move menu creation there - Set the title via supportActionBar
This does the work for Before I do the others, there is a Options I looked at:
But the methods couldn't have the same names as the framework methods, and would need to take additional parameters (the fragment, the activity context, the ID of the SwipeRefreshLayout). This feels clunky. Also, there's no way for the tooling to remind you to call these methods.
Attractive, but doesn't work because these fragments already inherit from SFragment, and can only inherit from one class. This menu code could be moved in to SFragment, and SFragment could expose a "hasRefreshMenu" property that subclasses could set to true and would activate the functionality in SFragment. But my understanding is that SFragment is due a refactoring, so things that complicate the SFragment code and its relationship with subclasses is probably not a good idea.
On the one hand, I'm not a huge fan of duplicating code. On the other hand, it's probably the cleanest solution at the moment, and it does mean that if you're reading the code its very clear where the refresh menu is coming from without having to chase down layers of nesting. Thoughts? |
Option 3 it is. Done. |
# Conflicts: # app/src/main/java/com/keylesspalace/tusky/MainActivity.kt # app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt # app/src/main/res/values/strings.xml
SwipeRefreshLayouts in:
|
Also, fix the colour of the refresh progress indicator
Make `tabs` `var` instead of `val` in `MainPagerAdapter` so it can be updated when tabs change. Then detach the `tabLayoutMediator`, update the tabs, and call `notifyItemRangeChanged` in `setupTabs()`. This fixes a bug (not sure if it's this code, or in ViewPager2) where assigning a new adapter to the view pager seemed to result in a leak of one or more fragments. This wasn't user-visible, but it's a leak, and it becomes user-visible when fragments want to display menus. This also fixes two other bugs: 1. Be on the left-most tab. Scroll down a bit. Then modify the tabs at "Account preferences > tabs", but keep the left-most tab as-is. Then go back to MainActivity. Your reading position in the left-most tab has been jumped to the top. 2. Be on any non-left-most tab. Then modify the tab list by reordering tabs (adding/removing tabs is also OK). Then go back to MainActivity. Your tab selection has been overridden, and the left-most tab has been selected. Because the fragments are not destroyed unnecessarily your reading position is retained. And it remembers the tab you had selected, and as long as that tab is still present you will be returned to it, even if it's changed position in the list. Fixes #3251
Using "collapseActionView" requires the user to press "Back" twice to exit the activity, which is not acceptable.
Previous code had the toolbar in the fragment's layout. Refactor to make consistent with other activities, and move the toolbar in to the activity layout. Implement MenuProvider in ViewThreadFragment to adjust the menu in the activity.
# Conflicts: # app/src/main/java/com/keylesspalace/tusky/MainActivity.kt # app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt
Be consistent with the layout resource files, which have an activity/fragment prefix, then the lower_snake_case name of the activity or fragment it's for.
Should be squash merged |
I'm still not convinced this is even a problem 🤔 |
https://developer.android.com/reference/androidx/swiperefreshlayout/widget/SwipeRefreshLayout has the explanation:
|
Yes I have seen that, I don't think it is a good idea (and I don't know a single app that does that). I'd leave it as it is, or add an accessibility action. |
Web browsers. I just checked Chrome and Firefox on my device, they both have "Refresh" or equivalent functionality accessible by swipe and menu access.
You keep saying this, but I don't understand how that would work in practice. My understanding is that accessibility actions need to be added to a view. But there's no available view to add a "swipe to refresh" accessibility action to.
All those problems are why the guidelines say "Add a menu item". So I feel like I'm missing something. When you say "add an accessibility action", which view, specifically, are you suggesting that the accessibility action should be added to? |
# Conflicts: # app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
I tried putting it on the main toolbar, Talkback goes "Home, press to activate, actions available".
We jump to top when clicking it in MainActivity. I see no problem with that and it would make sense to do the same in other views as well. |
But it's not just about Talkback:
(emphasis mine) The whole point of the menu is to provide an accessible and discoverable alternative to swiping. Any solution that is not both accessible and discoverable doesn't make sense. What, specifically, is the objection to the menu on these fragments? Other fragments in the app have menus. |
I think it is confusing to have options in the same menu where some apply to the current fragment and others have nothing to do with (in MainActivity), also I would not expect to have a menu item for things I can also do otherwise. But I guess I'll have to live with it because accessibility is more important. |
That doesn't happen. This code uses the That's this code in the fragments:
and the 3-arg version of |
Just in case you want to convince yourself of this, fetch this branch, modify Then swipe between the fragments in |
Yes I know it is technically a different menu, still shows up in the same place |
@@ -133,6 +148,27 @@ class AccountMediaFragment : | |||
} | |||
} | |||
|
|||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AccountMediaFragment and other fragments in the AccountActivity should only be refreshed together. If we are doing this we need to at least be consistent
MainActivity: Every Fragment has an individual swipe to refresh. The new menu refreshes the individual, active fragment ✅
AccountActivity: There is one swipe to refresh. It refreshes the activity as well as all the fragments. The menu options just refreshes the active fragment now 🟥 If it is supposed to improve the accessibilty of the swipe to refresh, it needs to refresh the same thing.
Actually when I think about it, having the menu option refresh all fragments, even in MainActivity and SearchActivity, could be a good idea and would lessen my concerns of it being confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AccountActivity: There is one swipe to refresh. It refreshes the activity as well as all the fragments. The menu options just refreshes the active fragment now 🟥 If it is supposed to improve the accessibilty of the swipe to refresh, it needs to refresh the same thing.
That makes sense. It's an oversight that it doesn't. I'll fix that. [Edit: done]
Actually when I think about it, having the menu option refresh all fragments, even in MainActivity and SearchActivity, could be a good idea and would lessen my concerns of it being confusing.
That contradicts the previous paragraph, where you just said "it needs to refresh the same thing".
The menu should behave identically to the swipe gesture.
android:id="@+id/action_refresh" | ||
android:title="@string/action_refresh" | ||
app:showAsAction="never" /> | ||
</menu> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have 1 refresh menu instead all these duplicate files please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that, but I figured:
- I plan on extending some of these to add additional menu items:
For example:
- in Notifications the "Clear" and "Filter" controls can move in to the menu
- on a timeline having a menu with "Hide boosts" and "Hide replies" (or "Show...") to temporarily override (or adjust) the preference
- when viewing edits, an option to toggle the display of what's changed
etc.
- It makes it easier to navigate the code. If you want to see what menu an activity or fragment uses you only have to open one file.
Some timelines don't have swipetorefresh enabled (e.g., those shown on AccountActivity). In those cases don't add the refresh menu, rely on the hosting activity to provide it. Update AccountActivity to provide the refresh menu item.
Per https://developer.android.com/reference/androidx/swiperefreshlayout/widget/SwipeRefreshLayout the layout does not provide accessibility events, and a menu item should be provided as an alternative method for refreshing the content.
In fragments:
MenuProvider
interface so it can populate the action bar menu in activities that host the fragmentIn activities:
setSupportActionBar
if not already done, so the toolbar participates in menus