Android调用View的layout()方法的时候出现ClassCastException

在Android应用开发中,从SDK 4.4的模拟器切换到7.0真机调试时,一个好友列表页面在调用View的layout()方法时发生ClassCastException。错误源于尝试将ViewGroup.LayoutParams转换为AbsListView.LayoutParams,具体涉及ExpandableListView。通过删除或修改ExpandableListView的footer布局参数类型,解决了问题。原因可能是不同Android版本对布局参数类型的检查宽松度不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在调试代码的时候出现了ClassCastException直接崩溃,导致崩溃的操作是跳转到一个好友列表页面,页面和微信的通讯录页面很像,就是一个列表,右边一个导航栏,原来一直用的模拟器调试,模拟器的sdk版本是4.4的,今天换到了7.0的真机就直接崩了。
打印的错误日志如下:

java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
                                                                  at android.widget.ListView.removeUnusedFixedViews(ListView.java:1908)
                                                                  at android.widget.ListView.layoutChildren(ListView.java:1769)
                                                                  at android.widget.AbsListView.onLayout(AbsListView.java:2161)
                                                                  at android.view.View.layout(View.java:17520)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5612)
                                                                  at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
                                                                  at android.view.View.layout(View.java:17520)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5612)
                                                                  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
                                                                  at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
                                                                  at android.view.View.layout(View.java:17520)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5612)
                                                                  at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
                                                                  at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                                                  at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                                                  at android.view.View.layout(View.java:17520)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5612)
                                                                  at com.newbeehood.widget.swipebackhelper.SwipeBackLayout.onLayout(SwipeBackLayout.java:278)
                                                                  at android.view.View.layout(View.java:17520)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5612)
                                                                  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
                                                                  at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
                                                                  at com.android.internal.policy.DecorView.onLayout(DecorView.java:724)
                                                                  at android.view.View.layout(View.java:17520)
                                                                  at android.view.ViewGroup.layout(ViewGroup.java:5612)
                                                                  at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2342)
                                                                  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069)
                                                                  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
                                                                  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
                                                                  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
                                                                  at android.view.Choreographer.doCallbacks(Choreographer.java:683)
                                                                  at android.view.Choreographer.doFrame(Choreographer.java:619)
                                                                  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
                                                                  at android.os.Handler.handleCallback(Handler.java:751)
                                                                  at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                  at android.os.Looper.loop(Looper.java:154)
                                                                  at android.app.ActivityThread.main(ActivityThread.java:6077)
                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

根据日志提示,出错代码是

mContentView.layout(mContentLeft, 0,
        mContentLeft + mContentView.getMeasuredWidth(),
        mContentView.getMeasuredHeight());

这行代码在SwipeBackLayout类的onLayout方法中,根据提示是类型转换异常,而且是ViewGroup.LayoutParams转AbsListView.LayoutParams时出现的,页面中好友列表是用ExpandableListView实现的(其实用RecyclerView更好,只是好多年之前写过一个类似的例子是用ExpandableListView实现的,这次就直接拿来用了,不知道RecyclerView会不会出现这个问题),第一反应就是这个ExpandableListView的问题,果然在把它删掉以后就不再报错了。虽然知道是它出的问题,但是在哪里出现的类型转换却还是没有找到。仔细看了下代码,发现在ExpandableListView添加footer的时候是这样写的:

mFooterTv = new TextView(this);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DensityUtil.dp2px(this, 50));
mFooterTv.setLayoutParams(params);
mFooterTv.setGravity(Gravity.CENTER);
number = mContacts.size();
mFooterTv.setText(number + "位联系人");
contactElv.addFooterView(mFooterTv);

FooterView的LayoutParams是ViewGroup.LayoutParams,是不是这里出现的类型转换?把这行代码改成下面这样:

AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, DensityUtil.dp2px(this, 50));

再次运行,果然没有问题了。
在网上查了一下,如果你要将一个view添加到另一个布局中,你必须设定该View的布局参数为其父类所使用的布局参数类型,也就是说header或者footer也要使用ListView的
LayoutParams,只是不知道为什么在4.4中运行是可以的,可能是低版本的约束比较松吧。

