简体   繁体   中英

Android ListFragment android.widget.LinearLayout cannot be cast to android.widget.TextView

I am in the process of changing my activities into fragments for one of my applications and have run into the error below. There was no indication in the error as to what was causing the error but I narrowed it down to the below fragment.

I am also getting another strange error, in that when a item is added to the list, its check box cannot be ticked until the activity is left and re-entered again? Is there a way to make the checkbox deletable as soon as it is added to the list without having to leave and come back again?

Can anyone explain to me this error?

Fragment

import android.app.Dialog;
import android.support.v4.app.ListFragment;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;


public class ShoppingList extends ListFragment{

    private Cursor cursor;
    private static int measurementValue;
    private static String unitValue;

    private String name;
    private String unit;
    private int measurement;
    private int currMeasurement;
    private int newMeasure;


    public ShoppingList() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        final View rootView = inflater.inflate(R.layout.fragment_shopping, container, false);

        final DBMain db = new DBMain(getActivity());

        db.open();

        cursor = db.getAllItems();
        String[] values = new String[cursor.getCount()];
        cursor.moveToFirst();
        for(int i = 0; i < cursor.getCount(); i++)
        {
            String row = cursor.getString(cursor.getColumnIndex("name"));
            values[i] = row;
            cursor.moveToNext();
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
                R.layout.shopping_list_row, values);
        setListAdapter(adapter);

        FloatingActionButton filterButton = (FloatingActionButton) rootView.findViewById(R.id.addButton);
        filterButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
            // custom ingredient_dialog
            final Dialog dialog = new Dialog(getActivity());
            dialog.setContentView(R.layout.shopping_dialog);
            dialog.setTitle("Add Item");

            final EditText item = (EditText) dialog.findViewById(R.id.item);

            final Spinner measurement = (Spinner) dialog.findViewById(R.id.measurement);
            measurement.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                final String measurementValue = measurement.getSelectedItem().toString();
                int finalMeasurement = Integer.parseInt(measurementValue);
                ShoppingList.measurementValue = finalMeasurement;
                }

                @Override
                public void onNothingSelected(AdapterView<?> parentView) {

                }

                });

                final Spinner unit = (Spinner) dialog.findViewById(R.id.unit);
                unit.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                    String finalUnit = unit.getSelectedItem().toString();
                    unitValue = finalUnit;
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> parentView) {
                    }

                    });

                    Button dialogButtonOk = (Button) dialog.findViewById(R.id.dialogButtonOK);
                    // if button is clicked, close the custom ingredient_dialog
                    dialogButtonOk.setOnClickListener(new View.OnClickListener() {
                                                    @Override
                                                    public void onClick(View v) {
                        String newItem = item.getText().toString();
                        db.open();
                        db.insertItem(newItem, measurementValue, unitValue);
                        Cursor cursor = db.getAllItems();

                        //String[] columns = new String[] {db.KEY_NAME, db.KEY_CODE, db.KEY_ROWID};
                        String[] columns = new String[]{db.KEY_ITEM_NAME, db.KEY_MEASUREMENT, db.KEY_UNIT};

                        int[] to = new int[]{R.id.ingredientName, R.id.ingredientMeasurement, R.id.ingredientUnit};

                        final SimpleCursorAdapter myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.shopping_list_row, cursor, columns, to, 0);

                        //final ListView shoppingList = (ListView) rootView.findViewById(R.id.shoppingList);
                        //shoppingList.setAdapter(myCursorAdapter);
                        setListAdapter(myCursorAdapter);
                        dialog.dismiss();
                            }
                        });

                        Button dialogButtonNext = (Button) dialog.findViewById(R.id.dialogButtonNext);
                        // if button is clicked, close the custom ingredient_dialog
                        dialogButtonNext.setOnClickListener(new View.OnClickListener() {
                                                    @Override
                                                    public void onClick(View v) {
                        String newItem = item.getText().toString();
                        db.open();
                        db.insertItem(newItem, measurementValue, unitValue);
                        item.setText("");
                        Cursor cursor = db.getAllItems();

                        //String[] columns = new String[] {db.KEY_NAME, db.KEY_CODE, db.KEY_ROWID};
                        String[] columns = new String[]{db.KEY_ITEM_NAME, db.KEY_MEASUREMENT, db.KEY_UNIT};

                        int[] to = new int[]{R.id.ingredientName, R.id.ingredientMeasurement, R.id.ingredientUnit};

                        final SimpleCursorAdapter myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.shopping_list_row, cursor, columns, to, 0);

                        //final ListView shoppingList = (ListView) rootView.findViewById(R.id.shoppingList);
                        //shoppingList.setAdapter(myCursorAdapter);
                        setListAdapter(myCursorAdapter);

                                                    }
                                                });
                         dialog.show();
                                            }
                                        }

                     );

        return rootView;
    }

    public class ShoppingCustomAdapter extends SimpleCursorAdapter implements CompoundButton.OnCheckedChangeListener {

        private Context mContext;
        private Context appContext;
        private int layout;
        private Cursor cr;
        private final LayoutInflater inflater;

        //private Context context = this;
        //DBMain db = new DBMain(context);


        public ShoppingCustomAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
            super(context, layout, c, from, to);
            this.layout = layout;
            this.mContext = context;
            this.inflater = LayoutInflater.from(context);
            this.cr = c;
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            return inflater.inflate(layout, null);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            super.bindView(view, context, cursor);
            CheckBox checkBox1 = (CheckBox) view.findViewById(R.id.checkBox1);
            checkBox1.setOnCheckedChangeListener(this);
            int columnIndex = cursor.getColumnIndex("_id");
            int columnvalue = cursor.getInt(columnIndex);
            checkBox1.setTag(columnvalue);
        }

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            int id = (Integer) buttonView.getTag();


            final DBMain db = new DBMain(getActivity());

            db.open();

            //getting information about deleted item from the shopping list
            Cursor item = db.getSingleItem(id);
            item.moveToPosition(-1);
            while(item.moveToNext())
            {
                name = item.getString(item.getColumnIndex("name"));
                measurement = item.getInt(item.getColumnIndex("measurement"));
                unit = item.getString(item.getColumnIndex("unit"));
            }
            item.close();

            //check if item is in Kitchen
            Cursor check = db.getSingleItem(id);

            //if yes, update it
            if(check!=null && check.getCount()>0)
            {
                //get current kitchen measurement
                Cursor measure = db.getKitchenMeasurementID(id);
                measure.moveToPosition(-1);
                while(measure.moveToNext())
                {
                    currMeasurement = measure.getInt(measure.getColumnIndex("measurement"));
                }
                measure.close();
                newMeasure = measurement + currMeasurement;

                db.updateContents(name, newMeasure);
            }
            else
            {

                db.insertContent(name, measurement, unit);
            }

            db.deleteItem(id);
        }
    }

}

