Android Accessibility: sending several accessibility events on a single touch - android

Inside one of my recycle view adapters, I have a layout which displays an image and a checkbox.
I am adding accessibility to the app, and I want it so that when a user touches a picture, it will get a reading of the image and the current state of the checkbox (as in, "checked" or "unchecked", which is what the accessibility assistant reads, not true or false)
The two separate lines of code which I have used fit my purpose are as follows:
myImageView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
myCheckbox.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
But if I run that call on the click event, the first instruction is cut short and only the second one is heard. So I believe this might not be the way to go. I probably have to use all of the Accessibility classes provided by Android, but I have no clue where to start.
What should I do for the voice feedback to read "Image one, checked... Image two, unchecked".
Additional info:
I cannot use strings to get the wanted value from the checkbox boolean because the app is multilingual and instead of having to get all the string resources I would rather take advantage of the system.
Thank you,
everyone, for your time.

You can combine both items in a linearlayout and/or you can market the "Image one" part as a label for the checkbox. Both examples are shown below and taken from the link below them.
<LinearLayout
android:id="#+id/consumedContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="false"
android:orientation="horizontal">
<TextView
android:id="#+id/coffeeLimitLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_weight="1"
android:labelFor="#id/coffeeLimitValue"
android:text="#string/coffee_limit_label"
android:textAppearance="#style/TextAppearance.AppCompat.Title"/>
https://www.raywenderlich.com/182100/android-accessibility-tutorial-getting-started

Related

Group Views for TalkBack

I have two TextViews. Currently, When Talkback is enabled, the user has to swipe twice to read both TextViews. But I want the screen reader to read the TextViews one after another without any user input (Like WhatsApp reading LastSeen and Chat name in one go). How can I achieve this? Any help would be appreciated
You can set the content description to the layout containing these two views and set individual views as not important for accessibility to combine them.
For example:
<LinearLayout …
android:id="#+id/combinedLayout"
android:contentDescription="Last seen / chat name"
<TextView …
android:text="Last seen"
android:importantForAccessibility="no" />
<TextView …
android:text="Chat name"
android:importantForAccessibility="no"/>
</LinearLayout>
Or in code it would be something like:
combinedLayout.contentDescription = "add content description here"
If any elements are clickable, be careful with setting as not important to accessibility, always test to make sure it behaves as you would expect.
Check out my post about common accessibility issues :) https://medium.com/microsoft-mobile-engineering/android-accessibility-resolving-common-talkback-issues-3c45076bcdf6

Avoid impact to performance, when designing activity with more than 80 views

I'm new to android. I'm creating an application, which should handle more than 200 settings, mostly Boolean. Settings can be grouped by they type, there are 5 groups. I assume, that users won't like to configure and save each group separately,but would like to configure all the settings and by pressing save -> save all of them at one time, so scenario with having 5 different activities for each setting group doesn't suite.
What I've tried to do, is set up a TabHost, with separate tab for each group. After I've got "more than 80 views" warning, I've split up my layout, and now each group has own layout.xml;
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/cbSetting1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/strSetting1" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/cbSetting2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/strSetting2" />
</TableRow>
...
</TableLayout>
And I'm inflating those views onCreate:
View setting1View= getLayoutInflater().inflate(R.layout.group1_layout, null);
group1Tab.addView(view);
With this steps done, I'm avoiding "more than 80 views warning", but won't have it impact on performance, when all views are inflated -> activity will have more than 80 views in total?
Next question: should I get references to all CheckBoxes on my views onCreate:
CheckBox setting1 = (CheckBox)setting1View.findViewById(R.id.cbSetting1);
or should reference them on my saving button press, like:
onSaveClick{
Boolean setting1Value = ((CheckBox)setting1View.findViewById(R.id.cbSetting1)).value
}
or in some other way, to have as little performance impact as possible?
Is there any "good pattern", for designing apps with a lot of views?
Thanks in advance!
P.S. I know, that "best practice" questions are not recommended on StackOverflow, but I've tried to ask as defined questions as possible, and, hopefully, my post is showing at least my researching effort on the issue.
Update
My fault not mentioning it earlier - those settings are stored remotely, and are accessed using HTTP requests (using Web-api). Does suggestions about Preference activities/fragments and ListViews fit in this case?
Based on the way you have described your application, it seems like you have many similar views. I would recommend using a ListView in each of your tabs. ListViews very efficiently handle tons of views.
You will need to write a custom adapter for you ListViews, but you can do this cleverly in a way that doesn't call findViewById() all the time (using the ViewHolder pattern).
It is hard to give specific advice because you have not described exactly what these settings items will contain, but this general idea works well when you have long lists of (event potentially slightly different) views. This pattern would work if you want to have a lot of flexibility over you layout. If you want some standard settings behavior, check out PreferenceFragments, or check out Android's settings developer guide.
If its just boolean settings [i.e. Checkbox].
Then I would prefer trying PreferenceActivity, its just like another activity but preferably used for settings functionality. Also there is an easy way to group your settings element, try PreferenceCategory for grouping.
A small tutorial is available here.
CheckBoxPreference is what you need.
Hope this helps!