我正在完成移动智能设备应用开发课程设计,设计要求是在Android Studio软件上设计一个简易的计算器。 以下是布局文件代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/whq" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="49吴俊廷" android:gravity="center" android:textColor="#000000" android:textSize="35sp" /> <TextView android:id="@+id/firstNumView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:id="@+id/operatorView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:id="@+id/secondNumView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:id="@+id/resultView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/btnClear" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:background="#AEACB7DD" android:alpha="0.5" android:text="c" /> <Button android:id="@+id/btnBack" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:text="√" android:background="#AEACB7DD" /> <Button android:id="@+id/btnPercent" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:background="#AEACB7DD" android:alpha="0.5" android:text="%" /> <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:background="#AEACB7DD" android:alpha="0.5" android:text="+" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:background="#AEACB7DD" android:orientation="horizontal"> <Button android:id="@+id/btn7" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEE9F0FF" android:text="7" /> <Button android:id="@+id/btn8" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEE5E9FC" android:text="8" /> <Button android:id="@+id/btn9" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEE5E9FC" android:text="9" /> <Button android:id="@+id/btnSubtract" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEE5E9FC" android:text="-" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/btn4" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="4" /> <Button android:id="@+id/btn5" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:background="#AEACB7DD" android:alpha="0.5" android:text="5" /> <Button android:id="@+id/btn6" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:background="#AEACB7DD" android:alpha="0.5" android:text="6" /> <Button android:id="@+id/btnMultiply" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="*" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="1" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="2" /> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="3" /> <Button android:id="@+id/btnDivide" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="/" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/btnSign" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="+/-" /> <Button android:id="@+id/btn0" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="0" /> <Button android:id="@+id/btnDecimal" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="." /> <Button android:id="@+id/btnEquals" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:alpha="0.5" android:background="#AEACB7DD" android:text="=" /> </LinearLayout> </LinearLayout> 以下是主函数代码: package com.example.qa;import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { // 声明界面组件 private TextView firstNumView, operatorView, secondNumView, resultView; // 计算器状态变量 private String currentInput = ""; private double firstOperand = 0; private String currentOperator = ""; private boolean resetOnNextInput = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 确保布局文件名匹配 // 初始化TextView组件 firstNumView = findViewById(R.id.firstNumView); operatorView = findViewById(R.id.operatorView); secondNumView = findViewById(R.id.secondNumView); resultView = findViewById(R.id.resultView); // 设置按钮监听器 setupButtonListeners(); } private void setupButtonListeners() { // 数字按钮监听器 setNumberButtonListeners(); // 操作符按钮监听器 setOperatorButtonListeners(); // 功能按钮监听器 setFunctionButtonListeners(); } private void setNumberButtonListeners() { int[] numberButtonIds = { R.id.btn0, R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6, R.id.btn7, R.id.btn8, R.id.btn9, R.id.btnDecimal }; for (final int id : numberButtonIds) { findViewById(id).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button button = (Button) v; String input = button.getText().toString(); if (resetOnNextInput) { clearAll(); resetOnNextInput = false; } // 处理小数点输入 if (input.equals(".")) { if (currentInput.contains(".")) return; // 防止多个小数点 if (currentInput.isEmpty()) currentInput = "0"; } currentInput += input; updateDisplay(); } }); } } private void setOperatorButtonListeners() { int[] operatorButtonIds = { R.id.btnAdd, R.id.btnSubtract, R.id.btnMultiply, R.id.btnDivide }; for (final int id : operatorButtonIds) { findViewById(id).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button button = (Button) v; String operator = button.getText().toString(); if (!currentInput.isEmpty()) { firstOperand = Double.parseDouble(currentInput); currentOperator = operator; currentInput = ""; resetOnNextInput = false; updateDisplay(); } else if (!currentOperator.isEmpty()) { // 允许更新操作符 currentOperator = operator; updateDisplay(); } } }); } } private void setFunctionButtonListeners() { // 等号按钮 findViewById(R.id.btnEquals).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { calculateResult(); } }); // 清除按钮 findViewById(R.id.btnClear).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clearAll(); } }); // 正负号按钮 findViewById(R.id.btnSign).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { toggleSign(); } }); // 百分号按钮 findViewById(R.id.btnPercent).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { convertToPercent(); } }); // 平方根按钮 findViewById(R.id.btnBack).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { calculateSquareRoot(); } }); } private void updateDisplay() { firstNumView.setText(currentOperator.isEmpty() ? "" : String.valueOf(firstOperand)); operatorView.setText(currentOperator); secondNumView.setText(currentInput); resultView.setText(""); } private void calculateResult() { if (currentOperator.isEmpty() || currentInput.isEmpty()) return; double secondOperand = Double.parseDouble(currentInput); double result = 0; try { switch (currentOperator) { case "+": result = firstOperand + secondOperand; break; case "-": result = firstOperand - secondOperand; break; case "*": result = firstOperand * secondOperand; break; case "/": if (secondOperand == 0) { resultView.setText("除数不能为0"); resetOnNextInput = true; return; } result = firstOperand / secondOperand; break; } // 处理整数结果显示 String resultStr; if (result == (int) result) { resultStr = String.valueOf((int) result); } else { resultStr = String.format("%.2f", result); } resultView.setText(resultStr); firstOperand = result; currentInput = ""; resetOnNextInput = true; } catch (Exception e) { resultView.setText("错误"); resetOnNextInput = true; } } private void clearAll() { currentInput = ""; firstOperand = 0; currentOperator = ""; resetOnNextInput = false; firstNumView.setText(""); operatorView.setText(""); secondNumView.setText(""); resultView.setText(""); } private void toggleSign() { if (!currentInput.isEmpty()) { double value = Double.parseDouble(currentInput); currentInput = String.valueOf(value * -1); updateDisplay(); } else if (resultView.getText().length() > 0) { double value = Double.parseDouble(resultView.getText().toString()); resultView.setText(String.valueOf(value * -1)); } } private void convertToPercent() { if (!currentInput.isEmpty()) { double value = Double.parseDouble(currentInput); currentInput = String.valueOf(value / 100); updateDisplay(); } else if (resultView.getText().length() > 0) { double value = Double.parseDouble(resultView.getText().toString()); resultView.setText(String.valueOf(value / 100)); } } private void calculateSquareRoot() { if (!currentInput.isEmpty()) { double value = Double.parseDouble(currentInput); if (value < 0) { resultView.setText("无效输入"); return; } currentInput = String.valueOf(Math.sqrt(value)); updateDisplay(); } else if (resultView.getText().length() > 0) { double value = Double.parseDouble(resultView.getText().toString()); if (value < 0) { resultView.setText("无效输入"); return; } resultView.setText(String.valueOf(Math.sqrt(value))); } } } 运行后模拟机显示Unfortunately,qa has stopp。 帮我解决该问题。
最新发布
06-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值