androidandroid-layoutandroid-contentproviderclasscastexceptionandroid-relativelayout

Getting java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams


Here I need to add textview at runtime. first I took reference of RelativeLayout to get layout params but unfortunately its throwing ClassCastException at RelativeLayout.LayoutParams params = (android.widget.RelativeLayout.LayoutParams)contentLayout.getLayoutParams()

I also checked - FrameLayout to RelativeLayout ClassCastException even if there is no FrameLayout used, but it didn't work. Since after replacing RelativeLayout with FrameLayout, I'm unable to add rule on layoutParams.

protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            TextView displayTextView = (TextView)findViewById(R.id.display_text);

            ContentResolver resolver = getContentResolver();
            Cursor cursor = resolver.query(UserDictionary.Words.CONTENT_URI, null, null, null, null);

            cursor.moveToFirst();
            displayTextView.setText("The User Dictionary contains " + cursor.getColumnCount() + " words");

            RelativeLayout contentLayout = (RelativeLayout)findViewById(R.id.content_layout);

            TextView columnNames = new TextView(this);
            columnNames.setText("Columns: _id - frequency - word");
            contentLayout.addView(columnNames);

            RelativeLayout.LayoutParams params = (android.widget.RelativeLayout.LayoutParams)contentLayout.getLayoutParams();
            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            params.addRule(RelativeLayout.BELOW);

            do{
                TextView entry = new TextView(this);
                entry.setText(cursor.getInt(cursor.getColumnIndex(UserDictionary.Words._ID)) + " - " +
                              cursor.getInt(cursor.getColumnIndex(UserDictionary.Words.FREQUENCY)) + " - " +
                              cursor.getString(cursor.getColumnIndex(UserDictionary.Words.WORD)));

                entry.setLayoutParams(params);
                contentLayout.addView(entry);
            }while(cursor.moveToNext());

            cursor.close();
    }

    **Getting following error** - 
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dexter.contentpro/com.example.dexter.contentpro.MainActivity}: java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                at android.app.ActivityThread.access$800(ActivityThread.java:144)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:135)
                at android.app.ActivityThread.main(ActivityThread.java:5221)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
         Caused by: java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
                at com.example.dexter.contentpro.MainActivity.onCreate(MainActivity.java:37)
                at android.app.Activity.performCreate(Activity.java:5933)
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                at android.app.ActivityThread.access$800(ActivityThread.java:144)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:135)
                at android.app.ActivityThread.main(ActivityThread.java:5221)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

activity_main.xml-

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:id="@+id/display_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Solution

  • The Error is right and you are also right,but its a misinterpretation on both you and android's part. You see when you Inflate a View with Parent_View being any sub class of a ViewGroup, android returns that View and treat it like a View if you want to treat it like a subclass of a ViewGroup you are going to have some cast Excetpions... You see i know this by experience but i cant give you a documented fact about this

    Back to your question; you try to get the Layoutparams of your RelativeLayout which is the top most View of that xml, so i am thinking getLayoutParams() should return null since its not attached to a ViewGroup but its not which means its attached to a FrameLayout which is the Top most View for the Window or itself.

    To solve it

    try this (1)

    instead of using this line

    RelativeLayout.LayoutParams params = (android.widget.RelativeLayout.LayoutParams)
                              contentLayout.getLayoutParams();
    

    use this

    //get the layoutParams of the TextView child in the Relativelayout in 
    //your xml,this will automatically map to the RelativeLayout params
    RelativeLayout.LayoutParams params = (android.widget.RelativeLayout.LayoutParams)
                              displayTextView.getLayoutParams();    
    

    or use this(2)

    change only your xml, and your previous code will work fine

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"    
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" 
    tools:context=".MainActivity">
    
       <RelativeLayout
          android:id="@+id/content_layout"
          android:layout_width="match_parent"
          android:layout_height="match_parent" >
    
            <TextView
               android:id="@+id/display_text"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content" />
    
        </RelativeLayout>
    </RelativeLayout>