Best solution to merge/include an xml layout file multiple times in an activity layout

I'm building a flashcards app as a college project, and wanted a horizontally scrolling display of the cards. I've built an xml file for the flashcard design itself:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="#drawable/whitenote" android:padding="3dp">
<ImageButton
android:id="#+id/imageButtonPins"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" android:background="#color/transparent" android:src="#drawable/pinselector"/>
<TextView
android:id="#+id/textViewWord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/imageButton1"
android:layout_centerHorizontal="true"
android:text="Word" android:textColor="#color/black" android:paddingTop="30dp" android:textSize="20dp"/>
<TextView
android:id="#+id/textViewMeaning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textViewWord"
android:layout_centerHorizontal="true"
android:text="Meaning" android:textColor="#color/black"/>
</RelativeLayout>
I've also created the Class file.
In the activity layout, I have a few more elements and as such a linearlayout at the root level is necessary. I've been able to display a single flashcard for test purposes using and using layout inflater.
Question
In both the ways, in and layout inflater I've been unable to get the ImageButton working. My question is how do I get the button to work.
Update: Managed to get the ImageButton working using . Realised that I have to handle the onclick event in the activity, and not the Custom Adapter class. This should allow me to obtain the words too, as long as I can keep track of the "current" flashcard on display
Also, whats the best way to handle the scrolling for a flashcard app? My current plans so far is to use a HorizontalScrollView and customise it a bit, because I need (a) a swipe should make the flashcard move only to the next one (b) I need to focus on the "current" flashcard since I need some data from its children views (ie, the word).
Are you considering Fragments?
You can get some help with the ViewPager here.This is supported in Android 3.0 or above or Android 1.6 with the compatibility package.
http://geekyouup.blogspot.com/2011/07/viewpager-example-from-paug.html
If you do not wish to use the fragments, you can simply use the Gallery. This way, you can achieve the horizontal scrolling. (like in the Amazon app) without complex ViewPager.
For the second part of your question, take a look at the ViewPager.
A HorizontalScrollView or a Gallery are probably the most direct way of implementing this. I don't use Gallery-- but it is good to at least know it exists.
If you want a much more robust implementation, I agree with dcanh121 and think you should check out a Fragment based ViewPager. This will allow more options than just a View , but might be overkill depending on the goal. A fragment is basically the bizarre offspring of an Activity and a View, but don't quote me on that.
Also,
Inflating layouts is costly, so try to only inflate the XML into a View once, and reuse that View object. Try not to re-inflate the XML every time a new flashcard is drawn.

Keep the text inside a button for the next run of the application

I have a button that changes the text inside in it when clicked.
<Button android:id="#+id/timelinebtn"
android:text="Button1"
android:background="#android:color/transparent"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:padding="5dp" />
I have some other user clickable buttons in my app, and depending on what they click, the text inside this button (at first "Button1") changes to some other text with the code:
button1.setText("Changed the text to something other.");
My question is how can I keep the last text that the button was showing for the next run of the program.
Once again to make it a bit more clear - when I close the program, how the button can save the text inside it until the next run of the application.
You will need to persist the state somewhere, perhaps the fastest way would be using the shared preferences.
You can read this, it describes all ways of storing data in android.

Custom listview with two buttons in each row

