Pregunta


Expected Result:

Android version = 2.2

Programmatically add a RelativeLayout to LinearLayout in main_menu.xml using inflate(). The linear layout (ID is item_list in main_menu.xml) is a container for holding a list of items. Each item is a relative layout, and is going to be added programmatically in a callback function after receiving data from a server.

The usage of inflate() is learned from here.


Problem:

The app crashes when running at this statement (which is MainActivity.java:693 in the error message),

RelativeLayout relativeLayout = (RelativeLayout) RelativeLayout.inflate(MainActivity.this, R.layout.template_item_list_cell, linearLayoutItemList);

However, the app works well if the above statement is replaced by these in the following updateItemList(),

RelativeLayout relativeLayout = new RelativeLayout(MainActivity.this);
RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, height);
relativeLayout.setLayoutParams(relativeLayoutParams);
relativeLayout.setBackgroundResource(R.color.cell_state);
relativeLayout.setClickable(true);

and insert this statement,

linearLayoutItemList.addView(relativeLayout);

after the comment,

// Add the RelativeLayout to LinearLayout

Error Messages:

08-07 13:54:44.689: W/dalvikvm(23363): threadid=1: thread exiting with uncaught exception (group=0x4001e578)
08-07 13:54:44.699: E/AndroidRuntime(23363): FATAL EXCEPTION: main
08-07 13:54:44.699: E/AndroidRuntime(23363): java.lang.ClassCastException: android.widget.LinearLayout
08-07 13:54:44.699: E/AndroidRuntime(23363):    at com.domainname.appname.android.MainAc$12$1.run(MainActivity.java:693)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at android.os.Handler.handleCallback(Handler.java:587)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at android.os.Handler.dispatchMessage(Handler.java:92)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at android.os.Looper.loop(Looper.java:130)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at android.app.ActivityThread.main(ActivityThread.java:3691)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at java.lang.reflect.Method.invokeNative(Native Method)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at java.lang.reflect.Method.invoke(Method.java:507)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:670)
08-07 13:54:44.699: E/AndroidRuntime(23363):    at dalvik.system.NativeStart.main(Native Method)

Code

res/layout/main_menu.xml

<?xml version="1.0" encoding="utf-8"? >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#555555"
    android:orientation="vertical" >

</LinearLayout>

res/layout/template_item_list_cell.xml

<?xml version="1.0" encoding="utf-8"? >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="41dp"
    android:background="@color/cell_state"
    android:clickable="true"
    android:visibility="gone" >

</RelativeLayout>

res/color/cell_state.xml

<?xml version="1.0" encoding="utf-8"? >
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- Active state -->
    <item
        android:state_selected="true"
        android:state_focused="false"
        android:state_pressed="false"
        android:drawable="@color/MyDarkGray" />

    <!-- Inactive state-->
    <item 
        android:state_selected="false" 
        android:state_focused="false"
        android:state_pressed="false" 
        android:drawable="@color/MyGray" />

    <!-- Pressed state-->
    <item 
        android:state_pressed="true"
        android:drawable="@color/MyDarkGray" />

    <!-- Selected state (using d-pad) -->
    <item
        android:state_focused="true" 
        android:state_selected="true"
        android:state_pressed="false" 
        android:drawable="@color/MyDarkGray" />

</selector>

res/values/customized_colors.xml

<?xml version="1.0" encoding="utf-8"? >
<resources>
    <color name="MyGray">#555555</color>
    <color name="MyDarkGray">#333333</color>
</resources>

src/com.domainname.appname.android/MainActivity.java

