android editText limit string length not by charac

2019-07-25 01:10发布

问题:

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"

回答1:

You can use TextWatcher to analyse text being entered and Paint to measure the width of the current value of the text.



回答2:

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);
     }