Android异常:RelativeLayout$LayoutParams cannot be cast to android.widget.LinearLayout$LayoutParams

本文介绍了一种特定的ClassCastException异常,即尝试将RelativeLayout$LayoutParams强制转换为LinearLayout$LayoutParams时引发的问题,并提供了详细的解决方案。

项目开发中碰到一个异常比较奇怪,因为这个异常一旦出现会然你很头疼,因为从奔溃日志中你基本找不到有用的信息,比如这个:

java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.LinearLayout$LayoutParams
                                                                    at android.widget.LinearLayout.measureVertical(LinearLayout.java:720)
                                                                    at android.widget.LinearLayout.onMeasure(LinearLayout.java:629)
                                                                    at android.view.View.measure(View.java:20171)
                                                                    at android.widget.ListView.setupChild(ListView.java:2031)
                                                                    at android.widget.ListView.makeAndAddView(ListView.java:1950)
                                                                    at android.widget.ListView.fillSpecific(ListView.java:1379)
                                                                    at android.widget.ListView.layoutChildren(ListView.java:1746)
                                                                    at android.widget.AbsListView.onLayout(AbsListView.java:2723)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:630)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
                                                                    at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1731)
                                                                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1496)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1080)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
                                                                    at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
                                                                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                                                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
                                                                    at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
                                                                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                                                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
                                                                    at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
                                                                    at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:3178)
                                                                    at android.view.View.layout(View.java:17945)
                                                                    at android.view.ViewGroup.layout(ViewGroup.java:5812)
                                                                    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2716)
                                                                    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2417)
                                                                    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1487)
                                                                    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7450)
                                                                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
                                                                    at android.view.Choreographer.doCallbacks(Choreographer.java:695)
                                                                    at android.view.Choreographer.doFrame(Choreographer.java:631)
                                                                    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
                                                                    at android.os.Handler.handleCallback(Handler.java:739)
                                                                    at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                    at android.os.Looper.loop(Looper.java:158)
                                                                    at android.app.ActivityThread.main(ActivityThread.java:7225)
                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

从log中看这个异常,信息中没有报类似的cause by信息,也就找不到异常出现在项目中的哪行代码。这个时候你可能会去点源码中的listView的代码,因为log中出现ndroid.widget.ListView类似信息,一番折腾下来然而并没有什么软用,怎么办呢?

这个时候我就去分析对比异常出现前后的代码,异常出现前后改动的布局文件,当然也会分析下ListView附近的改动代码。如上的这个异常是这么出现的:

我有一个View一开始是放在RelativeLayout里,此时运行Ok,然后我把这个View放到了一个LinearLayout里并且单独提出来作为一个layout,之后我又调用了ListView的addHeader方法把这个layout  Add进去了,因此出现了上面的错误,

一开始分析ListView也没分析出啥原因,后面看到View一开始是RelativeLayout的子View,后面View作为了LinearLayout的子View就出现了上面的异常;到这里还没看懂异常的原因,然后分析代码,结果看到这么一段

 RelativeLayout.LayoutParams gallery_lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
 slider.setLayoutParams(gallery_lp);
View指的就是slider,顿时焕然大悟。然后我就把如上代码改成如下,异常就没了。

LinearLayout.LayoutParams gallery_lp = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
slider.setLayoutParams(gallery_lp);
原因就是因为slider之后作为了LinearLayout的子View,它的Layoutparams就因该是它的父View的LayoutParams,所以就应该把slider的LayoutParams从RelativeLayout$LayoutParams改成LinearLayout$LayoutParams。

写这个的原因就是告诉自己,遇到这样的错误,就因该从这几个步骤解决问题:

  • 基本的定位异常出现的代码行数,分析...
  • 代码回退,然后对比分析代码找原因
  • 分析异常前后改动的Layout文件
  • 分析改动的View在代码中的调用
也希望这些总结能给大家带来帮助,谢谢!



