You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EditText点击扩展需求:输入时全屏宽度,失焦恢复原尺寸求方案

解决EditText点击展开全屏宽度、点击外部恢复的问题

嘿,我完全懂你遇到的困扰——你用ScaleAnimation做的展开动画只是视觉上的临时效果,动画结束后EditText会因为没真正修改布局参数而缩回去。咱们得把动画过渡和实际布局调整结合起来,再加上外部点击的判断逻辑,就能实现类似移动端浏览器地址栏的效果啦。

核心问题拆解

ScaleAnimation仅仅是对View做绘制层面的缩放,不会改变View本身的LayoutParams。所以动画一结束,系统就会按照原来的布局规则重新渲染View,导致它回到初始尺寸。我们需要在动画结束后真正修改EditText的宽度,同时处理外部点击的触发逻辑。

完整解决方案代码

下面是修改后的Home Activity代码,包含展开动画、布局参数永久修改、外部点击恢复的完整逻辑:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.EditText;
import android.widget.RelativeLayout;

public class Home extends AppCompatActivity {
    private EditText search_bar;
    // 保存EditText的初始宽度,用于后续恢复
    private int originalWidth;
    // 标记当前是否处于展开状态,避免重复触发动画
    private boolean isExpanded = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        search_bar = findViewById(R.id.search_bar);

        // 必须等布局加载完成后再获取初始宽度,用post确保时机正确
        search_bar.post(() -> originalWidth = search_bar.getWidth());

        // 设置EditText点击事件,触发展开逻辑
        search_bar.setOnClickListener(v -> {
            if (!isExpanded) {
                expandEditText();
            }
        });
    }

    // 展开EditText至全屏宽度的方法
    private void expandEditText() {
        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        // 计算横向缩放比例:屏幕宽度 / 原始宽度
        float scaleX = (float) screenWidth / originalWidth;

        // 创建缩放动画,以EditText左侧为原点横向缩放
        ScaleAnimation scaleAnimation = new ScaleAnimation(1f, scaleX, 1f, 1f,
                Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(750);

        // 动画结束后修改布局参数,让宽度永久变为屏幕宽度
        scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) search_bar.getLayoutParams();
                params.width = screenWidth;
                search_bar.setLayoutParams(params);
                isExpanded = true;
                // 可选:让EditText自动获取焦点并弹出软键盘
                search_bar.requestFocus();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}
        });

        search_bar.startAnimation(scaleAnimation);
    }

    // 恢复EditText至初始尺寸的方法
    private void collapseEditText() {
        if (!isExpanded) return;

        float scaleX = (float) originalWidth / getResources().getDisplayMetrics().widthPixels;

        // 创建反向缩放动画
        ScaleAnimation scaleAnimation = new ScaleAnimation(1f, scaleX, 1f, 1f,
                Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(750);

        // 动画结束后恢复初始布局参数
        scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) search_bar.getLayoutParams();
                params.width = originalWidth;
                search_bar.setLayoutParams(params);
                isExpanded = false;
                // 可选:清除焦点并收起软键盘
                search_bar.clearFocus();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}
        });

        search_bar.startAnimation(scaleAnimation);
    }

    // 重写Activity触摸事件,判断是否点击了EditText外部
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (!isPointInView(search_bar, event.getRawX(), event.getRawY())) {
                collapseEditText();
            }
        }
        return super.onTouchEvent(event);
    }

    // 辅助方法:判断触摸点是否在指定View范围内
    private boolean isPointInView(View view, float rawX, float rawY) {
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + view.getWidth();
        int bottom = top + view.getHeight();
        return rawX >= left && rawX <= right && rawY >= top && rawY <= bottom;
    }
}

关键细节说明

  • 初始宽度获取:用search_bar.post()确保布局完全加载后再获取宽度,避免拿到0值。
  • 动画+布局修改结合:动画负责平滑过渡,动画结束后修改LayoutParams让宽度永久改变,这样就不会再自动恢复了。
  • 外部点击判断:通过onTouchEvent结合isPointInView方法,精准判断点击位置是否在EditText之外,触发恢复逻辑。
  • 状态标记:isExpanded变量避免重复触发展开/恢复动画,提升交互流畅性。

布局适配提示

如果你的EditText父布局不是RelativeLayout,需要把代码中的RelativeLayout.LayoutParams替换成对应布局的参数类型(比如LinearLayout.LayoutParams),确保宽度修改生效。

内容的提问来源于stack exchange,提问作者EquiWare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:14:50