I'm trying to design a calculator app in Android to learn Java and Android at the same time but I do have prior experience with C++.
So far I've got two TextView elements. One displays the answer and one displays the input. However I don't want to use the user keyboard. I want to have my own buttons that navigate the input field. This is pretty standard for calculator apps.
If the user puts in 3+45/2.45*tan(9) that is put into a string array that would read
{3, +, 45, /, 2.45, *, tan, (, 9, )}. This is then validated, and processed by an RPN function when the user pushes equals.
Now this displays all nice, however I can't figure out how to implement a backspace or arrow keys that would navigate this input TextView field. I need to know where the cursor is which I'm not sure can even be enabled with TextView. Do I need to switch over to EditView? I want functionality so the cursor would skip over functions with one arrow push and delete functions with one push of delete but still navigate non-functions with single presses. For example, when pushing backspace on tan, it should delete all of tan, and not just leave "ta".
Any ideas on where to start?
You can get the Cursor position using the getSelectionStart() and getSelectionEnd() methods. If no text is highlighted, both getSelectionStart() and getSelectionEnd() return the position of the cursor.
Also, take a look at TextWatcher class. Its what Android uses, for per example, auto-formatting/adjusting phone numbers while typing etc.
Here you can find a list of TextWatchers used in Android to give you an idea;
http://grepcode.com/file/repo1.maven.org/maven2/com.google.android/android/2.2.1/android/text/TextWatcher.java
Related
Explanation of what I am trying to do
I'm making a custom in-app keyboard that works on the same principle of this example. However, in my keyboard I'm using popup windows to display extra letter forms. In traditional Mongolian letters have different forms depending on if they are located at the beginning, middle, or end of a word. Usually these can be determined from the context, but sometimes a user needs to choose an alternate form explicitly from the popup key candidates.
Lets say that a user starts typing a word (where - represent letters):
---
Then they chose a from the popup (I'm only using a to represent the concept of choosing a special Mongolian glyph form). The Unicode for this letter will be rendered as follows if they continue typing:
---a--
However, the Unicode is rendered as
---A
at the end of words. (a and A have the same code in Unicode.) So the user is confused why they chose a from the popup key but it gets rendered as A in the editor. If they would just keep typing, though, it will be fine since it gets rendered as a in middle of words.
What I want to do it set some sort of temporary span on the a of ---a so that it doesn't get rendered as ---A before they type the next letter. But if they add a space or move the cursor to a different location, then it will revert back to the default ---A form for final letters. (That is, the temporary span will be cancelled.)
Real example
If the abstract a and A are too confusing, here is a real example. The user wants to type a Mongolian UE form (Unicode \u1826\u180c) in this word
But since \u1826\u180c gets rendered like this at the end of words
the user is confused until they continue typing. I want the span to make it look like this
which can be temporarily rendered with \u1826\u180c\u200d.
Documentation
The documentation says
If your IME does text prediction or requires multiple steps to compose
a glyph or word, you can show the progress in the text field until the
user commits the word, and then you can replace the partial
composition with the completed text.
And it gives this example and image:
InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
ic.setComposingText("Composin", 1);
ic.commitText("Composing ", 1);
Problem
I was going to describe why it wasn't working in this section, but in the process of setting up my question here, I discovered that it actually works. So I will add my answer below as an example for other people are who doing something similar.
The following code sets a temporary composing span when the string in question is returned by the popup window
if (selectedItem.equals("a")) {
inputConnection.setComposingText("a", 1);
}
where selectedItem is the string chosen by the user from the key popup window candidates.
Note that the a has an underline indicating that it is a composing span. (This is a contrived example from the question where a would be rendered as A if the text were committed immediately.)
This also works for the real example in the question
if (selectedItem.equals("\u1826\u180c")) {
inputConnection.setComposingText("\u1826\u180c\u200d", 1);
}
Committing the composing span
When it is confirmed that the user wants to keep the composing span (ie, they keep typing more letters in the word), it can be committed with
inputConnection.commitText("\u1826\u180c", 1);
Abandoning the composing span
If the user clicks somewhere else, the composing span is not cancelled. But this is a different question.
Your keyboard can override onUpdateSelection to listen for cursor changes there. Then call
inputConnection.finishComposingText();
to keep whatever text was in the composing region. Or
ic.commitText("", 1);
to get rid of it. See this answer for more.
I am creating a custom keyboard for android devices and i have managed to implement everything but being able to move up and down lines through the use of buttons not just dragging with your finger. I am implementing this for small screens of older devices.
I have managed to implement moving the cursor one character to the left and right and to the end and start of the text how ever i cannot figure out how to implement moving up and down multiple lines like you would when navigating a word document on a normal computer.
I am not sure how you programmed all that, and it sounds like some really nice work, so not sure if you had this idea or if it is even possible, but:
Couldn't you make the cursor move to the right x-Times when trying to go down a line, where x is the amount of characters in one line, or rather the length of the String in a line?
Depending on the way you programmed it, if there is a string for each line, you could see where the cursor is in the line you are going from (e.g at the 3rd character of the String) and then just put it there in the next line.
In my application I have an EditText (Actually it's an implementation of MultiAutoCompleteTextView, but I don't think that matters) in which the user can enter a formula to be calculated, although generally they will want to just enter an integer.
What I would really like is for the keyboard to open with the numeric keyboard showing, but allow them to change to text if they want.
As standard of course it shows the letters and allwos them to change to numbers, which is OK, but 90% of the time they will want the numbers.
I tried doing:
operandEditText.setInputType(InputType.TYPE_CLASS_NUMBER|
InputType.TYPE_NUMBER_FLAG_SIGNED|InputType.TYPE_CLASS_TEXT);
But the result was a numeric keypad with letters written on the number keys (like a phone keypad), and it didn't write letters anyway.
I'm also aware that I could add a button, spinner or something that changed the input mode of the widget, but the aim of this is to make the interface easier to use, and I'm not sure adding another control will achieve that.
Is there a way to make it do what I want?
Suppose, I need the user to be able to input a list of strings somewhere in the settings of the app. Say, it's a list of URLs. The strings are not supposed to have any spaces, commas or semicolons inside.
The easiest thing I thought of so far is to make a big multi-line EditText with a hint to the user "Separate strings by spaces" and each time the user presses OK, use split(" ") to extract the array of strings.
The problem with that simple solution is that sometimes strings are not long enough to fill the whole EditText width, and >1 strings appear visually in 1 line. Sometimes the URLs are too long, so "www." remains on one line, and the rest of the address appears on the next line. It all looks messy and the user looses track where separate URLs start and end in the line.
Another easy solution: a long single-liner where all strings are separated by ; with optional spaces after. VisualStudio uses that in settings, I find it bad as well since you don't see all the strings at once and have to move in this long line a lot (even harder with the clumsy touch screen).
A more expensive solution: a vertically scrollable list of single-line EditTexts, which are generated programmatically each time the settings screen is opened. Would also need a "+" button which creates a new EditText and a "-" button next to each of the existing EditText's.
EDIT: Another idea: show all the strings in a plain ListView with a "+" button in the last row. When you tap "+", it turns into an EditText with 2 buttons to the right: "OK", "Cancel". "OK" would save the newly added string.
If the user taps any of the items in the list, the line turns into an EditText with "OK" and "Delete" button. "OK" saves edits, "Delete" deletes the item. "OK" and "Delete" buttons better should have images instead of words.
Or, well, all strings can be shown in a ListView, and each time the user taps on an item, an additional popup is shown with EditText for editing the string and 3 buttons below: "OK", "Cancel" and "Delete".
Am I thinking along the right lines? Do you know any existing patterns/libraries/solutions which solve this problem efficiently on touch screens?
It would be better, to have only a single editText, where user can set values in list one by one, and can see added values in listView, There may be some provision for a button to save all entered data, onve. See following link once,
http://www.mubasheralam.com/tutorials/android/listview-transcript-mode
IMHO touch screens are not made for extensive writing since the touch keyboards are awful for writing stuff too long or with too much symbols (e.g. programming language or URL). Do not think about touch apps like old desktop apps/systems. Maybe you should rethink your design and try to avoid this data input.
If it's something your app cannot live without, or you simply do want to do it that way anyway:
I think a newline separator is way more clear than a space or a ";" (assuming the URLs cannot contain ";" btw...).
What about one EditText for each URL, generating EditTexts programatically as the previous one is filled.
I'm designing my first Android IME and am a bit overwhelmed. My goals are accessibility-related, and as such I wonder if perhaps I'm trying things with the IME framework that just aren't possible. I've taken the default softkeyboard example and have it working along with some of my modifications, so I've definitely understood at least some of this, but there isn't a whole lot of documentation on some of the things I'm attempting. Here's what I mean:
Currently, Android phones with touchscreen-only keyboards are inaccessible. I currently have an accessible touchscreen keyboard using methods similar to those used in IOS/VoiceOver, so that part of the project is done and fairly straight-forward to accomplish in the IME framework.
Currently, Android's accessibility API doesn't provide accessible feedback for navigating text fields. That is, with an Android screen reader loaded, if you type the word "this", you'll hear individual characters spoken as you type them, but if you then try left-arrowing over the "s", that isn't spoken. So I want to trap movements and provide spoken feedback for the elements navigated past. Here's where I start encountering problems.
I currently have speech feedback for left and right arrowing, using getCurrentInputConnection.getTextBeforeCursor(1, 0) for arrowing left, and a similar call for arrowing right. This gets the character currently under the cursor after the movement is processed, and all is good.
My challenge, though, comes when arrowing up and down between lines. Ideally, I'd like to grab the current line of text and speak that, but I don't see any way to do that. The only thing I can think of is some combination of getTextBefore/AfterCursor(Integer.MAX_VALUE, 0) and combining those values, determining the current line by filtering for the previous and next \n. Is there another way--getting the entire text content of the field as a single block of text and using the cursor position to determine which piece of that text represents the current line? I'm seeing something about extracted text in the various input method classes, and it seems like there may be a way to monitor that, but I don't know if that is at all useful to me (I.e. would that return the entire field content?)
My next goal is providing standard text navigation capabilities. Android accessibility doesn't currently include touchscreen exploration, so it is impossible to otherwise scroll a large block of text. I don't necessarily expect folks to write novels on their phones, but I'd like to provide quick gestures or commands to move up/down paragraphs, and to the top/bottom of longer fields. Does the IMF provide methods for cursor movement, or is that outside of its authority?
Honestly, I didn't get the first part :(
For your second question, you will need to handle it by hand.
For instance, to add a key with a down drawable and make it work you will need to:
In the onKey method check for the code.
If it's 20, you should do a sendDownUpKeyEvents of that key event.