In my app I have the StackLayout with 2 entries. On initialize stacklayout visibility is set to false.
Later in code I change it to true together with setting focus on 1st entry. Despite focus working correctly selection length doesn't change its value.
protected void Txt_Focussed(object sender, FocusEventArgs e)
{
txt.CursorPosition = 0;
txt.SelectionLength = txt.Text.Length;
}
When I debug the code I see that txt.Text.Length is 1 because it has default value set as 1 letter text. But when I go through the line that is going to change SelectionLength to 1, it stays at 0.
Could it be that this doesn't change because when I trigger the focus event, the stacklayout containing that entry is not visible?
I've used events a couple of times to change the focus in my code, and it always worked like a charm. However, now the stacklayout visibility parameter is what makes this different from the others
And once I changed the visibility from false to true and back to false, the length of the selection will work fine until I restart the application.
Related
I'm starting with one programatically created AutoCompleteTextView view on my layout. After user typed valid data into the field, I'm creating a new AutoCompleteTextView object right under the first one by the same way, with the same parameters. I'm storing all of the field references in an ArrayList to keep up with the last one, this way I'm making sure that there will be new fields only under the one at the bottom (basically the last element in the reference list) - so it goes on at every field.
I would like to add this feature: when a new field is created, I change the last field's IME options to EditorInfo.IME_ACTION_NEXT and nextFocusForward attribute to the freshly created field - also programmatically. What I want to achieve: right when user presses Enter on the keyboard, last field's focus jumps to the new field. I'm using this code to set new IME options:
ArrayList<AutoCompleteTextView> fields = new ArrayList<>();
//Creating freshlyCreatedField, IT'S STILL NOT IN THE fields LIST!
AutoCompleteTextView currentlySelectedField = fields.get(fields.size() - 1); // last element
currentlySelectedField.setImeOptions(EditorInfo.IME_ACTION_NEXT);
currentlySelectedField.setNextFocusForwardId(freshlyCreatedField.getId());
currentlySelectedField.setSingleLine(true); //ACTV needs it to get IME to work
//Adding freshlyCreatedField to the fields list,
//so next time it will be the currentlySelectedField
But after running this code nothing happens to the currently selected AutoCompleteTextView object. Clearing and requesting focus did not work, and making it work by the reversed way (creating +1 "invisible" (technically GONE) field everytime) would be much more painful.
One more thing: after selecting any other field and re-selecting the one with configuration changes the Enter button works as it should first time! If I could do the same programmatically, it would solve my problem... so, any ideas how to do it? (Of course, I welcome better solutions also... ;) )
After some days, I've started to play with this problem again. Yes, it is a solution, but no, it's not so pretty as I would it to be like...
Anyhow, I created this code:
ArrayList<AutoCompleteTextView> fields = new ArrayList<>();
//Creating freshlyCreatedField, IT'S STILL NOT IN THE fields LIST!
//Last element
AutoCompleteTextView currentlySelectedField = fields.get(fields.size() - 1);
currentlySelectedField.setOnEditorActionListener(
new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_NEXT
|| actionId == EditorInfo.IME_ACTION_DONE
|| event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
freshlyCreatedField.requestFocus();
handled = true;
}
return handled;
}
});
//Adding freshlyCreatedField to the fields list,
//so next time it will be the currentlySelectedField
I put an EditorActionListener to the field actually under edit where the keyboard listens for one of the IME_ACTION_NEXT (if it's already set) and IME_ACTION_DONE action IDs (it's the default), or for the Enter key (for the case if someone would like to use physical keyboard). Then it jumps to the field below.
It works great, there aren't terrible problems with this approach. However I'm a little bit sad, because all of these possibilities stay invisible. The Done action button switches to Next only by clicking to somewhere else as I wrote it down in my question. So I think my "solution" can work, but it's not the best answer, so feel free to write your thoughts down if you have another idea... :)
Background
The fragment creates it's views and then starts a network operation. When the network operation is completed, various types of subviews are created and added to the fragment's view, based on the results of the network operation.
Problem
If a Spinner is added by the fragment, it's initial value is announced by TalkBack. This is very undesirable because the Spinner is usually buried deep within the form.
Failed Solutions
I've tried:
wrapping addView with setImportantForAccessibility
not setting the initial Spinner value (not an acceptable solution in any case) but the initial value is still announced when added
setting the Spinner's contentDescription to non-breaking space before adding and restoring it in onAttachedToWindow *
Question
Spinner is created and dynamically added, after the fragment is initially created. How can I prevent TalkBack from announcing the initial value of the Spinner?
Here's a workaround that I did in my project which worked as expected i.e. Spinner's content is only read out by TalkBack when it's in focus.
I subclassed the AppCompatSpinner class and overrode its onInitializeAccessibilityEvent function as follows:
#Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
super.onInitializeAccessibilityEvent(event);
}
}
1) set important for accessibility to false to all spinners in your form in onCreate().
spinner.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
2) setOnHoverListener to each spinner and inside it enable the accessibility again and send accessibility events to announce them properly.
spinner.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
spinner.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
spinner.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
spinner.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
3) setOnTouchListener to each spinner to perform click after double tap.
spinner.performClick();
I have 6 text fields on the stage along with a keypad with the numbers 0-9.
Ultimately this is going to be an Android app. And I want to be able the select a text field and then press the keypad buttons and have the numbers appear in the active text field.
I've been trying to Google active field and similar searches and can't seem to find a reference.
Keep in mind I'm fumbling around in the dark from what I've tried to gather from multiple tutorials. This code is probably complete garbage:
package {
public class main {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import fl.managers.FocusManager;
var focus:FocusManager = new FocusManager(this);
btn_1.addEventListener(MouseEvent.MOUSE_DOWN, inputNumber);
public function inputNumber(m:MouseEvent){
focus.text = 1;
}
public function main() {
// constructor code
}
}
}
Current Errors:
C:\Users\Otaku\Documents\lottocount\main.as, Line 19, Column 35 1118: Implicit coercion of a value with static type flash.display:InteractiveObject to a possibly unrelated type flash.text:TextField.
C:\Users\Otaku\Documents\lottocount\main.as, Line 14, Column 44 1120: Access of undefined property onMyButtonClick.
C:\Users\Otaku\Documents\lottocount\main.as, Line 14, Column 3 1120: Access of undefined property btn_1.
C:\Users\Otaku\Documents\lottocount\main.as, Line 13, Column 47 1120: Access of undefined property onFocusIn.
C:\Users\Otaku\Documents\lottocount\main.as, Line 13, Column 3 1120: Access of undefined property stage.
If you access the focus object, you'll have a reference to your currently active (focused on) object.
But in reality, just having a TextField that allows input will open a keyboard view (only on mobile) on touching it.
You can also tell Flash not to automatically show the keyboard, if you plan to use your own, then you can use the focus or make your own system that would track the appropriate TextField depending on where the last touch was.
EDIT:
Here's a simplistic example of how it could be done.
In this example I have two TextFields: tf1 and tf2. Also I've added a button for the sake of covering a situation where you need to save the last focus on a concrete type of object. The buttons name is myButton.
var lastSelectedTextField:TextField; // this will hold our last selected TextField
// make sure stage exists. If you're writing script in a frame, don't mind, if you use OOP approach you can do so by adding an eventListener for the event ADDED_TO_STAGE
stage.addEventListener(FocusEvent.FOCUS_IN, onFocusIn); // onFocusIn will trigger every time a focus is changed.
myButton.addEventListener(MouseEvent.CLICK, onMyButtonClick);
function onFocusIn(e:FocusEvent):void
{
if (stage.focus is TextField)
lastSelectedTextField = stage.focus as TextField;
}
function onMyButtonClick(e:MouseEvent):void
{
trace("Text of the last selected text field is:", lastSelectedTextField.text);
}
I have several EditViews in my activity's layout with editable enabled. When the activity's view is brought up, the first EditView gains focus: there is a blinking cursor and soft keyboard. However I can't get focus on any of the other EditViews in order to type into them. I have them enabled and editable. What other things could cause this?
If I simply load the layout in the activity without running any of my code, this problem does not occur, so it must be caused in the code at runtime--this is a ton of ported legacy code that is too much to share, but I wonder what types of properties or method side effects could cause enabled EditViews to not receive focus when tapped.
Another cause of this is having a Touch listener that does not set the event's TouchEventArgs.Handled property to true (I'm using Xamarin/monodroid vernacular here).
This was my code's problem. You must be sure to set TouchEventArgs.Handled to false. It was defaulting to true, which caused Android's handler which sets focus to not be run in the chain of responsibility!
_view.Touch += (sender, args) =>
{
Click(sender, new EventArgs());
args.Handled = false;
};
Right now I'm building a simple form and I'm designing it so that if the user hasn't entered the necessary info before clicking the submit button the background turns red. And after if they have entered the correct info the form goes back to the way it was before.
// "if empty then set fields to red" checks
if (firstLastName.getText().toString().equals("")) {
firstLastName.setBackgroundColor(Color.RED);
}
else
firstLastName.setBackgroundColor(Color.WHITE);
}
The problem is that white apparently isn't what it was before, because it looks different. Is there a way to reset the form without deleting the info entered by the user?
If I'm not being clear please let me know and Ill try to elaborate.
How about setting and removing a color filter instead of changing the background color:
if (firstLastName.getText().toString().equals("")) {
// 0xFFFF0000 is red
firstLastName.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.DARKEN);}
else {
//Setting to null removes filter
firstLastName.getBackground().setColorFilter(null);
}