I need to make sure the input string can fit the line where I'm going to show it.
I already know how to limit the number of characters but that is not very good because 2 strings with the same character length have differente size...
For exemple:
String1: "wwwwwwwwww"
String2: "iiiiiiiiii"
in android string1 is much larger than string 2 because "i" consumes less visual space than "w"
You can use TextWatcher
to analyse text being entered and Paint
to measure the width of the current value of the text.
This is a code I used in TextWatcher's function afterTextChanged for this purpose. I based the solution on Asahi's advice. I'm no pro programmer so the code looks probably awful. Feel free to edit it to make it better.
//offset is used if you want the text to be downsized before it reaches the full editTextWidth
//fontChangeStep defines by how much SP you want to change the size of the font in one step
//maxFontSize defines the largest possible size of the font (in SP units) you want to allow for the given EditText
public void changeFontSize(EditText editText, int offset, int maxFontSize, int fontChangeSizeStep) {
int editTextWidth = editText.getWidth();
Paint paint = new Paint();
final float densityMultiplier = getBaseContext().getResources().getDisplayMetrics().density;
final float scaledPx = editText.getTextSize();
paint.setTextSize(scaledPx);
float size = paint.measureText(editText.getText().toString());
//for upsizing the font
// 15 * densityMultiplier is subtracted because the space for the text is actually smaller than than editTextWidth itself
if(size < editTextWidth - 15 * densityMultiplier - offset) {
paint.setTextSize(editText.getTextSize() + fontChangeSizeStep * densityMultiplier);
if(paint.measureText(editText.getText().toString()) < editTextWidth - 15 * densityMultiplier - offset) //checking if after possible upsize the text won't be too wide for the EditText
if(editText.getTextSize()/densityMultiplier < maxFontSize)
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, editText.getTextSize()/densityMultiplier + fontChangeSizeStep);
}
//for downsizing the font, checking the editTextWidth because it's zero before the UI is generated
while(size > editTextWidth - 15 * densityMultiplier - offset && editTextWidth != 0) {
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, editText.getTextSize()/densityMultiplier - fontChangeSizeStep);
paint.setTextSize(editText.getTextSize());
size = paint.measureText(editText.getText().toString());
}
}
Just a small advice if you want to change the fontSize already when loading the activity. It won't work if you use the function in OnCreate method because at this point the UI isn't defined yet so you need to use this function to get the desired result.
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
changeFontSize(editText, 0, 22, 4);
}