Fragment's XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<ListView
    android:id="@android:id/list"
    android:layout_below="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</ListView>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/addButton"
    app:backgroundTint="@color/floatingButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|right"
    android:clickable="true"
    android:src="@drawable/ic_tab_add"
    android:layout_alignParentBottom="true"
    android:layout_alignParentEnd="true"
    android:layout_marginBottom="63dp"
    android:layout_marginRight="16dp" />


</android.support.design.widget.CoordinatorLayout>

Row Layout

<?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:orientation="horizontal"
android:weightSum="1">

<TextView
    android:id="@+id/ingredientName"
    android:layout_width="wrap_content"
    android:textColor="#000000"
    android:layout_height="wrap_content"
    android:padding="5dp"
    android:hint="wewewe"/>

<TextView
    android:id="@+id/ingredientMeasurement"
    android:textColor="#000000"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/ingredientName"
    android:padding="5dp"
    android:hint="fefefef"/>

<TextView
    android:id="@+id/ingredientUnit"
    android:textColor="#000000"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/ingredientMeasurement"
    android:padding="5dp"
    android:hint="qqqqq"/>


<CheckBox
    android:id="@+id/checkBox1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right"
    android:background="#fff"
    android:text=""/>
</LinearLayout>

Logcat Error

Caused by: java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.TextView

You are using ArrayAdapter incorrectly, the problem seems to be on this line:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
                R.layout.shopping_list_row, values);

Check the documentation , the 2nd argument expects layout resource id but not any resource:

The resource ID for a layout file containing a TextView to use when instantiating views.

But your row layout is a LinearLayout .

If you use more complex layout, use another constructor:

public ArrayAdapter (Context context, int resource, 
                     int textViewResourceId, T[] objects)

You can use it's 3rd argument to specify the TextView in the layout.

In Code line

ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
                R.layout.shopping_list_row, values);
        setListAdapter(adapter);

the layout "shopping_list_row" is having LinearLayout but array adapter takes the textview so you need to set the layout who's parent is a Textview or either create a custom adapter with custom row.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM