Android - Bolding Part of Text in EditText - java

There's a similar answer here, but it doesn't state what I'm about to ask.
I have a 'Bold Text' option in my Android view and if a user selects that option, a boolean gets set as true in the code behind.
Using a TextWatcher, how can I change the text typed by the user to bold after a specific point in the EditText. If the user turns it off, the text typed after should be in normal styling. Everything depends on the boolean value.
Here's what I have so far:
Boolean isBolded = false;
// Code that turns the bold option true and false...
contentBox = (EditText) findViewById(R.id.contentBox);
contentBox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(isBolded)
{
//Start bolding the text typed after that point
}
else
{
//Stop styling the text typed after that point
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
The difficulty would be to determine the points in the EditText where the user decides to turn bolding off and on while typing. What do you guys have in mind?

Set Html.fromHtml("<b>This part will be bold</b> This won't!") as the Text.

Related

Android: How to run a callback right after setText() is rendered

I want to display some text in an EditText and do some work right away after the text is displayed. I have the following code in my onCreate() method:
this.editor.setText(text, TextView.BufferType.EDITABLE);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
// Work that needs to be done right after the text is displayed
}
}, 1000);
This works OK, but I want to minimize the delay between setText() rendering and the work being done-- a 1s delay is unacceptable. However, if I change the delay to 0ms or 1ms, then the work is done before the text gets rendered.
I could keep typing in numbers to search for the perfect delay time that would execute my code just after the text was rendered, but that seems very tedious/imprecise. Is there a better way to tell Android to run a callback right after that happens? Thanks.
edit: Here are two things I've tried that didn't work. For bonus points, it would be very helpful if you could explain to me why these didn't work.
Using Handler.post
new Handler(Looper.getMainLooper()).post(r) also runs r before the text finishes rendering. I thought setText adds rendering code to the queue, so shouldn't post(r) being called after that add r after the rendering code?
Using View.post
this.editor.post(r) didn't work either, r is still called before the text is rendered.
Use this it would hlp
mSongNameTextView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
You can assign a TextWatcher to your EditText.
A TextWatcher is basically a listener that listens for changes to the text (before, during and after) in the EditText.
It can be implemented as follows:
EditText et;
et.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
// Work that needs to be done right after the text is displayed
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
}
So when you set the text explicitly, this listener should be called and after the text is changed, the // Work that needs to be done right after the text is displayed code will be run.
You can use ViewTreeObserver as below:
yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// do your work here. This call back will be called after view is rendered.
yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// or below API 16: yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
I initially wanted to delay the work because it was CPU-intensive. I realized the solution was to spin up a new thread for the work, rather than post it to the UI thread.

how setOnKeyListener works

we got homework to make convertor of weights where the fields are updated while typing the number (no need to click "calculate" or anything). one of the students offered the code below.
the code works: when putting a number in field 1, field 2 changes while typing.
what i dont understand is how does that work?
in the onKey method, no value is given to View int and keyEvent
so how does the listener "knows" on which view to and what keys to listen to or what event to activate ?
public class Screen extends Activity {
double weight = 2.20462;
EditText kgEdit, lbsEdit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
kgEdit = (EditText) findViewById(R.id.kgEdit);
lbsEdit = (EditText) findViewById(R.id.lbsEdit);
kgEdit.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
String kg = kgEdit.getText().toString();
if (kg.isEmpty()) {
lbsEdit.setText("");
} else {
double num = Double.valueOf(kgEdit.getText().toString()) * weight;
lbsEdit.setText(num + "");
}
return false;
}
});
lbsEdit.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
String lbs = lbsEdit.getText().toString();
if (lbs.isEmpty()) {
kgEdit.setText("");
} else {
double num = Double.valueOf(lbsEdit.getText().toString()) / weight;
kgEdit.setText(num + "");
}
return false;
}
});
}
}
I'm going to focus on just 1 of the text fields to answer this. Look at this first line:
kgEdit = (EditText) findViewById(R.id.kgEdit);
All this does is get a reference to the EditText for entering kg. Now that there is a reference, we can call methods on that object.
Next, we have this:
kgEdit.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// ...
}
}
What the above does is the following. Take our reference to the EditText for kilograms that we retrieved in our first line. The method setOnKeyListener does the following (from here): "Register a callback to be invoked when a hardware key is pressed in this view."
What this means is that you've now told the view that you want to be informed every time the user presses a key while this EditText has the focus. You make this call to the Android API and in the background Android handles everything you're asking. It will call the method with the View view, int keyCode and KeyEvent event. You give it a method that then handles those inputs. So nowhere in your code do you need to call the method, Android calls it in the background where you'll never have to see or worry about it.
Now, because you called the method on kgEdit, that means the following code will ONLY be called when kgEdit is focused and keys are typed, so there's no confusion with the other EditText. It gets its own method call later, just below. Here's the rest of the code inside the setOnKeyListener:
String kg = kgEdit.getText().toString();
if (kg.isEmpty()) {
lbsEdit.setText("");
} else {
double num = Double.valueOf(kgEdit.getText().toString()) * weight;
lbsEdit.setText(num + "");
}
return false;
What this does is get the current text in kgEdit, which has already been updated with the key the user pressed. And it just checks if the text is empty, and if so remove the text in lbsEdit. If it's not empty, then get the text, convert it to a number, convert the number from kg to lbs and update lbsEdit
You have to use addTextChangedListener like this-
EditText editText = (EditText) findViewById(R.id.editText1);
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
//do here your calculation
String data = s.toString();
}
});

