javaandroidandroid-edittextline-height

How to get the height of each line in edit text


I want to animate the keyboard when a new line is added or removed just like how telegram does. I am able to add the animation like this:

private void doAnimation(int linesCount, String s){
        Toast.makeText(this, "" + linesCount, Toast.LENGTH_SHORT).show();
        if (linesCount == 1){
            binding.message.getLayoutParams().height = defEditTextHeight;
            return;
        }
        if (linesCount < binding.message.getLineCount()) {
            ValueAnimator anim = ValueAnimator.ofInt(binding.message.getHeight(), binding.message.getHeight() + 60)
                    .setDuration(250);
            anim.addUpdateListener(animation -> {
                binding.message.getLayoutParams().height = (int) animation.getAnimatedValue();
                binding.message.requestLayout();
            });
            anim.start();
        }else if( linesCount > binding.message.getLineCount()){
            ValueAnimator anim = ValueAnimator.ofInt(binding.message.getHeight(), binding.message.getHeight() - 60)
                    .setDuration(250);
            anim.addUpdateListener(animation -> {
                binding.message.getLayoutParams().height = (int) animation.getAnimatedValue();
                binding.message.requestLayout();
            });
            anim.start();
        }
    }

But, as you can see for the animation I am adding a random value like 60. But, this is not reliable for all the devices.

So, how can I get the height of each line so that I can add it and get a good animation?

Thanks in advance 🙂


Solution

  • The height of each line of an EditText is given by a StaticLayout that is created by the EditText.

    // Get vertical padding of the EditText
    int padding = binding.message.getPaddingTop() + binding.message.getPaddingBottom();
    
    // Get the total height of the EditText
    int totalHeight = binding.message.getLayout().getHeight() + padding;
    // or
    int totalHeight = binding.message.getHeight();
    
    // Get the height that line i contributes to the EditText. 
    int height = binding.message.getLayout().getLineBottom(i) - binding.message.getLayout().getLineTop(i);
    

    So, your animation definitions would look like this:

    int i = linesCount - 1;
    int height = binding.message.getLayout().getLineBottom(i) - binding.message.getLayout().getLineTop(i);
    ValueAnimator anim = ValueAnimator.ofInt(binding.message.getHeight(), binding.message.getHeight() + height)
                    .setDuration(250);
    

    If you need to wait for the layout, you can use the following:

    binding.message.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
        // code here 
    };