package com.example.layoutdome; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.MediaController; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import android.widget.VideoView; import com.example.mylibrary.Usages; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainActivity extends AppCompatActivity implements DataUploader.OnDataReceivedListener { private List<DataList> dataLists = new ArrayList<>(); private int type; private DataList.DataDTO.ComponentsDTO.SetStyleDTO setStyle; private TextView tvDate, tvWeather, tvList; private FullScreenVideoView tvVideo; private VerticalMarqueeTextView tvMarquee; private String fileUrl; private List<DataList.DataDTO.ComponentsDTO.SetStyleDTO.VideoListDTO> videoList; private int currentIndex = 0; // 用于追踪当前播放的视频索引 private MediaController mMediaController; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.text); tvMarquee = (VerticalMarqueeTextView) findViewById(R.id.tv_marquee); tvVideo = (FullScreenVideoView) findViewById(R.id.tv_video); tvDate = (TextView) findViewById(R.id.tv_date); tvWeather = (TextView) findViewById(R.id.tv_weather); tvList = (TextView) findViewById(R.id.tv_list); textView.setText("版本号:" + APKVersionCodeUtils.getVersionCode(MainActivity.this)); Usages usages = new Usages(); usages.getTimes(MainActivity.this); new DataUploader("ES0001", this).execute(); } @Override public void onDataReceived(DataList dataList) { // 当数据接收到时更新 dataLists dataLists.clear(); dataLists.add(dataList); // 输出数据 for (int i = 0; i < dataLists.size(); i++) { DataList.DataDTO data = dataLists.get(i).getData(); List<DataList.DataDTO.ComponentsDTO> components = data.getComponents(); for (int j = 0; j < components.size(); j++) { type = components.get(j).getType(); Log.i("components:", "" + type); setStyle = components.get(j).getSetStyle(); //1文本组件 2图片组件 3视频组件 4天气 5日期 6线路 if (type == 1) { int height = setStyle.getHeight(); int width = setStyle.getWidth(); int left = setStyle.getLeft(); int top = setStyle.getTop(); String noticeText = setStyle.getNoticeText(); tvMarquee.setTextList(Arrays.asList( noticeText )); tvMarquee.startMarquee(); Log.i("aaaaaaa", "文本组件marqueeTop:" + top); Utils.updateLayoutParams(MainActivity.this,tvMarquee,width,height,left,top); Log.i("aaaaaaa", "文本组件:" + type); } else if (type == 2) { // int height = setStyle.getHeight(); // int width = setStyle.getWidth(); // int left = setStyle.getLeft(); // int top = setStyle.getTop(); // int videoWidth = Integer.parseInt(String.valueOf(width)); // int videoHeight = Integer.parseInt(String.valueOf(height)); // int videoTop = Integer.parseInt(String.valueOf(top)); // FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(videoWidth, videoHeight); params.width = dip2px(MainActivity.this, videoWidth); // params.height = dip2px(MainActivity.this, videoHeight); // params.leftMargin = dip2px(MainActivity.this, left); // params.topMargin = dip2px(MainActivity.this, videoTop); // tvVideo.setLayoutParams(params); // 重新设置 LayoutParams } else if (type == 3) { int height = setStyle.getHeight(); int width = setStyle.getWidth(); int left = setStyle.getLeft(); int top = setStyle.getTop(); Utils.updateLayoutParams(MainActivity.this,tvVideo,width,height,left,top); videoList = setStyle.getVideoList(); // 开始播放第一个视频 playNextVideo(); Log.i("aaaaaaa", "视频组件:" + type); } else if (type == 4) { int height = setStyle.getHeight(); int width = setStyle.getWidth(); int left = setStyle.getLeft(); int top = setStyle.getTop(); Utils.updateLayoutParams(MainActivity.this,tvWeather,width,height,left,top); Log.i("aaaaaaa", "天气组件:" + type); // Log.i("aaaaaaa", "天气组件左边距:" + params.leftMargin); // Log.i("aaaaaaa", "天气组件高:" + params.height); // Log.i("aaaaaaa", "天气组件宽:" + params.width ); // Log.i("aaaaaaa", "天气组件距上边距:" + params.topMargin); } else if (type == 5) { int height = setStyle.getHeight(); int width = setStyle.getWidth(); int left = setStyle.getLeft(); int top = setStyle.getTop(); Utils.updateLayoutParams(MainActivity.this,tvDate,width,height,left,top); Log.i("aaaaaaa", "日期组件:" + type); } else if (type == 6) { int height = setStyle.getHeight(); int width = setStyle.getWidth(); int left = setStyle.getLeft(); int top = setStyle.getTop(); Utils.updateLayoutParams(MainActivity.this,tvList,width,height,left,top); Log.i("aaaaaaa", "线路组件:" + type); } } } } private void playNextVideo() { mMediaController = new MediaController(this); if (currentIndex < videoList.size()) { String fileUrl = videoList.get(currentIndex).getStaticFileName(); Log.i("aaaaaaa", "视频地址:" + fileUrl); Uri parse = Uri.parse("http://117.71.111.12:8087/eb/static/"+fileUrl); tvVideo.setVideoURI(parse); mMediaController.setVisibility(View.GONE); mMediaController.setMediaPlayer(tvVideo); tvVideo.setMediaController(mMediaController); tvVideo.start(); // 设置视频准备好之后的监听 tvVideo.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { try { tvVideo.start(); } catch (Exception e) { Log.e("VideoPlayError", "播放视频时出错: " + e.getMessage()); } } }); // 设置视频播放完成后的监听 tvVideo.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if (currentIndex < videoList.size() - 1) { currentIndex++; // Move to the next video playNextVideo(); // Play next video } else { Log.i("VideoPlayer", "所有视频均已播放"); } } }); } else { Log.i("aaaaaaa", "所有视频已播放完毕"); } // 检查文件格式和编码是否受支持 tvVideo.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { if (what == MediaPlayer.MEDIA_ERROR_UNSUPPORTED) { // 处理不支持的文件格式或编码 Log.e("VideoPlayer", "播放视频时发生错误. what: " + what + ", extra: " + extra); } return false; } }); } } package com.example.layoutdome; import android.content.Context; import android.view.View; import android.widget.FrameLayout; import android.widget.RelativeLayout; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; public class Utils { /** * 设置布局参数,改变控件位置 * @param view * @param width * @param height * @param left * @param top */ static void updateLayoutParams(Context context,View view, int width, int height, int left, int top) { FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height); params.width = dip2px(context, width); params.height = dip2px(context, height); params.leftMargin = dip2px(context, left); params.topMargin = dip2px(context, top); view.setLayoutParams(params); // 重新设置 LayoutParams } /** * dp转为px * @param context 上下文 * @param dpValue dp值 * @return */ public static int dip2px(Context context, int dpValue) { float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } } 报错 java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
07-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值