I have spent literally two days trying to sort this issue. If anyone could help I would be massively appreciative.
What I'm trying to achieve:
Have a ListView, whereby the player can add new entries (players), through a text field (for the player name), and then a submit button. In each field of the ListView, I display the player name, and then two ImageButtons. One with a male symbol, and one with a female symbol. The male symbol is toggled by default, and the user can set the player as being male or female by toggling either the male button or the female button. Finally, once the user moves onto the next screen (a new activity), the application will save the player names and the attached sex to some form of storage and proceed to the next activity.
What I have achieved:
I have a simple array adapter, which upon the player adding a new player name to the list, I run the notifyDataSetChanged() on it. The adapter also is set to use a custom row layout file. Inside the layout file, it looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<RelativeLayout android:layout_height="wrap_content"
android:layout_width="fill_parent" android:id="#+id/relativeLayout1" android:layout_marginTop="5dp">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/playerName"
android:layout_centerVertical="true" android:text="Derp" android:textStyle="bold" android:layout_marginLeft="5dp" android:textSize="22dp" android:textColor="#color/male_blue"></TextView>
<ImageButton android:layout_height="60dp"
android:layout_width="60dp" android:onClick="maleClickHandler"
android:src="#drawable/male_icon_settings" android:id="#+id/buttonA" android:layout_alignParentRight="true" android:layout_marginRight="65dp"></ImageButton>
<ImageButton android:onClick="femaleClickHandler"
android:layout_height="60dp" android:layout_width="60dp" android:id="#+id/buttonB"
android:layout_alignParentRight="true" android:layout_marginRight="5dp" android:src="#drawable/female_icon_settings"></ImageButton>
</RelativeLayout>
</LinearLayout>
The two buttons on each row reference to methods in the class file. Here is my code for this:
public void maleClickHandler(View v) {
RelativeLayout vwParentRow = (RelativeLayout) v.getParent();
ImageButton maleButton = (ImageButton) vwParentRow.getChildAt(1);
maleButton.setImageDrawable(getResources().getDrawable(
R.drawable.male_icon_selected));
vwParentRow.refreshDrawableState();
}
public void femaleClickHandler(View v) {
RelativeLayout vwParentRow = (RelativeLayout) v.getParent();
ImageButton femaleButton = (ImageButton) vwParentRow.getChildAt(2);
femaleButton.setImageDrawable(getResources().getDrawable(
R.drawable.female_icon_selected));
vwParentRow.refreshDrawableState();
}
I haven't yet implemented any inter-connectivity between these two buttons, to allow only one to be active at a time, or to even untoggle one, since I think I might be taking the wrong approach entirely.
The problem:
Upon adding new entries to the list, AFTER toggling one and/or the other male/female buttons, things get really buggy, and the male/female toggled icon might move as it should, along with the attached player string, or more likely, those toggled will stay on that first row (array position 0 of the list), or even move into the second list position, AND copy themselves as being toggled onto the row above.
How you can help...?
I have attached an image below of my screen, from the emulator, to help illustrate my points
Screenshot!
I think that I might need to use some form of custom adapter; I have done so much reading around on the subject, but I can't find anything relevant to what I am trying to achieve, so if you could point me in the right direction, or even try and put together the most basic solution to this type of problem, I would be very grateful.
Finally, when I get this working, which form of storage would be best for storing player names, and their sex? I would like the user to be able to keep the player list after they quit the application and restarted it.
Thanks for any help! :)
You will need to use a Custom Adapter, which in itself should be able to track the male/female flag for each of it's entries.
Your method will not work since the state of the buttons are managed by the getView method of the adapter. Even if you change them by digging through the children, the next time when the getView method is called, it's going to mess up things.
A lot of this depends on how many players you expect to have in your game. If it's a number that would likely fit on one screen (or very close to it), the ListView is actually unnecessary. ListViews and adapters aren't really a convenience method as much as they are a tool to improve performance. They only keep in memory what is on the screen and recycle old, already-displayed Views for new rows when you scroll--this is why some of your button states are being copied to different rows.
There are a couple of ways you could fix this:
You could write a custom adapter yourself as Kumar Bibek suggests. In this adapter, you would want to override the getView() method to make sure each button has the correct state each time the method is called.
You could also simply use a ScrollView populated with a few of your rows manually if you don't have enough data to warrant using a ListView. This way you wouldn't need to worry about your rows being recycled and button states being out of wack.
In addition, you might want to look into using a RadioGroup for the gender selector (I can't think of a much better use for radio buttons since they are made to be mutually exclusive).
Also, the outer LinearLayout in your row XML file looks unnecessary.
As far as storage, you could either use an SQLite database or SharedPreferences. SharedPreferences requires no setup, but I feel like an SQLite database is more suited to your needs.

Categories

Resources