Android EditText:新起一行时平滑展开动画

4
我注意到Telegram在聊天输入框中插入/开始新行时有平滑的动画效果。下面有两个GIF,第一个是Telegram,第二个是我的应用程序。

Telegram EditText

My EditText


你如何实现这样的动画效果?

我尝试谷歌搜索,但没有找到任何信息。我知道Telegram是开源的,我试图从他们的GitHub上找出来,但我找不到是什么使EditText具有如此平滑的动画效果。


3
看起来他们有一个完全的定制内容视图,自己绘制一切,并使用Animator API实现了自定义动画。请查看ChatActivitycheckAnimation方法。 - peshkira
2个回答

1

很简单。我也在我的聊天应用程序中添加了它,它的效果非常好。在你的根布局中,添加这一行:

android:animateLayoutChanges="true"

这将会使所有布局变化都具有动画效果。

编辑

如果以上方法没有帮助,你可以尝试以下操作。

userIdInput.setOnKeyListener(new View.OnKeyListener() {
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if ((keyCode == KeyEvent.KEYCODE_ENTER)  {

           ValueAnimator anim = ValueAnimator.ofInt(edMESSAGE.getHeight() - 40, edMESSAGE.getHeight() + 40)
                        .setDuration(500);
                anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    public void onAnimationUpdate(ValueAnimator animation) {
                        edMESSAGE.getLayoutParams().height = (int)animation.getAnimatedValue();
                        edMESSAGE.requestLayout();
                    }
                });
                anim.start();

            }
            return false;

        }

    });

当按下新行键时,您可以在onKeyListener中调用此方法。

编辑

有时,在输入文本时,会进入新的一行。为了实现动画效果,我们可以这样做:

chatInputET.addTextChangedListener(new TextWatcher() {
  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {
    String string = s.toString();
    if (string.length() > 0 && string.charAt(string.length() - 1) == '\n') {
      ValueAnimator anim = ValueAnimator.ofInt(edMESSAGE.getHeight() - 40, edMESSAGE.getHeight() + 40)
                        .setDuration(500);
                anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    public void onAnimationUpdate(ValueAnimator animation) {
                        edMESSAGE.getLayoutParams().height = (int)animation.getAnimatedValue();
                        edMESSAGE.requestLayout();
                    }
                });
                anim.start();
    }
  }
});

至于退格键,您可以这样做:

inputMessage.setOnKeyListener(new View.OnKeyListener() {
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            String string = inputMessage.getText().toString();
            if ((keyCode == KeyEvent.KEYCODE_DEL && (string.length() > 0 && string.charAt(string.length() - 1))  {

           ValueAnimator anim = ValueAnimator.ofInt(edMESSAGE.getHeight() + 40, edMESSAGE.getHeight() - 40)
                        .setDuration(500);
                anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    public void onAnimationUpdate(ValueAnimator animation) {
                        edMESSAGE.getLayoutParams().height = (int)animation.getAnimatedValue();
                        edMESSAGE.requestLayout();
                    }
                });
                anim.start();

            }
            return false;

        }

    });

添加这个对我没有任何影响。我将EditText包装在LinearLayout中,并在该LinearLayout中添加了android:animateLayoutChanges="true",但它并没有添加动画效果。 - mathematics-and-caffeine
我会检查。我不知道为什么。它对我起作用了。 - Sambhav Khandelwal
我已经编辑了答案,请查看。 - Sambhav Khandelwal
1
我如何注意到新的一行开始?当一行被填满并自动开始新行时,KEYCODE_ENTER不足以满足需求。此外,这还缺少另一方面的情况,即当删除一个新行时,EditText必须收缩。 - mathematics-and-caffeine

0
如果上面的答案不起作用,您可以使用这个:
binding.message.addTextChangedListener(new TextWatcher() {
            int linesCount = 0;
            @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 (s.toString().length() == 0){
                    binding.message.getLayoutParams().height = defEditTextHeight;
                    linesCount = binding.message.getLineCount();
                    return;
                }
                if (linesCount == 0){
                    linesCount = binding.message.getLineCount();
                    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();
                }
                linesCount = binding.message.getLineCount();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

defEditTextHeight 是默认高度的编辑文本,可以像这样获取:

defEditTextHeight = binding.message.getHeight();

希望能有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接