I noticed that different Android applications have different methods of selecting text. If you click-hold in Browser, there is a close up of the text plus the left and right edges can be dragged to modify the selection. In the Gmail app, a large blue circle appears below the cursor which makes it easy to move around.
The default text selection widget in an EditText box is very primitive by comparison. How can it be changed?
Update: I forgot to mention that editable is false. When editable is true the text selector is fine.
p.s. What its the proper name for the on-screen text selector?
As of Android 3.0 (API level 11), you can set the android:textIsSelectable attribute on any TextView to make its text selectable. The default UI as of this writing is similar to the behavior you referenced for the browser.
EDIT: Also, the default Android browser uses its own system-independent text selection mechanism that resembles the default text selection handles in Gingerbread. The "blue circle" sounds like a customized interface that a handset manufacturer added.
I would implement this as a custom class that extends EditText and implements LongClickListener and ClickListener. Then you can take complete control.
This is all just pseudo-code, and to point you in the right direction:
public class PrettySelectionEditText extends EditText implements OnLongClickListener, OnClickListener
{
private boolean isSelecting = false;
public PrettySelectionEditText(Context context)
{
super(context);
}
#Override
public boolean onLongClick(View v)
{
if (clickIsOnText)
{
isSelecting = true;
//Highlight word and pretty controls
}
//Select here based on the text they've clicked on?
//Return true if you want to consume the longClick
return true;
}
#Override
public void onClick(View v)
{
//If in selection mode
if (isSelecting)
{
//check where they've clicked
if (clickIsInSelect)
{
updateSelection(click);
}
else
{
isSelecting = false;
}
}
}
}
You could use a WebView instead and enable text selection.
If this is merely a problem of being unable to highlight uneditable text, you can use the XML attribute
android:textIsSelectable="true"
for that EditText box.
From the Android website:
android:textIsSelectable="true" indicates that the content of a non-editable text can be selected.
As for your question regarding terminology, I would call this the cursor.
Related
I am new to android development and currently trying to integrate material design into my app.
I would like to evaluate a simple form, for this purpose I used the components com.google.android.material.textfield.TextInputLayout and com.google.android.material.textfield.TextInputEditText for user input. Besides the text input, I need a date, which I want to read with a MaterialDatePicker.
I tried to display the MaterialDatePicker with OnFocusChangeListener, this works too, but I have two problems.
the display is a little bit delayed because first a keyboard is opened which is closed immediately after calling the MaterialDatePicker.
when the display is closed with the Back button, the focus is still on TextInputLayout. So I would have to change the focus first to open a MaterialDatePicker again.
This is how I implemented the OnFocusChangeListener
#Override
public void onFocusChange(View view, boolean selected) {
if( view.getId() == R.id.myId&& selected ){
MaterialDatePicker.Builder builder = MaterialDatePicker.Builder.datePicker();
MaterialDatePicker picker = builder.build();
picker.show( this.getParentFragmentManager(), "DATE_PICKER" );
}
}
Are there alternative components of Material Design that are better suited for the presentation? I would like to keep the behavior within the form, so as soon as the date is entered by the user, a small label should be displayed above, like this:
Thank you for your help.
I recently encountered the same problem.
The first issue concerning the keyboard, is solved by calling:
mTextInputEditText.setInputType(InputType.TYPE_NULL);
By setting the InputType to TYPE_NULL the keyboard won't open by clicking on the text field.
In addition, if you no longer want the user to be able to input any text, you can add:
mTextInputEditText.setKeyListener(null);
The second issue, to show the DatePicker again while it is already in focus, you can set an extra onClickListener:
mTextInputEditText.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
openDatePicker();
}
});
The OnClickListener is called as soon as the user clicks the text field again. Sadly it will not work with the first click.
You can look at this answer https://stackoverflow.com/a/11799891/9612595 for more information. Unfortunately, making the text field unfocusable resolves into weird behavior with the hint from Material.
I hope that helps!
Adding to luk321 answer. Instead of OnClickListener you can use OnTouchListener. For ex -
editText.setOnTouchListener((view, motionEvent) -> {
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
//your code
}
return false;
});
It will work on first touch. Be sure to use ACTION.UP otherwise event will occur while scrolling also.
deliverDatePicker.editText?.setOnClickListener {
viewModel.onDatePickerClick()
}
deliverDatePicker.editText?.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
viewModel.onDatePickerClick()
}
}
Overriding setOnFocusChangeListener as well as setOnClickListener solves the first unregistered click event of #luk321 answer
There is the proper method which is to draw the line myself via canvas. I want to avoid the complexity and I am asking here to double check if there is a simpler method I can use.
I am currently using a temporary method, which is to use SpannableString to highlight the nearest text 'character' that the cursor is on. But as you know, this "selects" the current character. I prefer the cursor to be between two characters instead of on top of one character.
I also don't want keyboard focus because I already laid out some nice buttons for the user to interact with. I don't want the app to use the Android keyboard and input methods. Only my buttons should be enough.
I tried accessing TextView methods:
Remove keyboard focus and input via the manifest
setFocusable(false)
setFocusableInTouchMode(false)
setCursorVisible(true) or cursorVisible="true"
This didn't work for me. I know that if I make the TextView focusable, then the cursor will be visible. But if it's not focusable, then the cursor does not show, even if it it is: cursorVisible="true".
What should I do?
Solution:
Disable input method of EditText but keep cursor blinking
Maybe try leaving out the xml attribute android:editable entirely
and then try the following in combination to
keep the cursor blinking and prevent touch events from popping up
a native IME(keyboard)..
/*customized edittext class
* for being typed in by private-to-your-app custom keyboard.
* borrowed from poster at http://stackoverflow.com/questions/4131448/android-how-to-turn-off-ime-for-an-edittext
*/
public class EditTextEx extends EditText {
public EditTextEx(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onCheckIsTextEditor() {
return false; //for some reason False leads to cursor never blinking or being visible even if setCursorVisible(true) was
called in code.
}
}
Step 2 change the above method to say return true;
Step 3 Add another method to above class.
#Override public boolean isTextSelectable(){ return true; }
Step 4 In the other location where the instance of this class has been
instantiated and called viewB I added a new touch event handler
viewB.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
viewB.setCursorVisible(true);
return false;
} });
Step 5 Check to make sure XML and or EditText instantiation code
declares IME/keyboard type to be 'none'. I didnt confirm relevance,
but Im also using the focusable attributes below.
<questionably.maybe.too.longofa.packagename.EditTextEx
android:id="#+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:focusable="true"
android:focusableInTouchMode="true"
android:inputType="none">
Sorry for so many xml attributes. My code uses them all, testing in
4.2.1, and has results. Hope this helps.
Hello I'm new to android developing.
Is there a method in java that equals to #.gotFocus?
Is there in java an events list that I can watch and select like in c# visual studio?
I tried to do #.Focus or something similar but had no success.
I want to reproduce the following scheme:
1- EditText has a certain hint => "Enter a value"
2- The user clicks the edit text and the hint disappears => ""
3- The user fills a certain value => "certain value"
Thank's for helpers :)
Ron Yamin, If I understand your doubt correctly what you want is:
1- Have a field of text for the user to type words/numbers etc --> It is called EditText in android
2- Have an hint so the user knows what to type --> Eg. "Type your name"
3- And react to focus in some way.
The first one you will achieve either through XML or by code. If you have a main.xml in your layouts folder (assuming you are using eclipse/android studio to develop), you can use the interface to drag an edit text to the android screen.
The second one you will achieve still through the XML. If you right click on it, right side of the screen there will be a little window called Proprieties that you can change things like height and width and a hint. Type there your hint.
Finally the last one you need to go to your code in .java and get a reference of your edit text (findViewById).
Either through setOnClickListener or setOnFocusChangeListener.
More info you can checkout here:
http://developer.android.com/guide/topics/ui/controls/text.html
I have googled a tutorial you can check with more detailed information and step by step guide.
Hope it helps:
http://examples.javacodegeeks.com/android/core/widget/edittext/android-edittext-example/
It seems that you changed your question quite a bit, and my C# ignorance got the best of me.
It seems that what you really want is an EditText, the example text you are looking for is the hint.
You can set the hint in the xml file or by code with .setHint(string) method.
Here's where to start:http://developer.android.com/guide/topics/ui/controls/text.html
edit 3 - events in android are dealt with by using listeners. You can use an onClickListener to achieve what you want.
textView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(){
//dostuff
}
}
Assuming your textfield is an instance of EditText (which it probably should be), you can do the following:
textfield.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
// this is where you would put your equivalent #.gotFocus logic
}
}
});
It's worth noting that the behavior you've described can be achieved by using textfield.setHint. The hint is text that is cleared automatically when the user selects the EditText. It's designed specifically for the case you describe, e.g. textfield.setHint("Enter a Value")
I'm not familiar with c# but I'm guessing you want event fired when edittext get focus. Try this
EditText txtEdit= (EditText) findViewById(R.id.edittxt);
txtEdit.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
// do the job here when edittext get focus
}
}
});
By default, the Accessibility Services will read out the following for an EditText view
If the EditText has a value entered = it will read out that value
If there is not value entered = it will read out the "hint"
I want it to read out something completely different in both cases.
My xml snippet is
<EditText
android:id="#+id/my_edit_text"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:editable="false"
android:focusable="true"
android:hint="my hint text"/>
I have to support API 14 and onwards.
I do not want to go to the trouble of extending EditText for this one single case, therefore I am using am AccessibilityDelegate.
mEditTextView.setAccessibilityDelegate(accessibilityDelegate);
From the documentation I understand that in my delegate I only have to overwrite those methods in the delegate for which I would like to change the behaviour. All other methods will default to the View's implementation.
http://developer.android.com/reference/android/view/View.AccessibilityDelegate.html
http://developer.android.com/reference/android/view/View.html
The doc for "onPopulateAccessibilityEvent" says : "Gives a chance to the host View to populate the accessibility event with its text content."
The doc for "dispatchPopulateAccessibilityEvent" says : "Dispatches an AccessibilityEvent to the host View first and then to its children for adding their text content to the event." and that the default behaviour is to call "onPopulateAccessibilityEvent" for the view itself and then "dispatchPopulateAccessibilityEvent" on all its children
http://developer.android.com/guide/topics/ui/accessibility/apps.html
This doc says under "onPopulateAccessibilityEvent" "*If your implementation of this event completely overrides the output text without allowing other parts of your layout to modify its content, then do not call the super implementation of this method in your code."
Therefore my delegate is the following
View.AccessibilityDelegate accessibilityDelegate = new View.AccessibilityDelegate() {
#Override
public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
event.getText().add("Apples");
}
};
Why when I use the keyboard to navigate to or use the screen to tap on the EditText view it is still reading "my hint text" and not "Apples"?
If I use a debugger, I see that before I set the event text, the text is empty and after I set it, it is "Apples" yet the TalkBack still reads out the hint.
Weirdly if I overwrite "onInitializeAccessibilityNodeInfo" and send an event with my desired text, then this desired text gets read out (see code snippet below). But this seems wrong to me as the "onInitializeAccessibilityNodeInfo" is reacting to the EditText's event but then just raising a new one.
#Override
public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfo info){
super.onInitializeAccessibilityNodeInfo(v, info);
...
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.getText().add("Pears");
event.setClassName(className);
event.setPackageName(packageName);
...
v.getParent().requestSendAccessibilityEvent(v, event);
}
We can change the text read out loud of EditText view by doing the following:
View.AccessibilityDelegate accessibilityDelegate = new View.AccessibilityDelegate() {
#Override
public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(v, info);
info.setText("some customized text")
}
};
and then set this delegate to the EditText View.
This sounds very similar to a problem I previously encountered: Android: How to eliminate spoken text from AccessibilityEvents when extending SeekBar?
Have you tried (as a test) clearing the hint text in onPopulateAccessibilityEvent, rather than just adding the 'Apples' text? I seem to remember that my empirical results did not match the Android documentation, particularly for Android OS prior to API 14.
I need a listener which is called every time the selection in an EditText changes.
I googled around but I couldn't find anything useful for API level 7.
I'm writing a Text Editor and I want the bold/italic/underlined button appear selected every time the user selects bold/italic/underlined text.
Pretty old question, but someone might still need this, so here's my solution : since the text selection accomplished with long press on the text, I simply used the following :
editText.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
// do whatever you need to do on text selection
}
});
This allows for custom behavior on text selection and doesn't prevent the user from copying/pasting.
The better way to do it would be to extend the EditText and then based upon how you would want to manage the changing text, you could override one of the 2 methods to work out your customized behavior.
If you want the selection changed then you could use the onSelectionChanged() method and implement your code there.
In case you want to implement something when the text changes in your editor then you could use, onTextChanged().