public class MainActivity extends Activity {
    @Override
    public void onCreate{
        // Some initialization
        setContentView(R.layout.main_menu);
        // Some other initialization
    }
    public void updateItemList() {
        // Remove previous items in the list
        LinearLayout linearLayoutItemList = (LinearLayout) menu.findViewById(R.id.item_list); // The linear layout is given an ID of item_list in main_menu.xml
        linearLayoutItemList.removeAllViews();

        // Request to server and define the callback function to add item(s) to the list programmatically

        JSONObject json = new JSONObject();
    MyRequestClass request = new MyRequestClass();

    request.request(MyConstants.WEB_BASE_URL, "app/get_latest_item_list", json, new MyCallbackClass() {
            @Override
            public void run(final JSONObject json) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String jsonInString = json.toString();
                            JSONArray jsonArray = json.getJSONArray("data");

                            // Suppose the JSON is properly returned
                            int numberOfItemListItems = jsonArray.length();

                            RelativeLayout relativeLayoutItemListTitleBar = (RelativeLayout) menu.findViewById(R.id.item_list_title_bar);
                            View viewDivider1 = (View) menu.findViewById(R.id.item_list_divider_1);
                            View viewDivider2 = (View) menu.findViewById(R.id.item_list_divider_2);
                            LinearLayout linearLayoutItemList = (LinearLayout) menu.findViewById(R.id.item_list);
                            View viewDivider3 = (View) menu.findViewById(R.id.item_list_divider_3);
                            View viewDivider4 = (View) menu.findViewById(R.id.item_list_divider_4);

                            if (0 == numberOfItemListItems) {
                                relativeLayoutItemListTitleBar.setVisibility(RelativeLayout.GONE);
                                viewDivider1.setVisibility(View.GONE);
                                viewDivider2.setVisibility(View.GONE);
                                linearLayoutItemList.setVisibility(LinearLayout.GONE);
                                viewDivider3.setVisibility(View.GONE);
                                        viewDivider4.setVisibility(View.GONE);
                            } else {
                                relativeLayoutItemListTitleBar.setVisibility(RelativeLayout.VISIBLE);
                                viewDivider1.setVisibility(View.VISIBLE);
                                viewDivider2.setVisibility(View.VISIBLE);
                                linearLayoutItemList.setVisibility(LinearLayout.VISIBLE);
                                viewDivider3.setVisibility(View.VISIBLE);
                                    viewDivider4.setVisibility(View.VISIBLE);

                                for (int index = 0; index < numberOfItemListItems; index++) {
                                    try {
                                        JSONObject currentJsonObject = jsonArray.getJSONObject(index);

                                        // Extract item title
                                        String currentTitle = currentJsonObject.getString("Title");

                                        // Extract icon image URI
                                        final String currentIconImageUri = ITEM_ICON_IMAGE_BASE_URL + currentJsonObject.getString("IconImageUri");

                                        // Extract item ID
                                        final String currentItemId = currentJsonObject.getString("ItemIdUri");

                                        // Create a cell to display the item
                                        linearLayoutItemList = (LinearLayout) menu.findViewById(R.id.item_list);

                                        // Create RelativeLayout for the cell
                                        int height = (int) (getResources().getDisplayMetrics().density * 41 + 0.5f); // 41dp height

                                        RelativeLayout relativeLayout = (RelativeLayout) LinearLayout.inflate(linearLayoutItemList.getContext(), R.layout.template_item_list_cell, linearLayoutItemList);
                                        relativeLayout.setOnClickListener(new View.OnClickListener(){
                                             @Override
                                             public void onClick(View v){
                                                 selectItemListCell(currentItemId);
                                             }
                                         });

                                        // Add icon image to a ImageView and add that TextView to RelativeLayout
                                        ImageView imageView = new ImageView(MainActivity.this);
                                        imageView = loadImageWithUrlString(imageView, currentIconImageUri);
                                        int width = (int) (getResources().getDisplayMetrics().density * 31 + 0.5f); // 31dp height
                                        height = (int) (getResources().getDisplayMetrics().density * 31 + 0.5f); // 31dp height
                                        RelativeLayout.LayoutParams relativeLayoutParams1 = new RelativeLayout.LayoutParams(width, height);
                                        relativeLayoutParams1.addRule(RelativeLayout.CENTER_VERTICAL);
                                        relativeLayoutParams1.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                                        int marginLeft = (int) (getResources().getDisplayMetrics().density * 10 + 0.5f); // 10dp
                                        int marginTop = (int) (getResources().getDisplayMetrics().density * 5 + 0.5f); // 5dp
                                        int marginRight = (int) (getResources().getDisplayMetrics().density * 0 + 0.5f); // 0dp
                                        int marginBottom = (int) (getResources().getDisplayMetrics().density * 5 + 0.5f); // 5dp
                                        relativeLayoutParams1.setMargins(marginLeft, marginTop, 0, marginBottom);
                                        imageView.setLayoutParams(relativeLayoutParams1);
                                        relativeLayout.addView(imageView);

                                        // Add title text to a TextView and add that TextView to RelativeLayout
                                        TextView textView = new TextView(MainActivity.this);
                                        textView.setText(currentTitle);
                                        float shadowRadius = 2.0f;
                                        int shadowDx = 0;
                                        int shadowDy = 1;
                                        int shadowColor = 0xFF000000;
                                        textView.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
                                        RelativeLayout.LayoutParams relativeLayoutParams2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                                        relativeLayoutParams2.addRule(RelativeLayout.CENTER_VERTICAL);
                                        marginLeft = (int) (getResources().getDisplayMetrics().density * 56 + 0.5f); // 56dp
                                        marginRight = (int) (getResources().getDisplayMetrics().density * 43 + 0.5f); // 43dp
                                        relativeLayoutParams2.setMargins(marginLeft, 0, marginRight, 0);
                                        textView.setLayoutParams(relativeLayoutParams2);
                                        relativeLayout.addView(textView);

                                        // Add the RelativeLayout to LinearLayout
                                        //   linearLayoutItemList.addView(relativeLayout);

                                        // Add divider to the LinearLayout
                                        if (index < (numberOfItemListItems - 1)) {

                                            View view1 = new View(MainActivity.this);
                                            height = (int) (getResources().getDisplayMetrics().density * 0.5 + 0.5f); // 0.5dp height
                                            RelativeLayout.LayoutParams relativeLayoutParams3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, height);
                                            view1.setLayoutParams(relativeLayoutParams3);
                                            view1.setBackgroundColor(0xFF323232);
                                            linearLayoutItemList.addView(view1);

                                            View view2 = new View(MainActivity.this);
                                            height = (int) (getResources().getDisplayMetrics().density * 0.5 + 0.5f); // 0.5dp height
                                            RelativeLayout.LayoutParams relativeLayoutParams4 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, height);
                                            view2.setLayoutParams(relativeLayoutParams4);
                                            view2.setBackgroundColor(0xFF595959);
                                            linearLayoutItemList.addView(view2);
                                        }

                                    } catch (JSONException e) {
                                        // Oops
                                    } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                    }
                                }
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }); // End of runOnUiThread()
            }
        });


    } // End of updateItemList
} // End of MainActivity
¿Fue útil?

