For example, after setting Text in TextView to '347309', TalkBack should read "three, four, seven, three, zero(or o), nine."
But it announced "three hundred forty- seven thousand thirty nine."
In another case,
I set text 'API' (Application Programming Interface).
I want TalkBack to announce "A-P-I," but it announces "eipi" or "eipaɪ."
How do I get TalkBack to announce correctly?
Click here to check code. You need to take char array of that string and make separate each char with appending space and set that string as a content description to your view.
Here's the code :
Var str="347309"
textView.setContentDescription =getCharFromText(str)
fun getCharFromText(str:String):String
{
Var sb= StringBuilder()
foreach(c in str.charArray())
{
sb.append("")
sb.append(c).append(" ")
}
return sb.tostring()
}
Talkback has built-in functionality to adjust how text is read. By swiping up or down the screen, the user is able to go from default to reading out the text letter-by-letter if they need to.
It's preferable to allow the user to control this via existing controls, rather than force this choice programmatically.
Related
I am trying to create a small game with the following components:
9 cells - in a GridView
some words (that have to be introduced in the table, each on a cell)
TextToSpeech - on each cell
Each single cell contains one single word and the user has to choose one of the words displayed below in order to complete the cell (2 words are supposed to be in a cell).
Everything works perfectly, the only problem is that the TextToSpeech is being activated once the user chooses the right word, but I would want it to be one step forward. That means, once the user chooses the right word for ONE cell, the TextToSpeech should be automatically activated for the NEXT cell, so once the user has chosen the right word, he should hear the next word from the next cell.
These cells don't have ids, they are in the MainActivity, like this:
private fun setData() {
dataBeanArrayList = ArrayList<CellDataBean>()
val cellDataBean = CellDataBean()
//we store in the var cellDataBean both texts
//according to the class CellDataBean
cellDataBean.text_one = "Hello"
cellDataBean.text_two = "World"
dataBeanArrayList!!.add(cellDataBean)
val cellDataBean1 = CellDataBean()
cellDataBean1.text_one = "Okay"
cellDataBean1.text_two = "Not bad"
If I implement a new text view (which is not preferable), the TextToSpeech only works like I want for the first cell, once you press on this:
starttv.setOnClickListener {
if (count == 0) {
isstart = true
val text: String = dataBeanArrayList[count].text_1
textToSpeech!!.speak(text, TextToSpeech.QUEUE_FLUSH, null)
dataBeanArrayList[count].isSelected = true
cellAdapter!!.notifyDataSetChanged()
}
}
I am trying to implement something like: (where 'mainbacklay' is the ID from the cell)
when(vh.mainbacklay)[position]==0{
// here the text to speech should be enabled for the text from the second cell with the position 1
}
So when the position 2 from the cell is activated, the text to speech should be enabled for the text with the third position and so on.
Could someone help me figure this out, please?
Thank you.
I don't have a clear picture of exactly how your app operates, but I think you want something like this:
fun setAnswer(cellNumber: Int, text: String) {
// Update the data with the selected text etc
// Announce the text for cellNumber+1, or a fallback when there is no next cell
val message = dataBeans.getOrNull(cellNumber + 1)?.text_1 ?: "You're done!"
textToSpeech.speak(message, TextToSpeech.QUEUE_FLUSH, null)
}
and then whenever your event (a click or whatever) happens for cell n, you call that function. It takes care of handling that event, managing the overall state, and doing anything that needs to happen as a result (like announcing the next cell's contents, or moving to an endgame screen, etc.
Basically you don't want your individual cells / TextViews / ViewHolders managing that overall state and interacting with each other and each other's data. Just hand it off to a central function or component that manages what's going on, and tells the UI what to display. Makes it a lot easier!
Hope that helps, I can only be general without seeing exactly what you're doing
I am using library input-mask-android to format the text as user is typing.
I have an array of phone number masks. By default, the very first mask in the array is selected. The user can choose a different mask using the Spinner. But when the user selects a mask using the Spinner, it does not work as he would like.
Suppose the array of masks contains two masks: ["+12 - ###", "+34 - ###"]. If the user selects the second mask, then the following will appear when typing into the EditText:
Entered 5 will:
+34-512.
That is, after entering it will automatically put the key characters of the previous mask.
My code in Kotlin:
val listener: MaskedTextChangedListener = installOn(
etPhoneNumber!!,
maskT,
affineFormats, AffinityCalculationStrategy.PREFIX,
object : ValueListener {
override fun onTextChanged(
maskFilled: Boolean,
extractedValue: String,
formattedValue: String
) {
logValueListener(maskFilled, extractedValue, formattedValue)
Log.e("CHANGE FORMAT:", affineFormats.toString())
}
}
)
maskT - is the selected mask
affineFormats - dynamic array where the last mask is stored.
Any suggestions would be greatly appreciated.
input-mask-android library author here.
The installOn method won't suit your needs. You've got to manually initialise a MaskedTextChangedListener, then call an addTextChangedListener method on your EditText. On mask select, you've got to make sure the previous listener is removed (by calling a removeTextChangedListener on your EditText).
The installOn method does not consider there could be other TextWatcher instances attached to your EditText. Thus, all of those installed listeners are trying to take over the text, adding their own "+12" and "+34" prefixes simultaneously.
I want the user to type in his or her Facebook account-link (don't have a better solution atm).
Now, when the user clicks the edittext it is supposed to say : "www.facebook.com/". Now the cursor is supposed to be at the END of the edittext (after the "/") and the user is not supposed to delete the first letters so that the "www.facebook.com/" stays exactly where it is. This will have the user to ONLY type in his or her facebook name and therefore connect the profile.
Is there a way of doing this?
Thank you :)
You can do that by using the event "TextChanged" and in your code validate if the size is big than your string, like that:
if (((EditText)sender).Text.Length >= 17)
{
((EditText)sender).Text = e.NewTextValue;
}
else
{
((EditText)sender).Text = "www.facebook.com/";
}
So if the value is bigger than your string you will replace that for the value, if not you just set the value with your string
I have a string "9039662543", and when talk back is on, this string is read as "nine million...." in 4.3 android devices, above 4.3 devices its working fine, by reading "nine zero three...". What should I do to fix this?
I'm assuming this is a phone number? I can't tell because there is no formatting. Which is the heart of the problem. There are multiple fixes for this.
A: Leave it alone. TalkBack users have the option of parsing elements by view, paragraph, sentence, word, character, etc. If a user can't tell it's a phone number by the context, you need more context. The number itself is fine!
B: Format it better. (903)-966-2542 vs 9039662543, without any additional context, are two different pieces of information. It may still read out as something like "Parentheses nine-hundread and three........" but it will be more obvious it is a phone number, and the chunks are easy to keep track of. Sorry I dno't have a pre 4.3 device to check out what the actual announcement is.
C: Override the content description. If the text representation is:
Text: 9039662543
Content Description: 9 0 3 9 6 6 2 5 4 3
I recommend against this approach. These two values are not the same. Just because you are uncomfortable with the announcement doesn't mean a TalkBack user would be. As you get accustomed to using TalkBack you get accustom to switching to different text parsing modes. A user who doesn't care about the phone number would be frustrated by the slower read out of the separated version. Leave them the option of ignoring it, and having it blow by quickly in the more compressed form. Also, informatively, if there is no context those two numbers don't really represent the same thing. The solution in this case is provide this context NOT to change the presentation. Separate is NOT equal.
For EditText, add a space between characters and set this text in Accessibility Node Info.
ViewCompat.setAccessibilityDelegate(editText,object : AccessibilityDelegateCompat(){
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.text = editText.text.toString().replace(".".toRegex(),"$0 ")
}
})
While I see multiple people recommending what ChrisCM has posted. I see that the default contacts application does this differently.
The default contact application reads the phone number digit-by-digit. It also does a little more than that and it can be reused. The API that is used is:
https://developer.android.com/reference/android/telephony/PhoneNumberUtils.html#createTtsSpan(java.lang.String)
The details of how it works could be found here :
https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/android/telephony/PhoneNumberUtils.java
//add extra space to text and set that text as contentDescription
textView.setText(readbleText);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < readbleText.length(); i++) {
builder.append(readbleText.charAt(i));
builder.append("\u00A0");
}
textView.setContentDescription(builder);
Make sure the input type on the edittext is phone and not number:
android:inputType="phone"
and not:
android:inputType="number"
I know it's already answered but inspired by this answer
I wrote an extension function for textView (in Kotlin of course ) which can be re-used as a utility function overall by those who might have this problem.
fun TextView.separateText() {
val textView = this
ViewCompat.setAccessibilityDelegate(textView, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(
host: View,
info: AccessibilityNodeInfoCompat
) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.text = textView.text.toString().replace(".".toRegex(), "$0 ")
}
})
}
PS: I was not able to post this under his/her answer, because I do not enough reputation.
You can add zero-width non-breaking space characters "\ufeff" to separate the numbers invisibly. It will read the number as digits. Do refer the comment in the below link for more details
How to change Android Talkback in case of App name
I am writing a dictionary-type app. I have a list of hash-mapped terms and definitions. The basic premise is that there is a list of words that you tap on to see the definitions.
I have this functionality up and running - I am now trying to put dynamic links between the definitions.
Example: say the user taps on an item in the list, "dog". The definition might pop up, saying "A small furry [animal], commonly kept as a pet. See also [cat].". The intention is that the user can click on the word [animal] or [cat] and go to the appropriate definition. I've already gone to the trouble of making sure that any links in definitions are bounded by square brackets, so it's just a case of scanning the pop-up string for text [surrounded by brackets] and providing a link to that definition.
Note that definitions can contain multiple links, whilst some don't contain any links.
I have access to the string before it is displayed, so I guess the best way to do this is to do the scanning and ready the links before the dialog box is displayed.
The question is, how would I go about scanning for text surrounded by square brackets, and returning the text contained within those brackets?
Ideally the actual dialog box that is displayed would be devoid of the square brackets, and I need to also figure out a way of putting hyperlinks into a dialog box's text, but I'll cross that bridge when I come to it.
I'm new to Java - I've come from MATLAB and am just about staying afloat, but this is a less common task than I've had to deal with so far!
You could probably do this with a regular expression; something like this:
([^[]*)(\[[^]]+\])
which describes two "match groups"; the first of which means any string of zero or more characters that aren't "[" and the second of which means any string starting with "[", containing one or more characters that aren't "]", and ending with "]".
Then you could scan through your input for matches to this pattern. The first match group is passed through unchanged, and the second match group gets converted to a link. When the pattern stops matching your input, take whatever's left over and transmit that unchanged as well.
You'll have to experiment a little; regular expressions typically take some debugging. If your link text can only contain alphanumerics and spaces, your pattern would look more like this:
([^[]*)(\[[\s\w]+\])
Also, you may find that regular expression matching under Android is too slow to be practical, in which case you'll have to use wasyl's suggestion.
Quite simple, I think... As the text is in brackets, you need to scan every letter. So the basic recipe would be :
in a while loop scan every character (let's say, while i < len(text))
If scanned character is [:
i++;
Add letter at index i to some temporary variable
while (character # i) != ']' append it to the temporary variable
store this temporary variable in a list of results.
Some tips:
If you use solution above, use StringBuilder to append text (as regular string is immutable)
You might also want (and it's better, I think) to store starting and ending positions of all square brackets first, and then use string.substring() on each pair to get the text inside. This way you'd first iterate definition to find brackets (maybe catch unmatched ones, for early error handling), then iterate pairs of indices...
As for links, maybe this will be of use: How can I get clickable hyperlinks in AlertDialog from a string resource?