自定义Toolbar类触发EditText点击崩溃问题求助
问题背景
你之前一直用单一大型类开发,现在尝试为工具栏的EditText创建新类实现展开动画,但点击EditText时APP崩溃。目前MainActivity为空,后续计划添加WebView或其他组件。
你提供的代码
import android.support.v7.app.AppCompatActivity; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; import android.widget.EditText; /** * Created by on 2018-01-07. */ public class Toolbar extends AppCompatActivity { EditText search; public void onEdit(){ Animation scaleAnimation = new ScaleAnimation(0, -500, 1, 1); scaleAnimation.setDuration(750); scaleAnimation.setFillAfter(true); search.startAnimation(scaleAnimation); } }
崩溃日志
01-07 05:09:41.007 943-1130/? E/OMX-VDEC-1080P: Does not handle dataspace request 01-07 05:09:41.007 943-1130/? E/OMXNodeInstance: getConfig(3af0069:qcom.decoder.avc, ??(0x7f000062)) ERROR: UnsupportedSetting(0x80001019) 01-07 05:09:41.009 943-2332/? E/OMX-VDEC-1080P: Does not handle dataspace request 01-07 05:09:41.009 943-2332/? E/OMXNodeInstance: getConfig(3af0069:qcom.decoder.avc, ??(0x7f000062)) ERROR: UnsupportedSetting(0x80001019)
问题排查与修复
你提供的崩溃日志是关于视频解码器的,和当前EditText动画崩溃无关,大概率是日志不全。从代码来看,有几个致命问题:
错误的类继承关系
你的Toolbar类继承了AppCompatActivity,这完全不对!AppCompatActivity是页面容器,负责整个页面的生命周期,而Toolbar是一个UI组件,应该继承Android原生的Toolbar(或androidx.appcompat.widget.Toolbar),而不是Activity。把Activity当作UI组件用,必然会导致生命周期和初始化的混乱。未初始化的View变量
search这个EditText变量没有任何初始化代码(比如findViewById),直接调用search.startAnimation()会抛出NullPointerException,这是最常见的崩溃原因。ScaleAnimation参数错误
ScaleAnimation(0, -500, 1, 1)的参数是缩放比例,不是像素值!比如0代表缩放到0(完全隐藏),1代表原大小,你写-500是完全不合理的,会导致动画逻辑异常。
修复后的代码示例
自定义Toolbar类(正确的继承方式)
import android.content.Context; import android.util.AttributeSet; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; import android.widget.EditText; import androidx.appcompat.widget.Toolbar; public class CustomToolbar extends Toolbar { private EditText search; // 自定义View必须的构造方法 public CustomToolbar(Context context) { super(context); init(); } public CustomToolbar(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CustomToolbar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } // 初始化子View private void init() { // 假设你的Toolbar布局里有id为search的EditText,这里通过findViewById初始化 search = findViewById(R.id.search); } public void startSearchAnimation() { // 修正动画参数:x轴从0缩放到原大小,以View左侧为锚点,垂直方向保持原大小 Animation scaleAnimation = new ScaleAnimation( 0f, 1f, // x轴起始/结束缩放比例 1f, 1f, // y轴起始/结束缩放比例 Animation.RELATIVE_TO_SELF, 0f, // x轴锚点:View自身左侧 Animation.RELATIVE_TO_SELF, 0.5f // y轴锚点:View自身垂直中心 ); scaleAnimation.setDuration(750); scaleAnimation.setFillAfter(true); // 先判断search是否为空,避免空指针崩溃 if (search != null) { search.startAnimation(scaleAnimation); } } }
MainActivity中使用自定义Toolbar
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { private CustomToolbar customToolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 布局中要包含CustomToolbar // 初始化自定义Toolbar customToolbar = findViewById(R.id.custom_toolbar); // 给EditText设置点击事件,触发动画 customToolbar.findViewById(R.id.search).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { customToolbar.startSearchAnimation(); } }); } }
多类开发实用建议
从你之前只用单一大类的习惯来看,给你几个实用的开发原则,帮你理清代码结构:
职责单一原则:每个类只做一件事。比如:
- Activity/Fragment:负责页面的生命周期管理、业务逻辑协调、页面跳转。
- 自定义View:专注于UI的展示、交互逻辑(比如你需要的动画效果)。
- 工具类(Utils):封装通用功能(比如动画工具、字符串处理),方便多个地方复用。
- 模型类(Model):封装数据结构(比如网络请求返回的内容)。
避免错误继承:不要随便继承Activity/Fragment,只有当你需要创建一个新的页面时才用Activity;自定义UI组件要继承View或它的子类(比如Toolbar、LinearLayout)。
强制初始化变量:所有View变量必须在使用前初始化(比如在Activity的
onCreate、自定义View的init方法中调用findViewById),避免NullPointerException。学会看崩溃日志:你提供的日志和当前崩溃无关,下次要找Logcat中“Error”级别下的堆栈跟踪信息,里面会明确显示崩溃的类、方法和原因(比如
NullPointerException会告诉你哪个变量为空)。
内容的提问来源于stack exchange,提问作者EquiWare