Auto populate second EditText based on first EditText input

I'm brainstorming the next phase of my project, and I'm not certain which path to take. My idea is to have 2 EditText fields, one beneath the other. When the user types a unique ID into the first field, the second field will populate automatically with corresponding text. For example, entering "X5432" in box 1 will put "1957 Thunderbird" in box 2. I estimate having about 500 value pairs to work from, so I assume a SQLite structure would be better than just using arrays. Any suggestions would be appreciated. Thanks.
I think you should use TextWatcher.
Just get value from edittext1
Find appropriate text for edittext2
Set text to second edittext.
edittext.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// do some stuff
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// do some stuff
}
#Override
public void afterTextChanged(Editable s) {
// do some stuff
}
});

Count characters with TextWatcher fails on HTC longpress

I have 3 EditText elements, and I want to jump from one field to the next if there are 4 characters in the input.
I use a TextWatcher for this:
getEditView(R.id.edit_code1).addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void afterTextChanged(Editable input) {
if(input.length() == 4){
getEditView(R.id.edit_code2).requestFocus();
}
}
});
The inputType for the EditText is "textCapCharacters"
When doing a longpress on a key to get a number, like holding R to get a 4, most devices will not add the letter, until the user stops holding the button, and will fire afterTextChanged after the letter 4 is selected. On a HTC keyboard (In this case the HTC Desire on 2.3.5) this is not the case. Even though the user is still holding the button, the R is added to the EditText and afterTextChanged is fired, and the code does its job and puts the focus on the next field.
How can this undesired behavior be prevented? Watching onKeyDown/Up won't help, because it doesn't register normal keystrokes.
getEditView(R.id.edit_code1).addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
if(input.length() >3){
getEditView(R.id.edit_code2).requestFocus();
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void afterTextChanged(Editable input) {
}
}
});
Unfortunately it's a bug in the HTC keyboard with no way of fixing it. This being an event in the IME, it is impossible intercept touch or key events, so you would probably be better off simply making the user skip to the next input instead of you doing it for them.
If it's that important for you though, you can implement your own kind of keyboard there, with only the keys you need.

Detect a new line in android text view

I am trying to create my first Android application in which it will help me do some outlining.
Quite simply I am trying to write some sort of detection that when a line starts with a hyphen, the next time there is a new line a hyphen will be placed in front of that new line.
I am looking for any pointers or directions for where I should be looking, as this is my first app.
Or in another sense what would be the best way to detect text being typed and change the EditText based on it.
Since OnKeyListener does not work for Soft keyboard, I recommend using the TextWatcher.
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if( -1 != charSequence.toString().indexOf("\n") ){
// Do your stuff
}
}
When you want to replace this sequence by some other string, try this:
public void afterTextChanged(Editable editable) {
int i = editable.toString().indexOf("\n");
if ( i != -1 ) {
editable.replace(i, i+1, "");
}
}
You could use the text watcher class of android which can be attached to a event.
EditText mPasswordLength = (EditText)findViewById(R.id.password_length);
mPasswordLength.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s){
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count){
}
});
The method you can use to edit the text is onTextChanged. More detailed description about when and why these events are fired is explained in this post.. Read the answer with max up votes.
You want an OnKeyListener for the EditText, then in the listener's onKey(View v, int keyCode, KeyEvent event) method, see if it is the event is KeyEvent.ACTION_DOWN and the keyCode is for KeyEvent.KEYCODE_ENTER, if so then append a '-' to the end of the edittext.

Categories

Resources