Solución 2


Workaround

Change that erroneous statement,

RelativeLayout relativeLayout = (RelativeLayout) RelativeLayout.inflate(MainActivity.this, R.layout.template_item_list_cell, linearLayoutItemList);

into

RelativeLayout relativeLayout = (RelativeLayout) RelativeLayout.inflate(MainActivity.this, R.layout.template_item_list_cell, null);
linearLayoutItemList.addView(relativeLayout);

or

RelativeLayout relativeLayout = (RelativeLayout) MainActivity.this.getLayoutInflater().inflate(R.layout.template_item_list_cell, null);
linearLayoutItemList.addView(relativeLayout);

UPDATE

However, the above two fail to keep layout params info, because of that null value in the ViewGroup root parameter.

So a better solution is to point out the correct layout params info, according to Luksprog's answer in this post,

RelativeLayout relativeLayout = (RelativeLayout) MainActivity.this.getLayoutInflater().inflate(R.layout.template_item_list_cell, (LinearLayout) linearLayoutClubList, false);
linearLayoutItemList.addView(relativeLayout);

Otros consejos

The Error says you have a ClassCastException, which means you are not casting the classes properly. Most of the people seem to have issues when it comes to relations between Layout parameters and the layouts used.

Here is how its supposed to be:

You should be assigning Layout parameters which are of type parent to your layout. So for example lets say you have this

Button inside a LinearLayout

if you want to set LayoutParams to the button they have to be of type LinearLayout.LayoutParams which is the buttons parent ViewGroup (each layout is essentially a ViewGroup - LinearLayout, RelativeLayout etc..)

in your case the LayoutParams should be of type LinearLayout. Everything else is ok.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top