Logcat error: "addView(View, LayoutParams) is not supported in AdapterView" in a ListView
Asked Answered
L

6

52

I'm doing an application for Android and something I need is that it shows a list of all files and directories in the SD Card and it has to be able to move through the different directories. I found a good tutorial in anddev. I modified a few things so the application moves in the SD Card and not in Android root Directories but the rest is mostly the same.

This is my xml file for the activity:

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@id/android:list"       
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</ListView>

And this is the code for the Activity:

import hackreatorz.cifrador.R;
import java.io.File;
import java.util.ArrayList;
import android.app.ListActivity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class ArchivosSD extends ListActivity {

    private ArrayList<String> directoryEntries = new ArrayList<String>();
    private File currentDirectory = new File("/sdcard/");

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        browseToSD();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    private void browseToSD() {
        browseTo(new File("/sdcard/"));
    }

    private void upOneLevel() {
         if(this.currentDirectory.getParent() != null)
             this.browseTo(this.currentDirectory.getParentFile());
    }

    private void browseTo(final File directory) {
        if (directory.isDirectory()) {
                this.currentDirectory = directory;
                fill(directory.listFiles());
        } else {
                Toast.makeText(ArchivosSD.this, this.directoryEntries.get(this.getSelectedItemPosition()), Toast.LENGTH_SHORT).show();
                }
    }

    private void fill(File[] files) {
        this.directoryEntries.clear();
        this.directoryEntries.add(getString(R.string.current_dir));
        if(this.currentDirectory.getParent() != null)
            this.directoryEntries.add(getString(R.string.up_one_level));
            int currentPathStringLength = (int) this.currentDirectory.getAbsoluteFile().length();
            for (File file : files) {
                this.directoryEntries.add(file.getAbsolutePath().substring(currentPathStringLength));           
            }
        setListAdapter(new ArrayAdapter<String>(this, R.layout.archivos_sd, this.directoryEntries));
    }   

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        int selectionRowID = (int) this.getSelectedItemPosition();
        String selectedFileString = this.directoryEntries.get(selectionRowID);
        if (selectedFileString.equals(".")) {
            this.browseToSD();
        } else if(selectedFileString.equals("..")) {
            this.upOneLevel();
        } else {
            File clickedFile = null;
            clickedFile = new File(this.currentDirectory.getAbsolutePath() + this.directoryEntries.get(selectionRowID));
            if(clickedFile != null)
                this.browseTo(clickedFile);
            }
    }
}

I don't get any errors in Eclipse, but I get a Force Close when running the application on my phone and when I look at Logcat I see the following:

01-01 23:30:29.858: ERROR/AndroidRuntime(14911): FATAL EXCEPTION: main 01-01 23:30:29.858: ERROR/AndroidRuntime(14911): java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView

I don't have a clue what to do, I've looked up in Google and I didn't find anything and I did the same at stackoverflow. This is my first aplication in Java and for Android so I'm a real n00b and if the answer was there, I didn't understand it so I would really appreciate if you could explain what I should do to fix this error and why.

Thanks for everything in advance.

Lucania answered 1/1, 2011 at 23:4 Comment(0)
G
15

When creating an ArrayAdapter like yours, the ArrayAdapter needs a layout resource containing just a TextView. Try changing your ArrayAdapter creation with:

setListAdapter(new ArrayAdapter<String>(this, 
      android.R.layout.simple_list_item_1, 
      this.directoryEntries));

and see if it works.

Grub answered 1/1, 2011 at 23:49 Comment(7)
Great! It works thank you so much! I have a doubt about your answer, what does "android.R.layout.simple_list_item_1" include? If I use "android.R.layout.simple_list_item_1", what happens with the layout I did with a Listview and a textview? Thanks a lot!Lucania
When you create an ArrayAdapter you pass a layout resource to be used on each list item (and ArrayAdapter only wants a TextView). The layout file where you setup the "screen" is meant to be used inside onCreate, with setContentView(R.layout.your_layout).Grub
COuld I change "android.R.layout.simple_list_item_1" to R.layout.myxml if that xml file had the following code?: <?xml version="1.0" encoding="utf-8"?> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" />Lucania
I'm not sure if I get it. So, in OnCreate a should have setContentView(R.layout.my_layout with only a TextView and then on the adapter i have to pass the layout resource android.R.layout.simple_list_item_1?Lucania
Your previous comment is right, you can pass your own layout to the ArrayAdapter constructor. But your second comment is wrong, on setContentView you pass tge whole activity initial layout (headers, buttons, the ListView, etc). Although on ListActivities there's already a default layout with the ListView.Grub
So if I want to do a ListView, I don't have to creat my own layout? I just pass the default layout?Lucania
If you want to create your own layout for the whole screen, you can pass it to the setContentView method. If you want to create your own "list items" textview layout, you can pass it to the ArrayAdapter constructor.Grub
M
91

For others who have this problem and have inflated a layout in ArrayAdapter's getView, set the parent parameter to null, as in view = inflater.inflate(R.layout.mylayout, null);

Mcdade answered 19/6, 2013 at 23:59 Comment(4)
Great comment! I've struggling for hours because of this... Anyone know why?Agnew
This also fixed my problem. I think it's something to do with listview parent requiring layout params.Dismal
This is definitely a wrong answer, you should always pas a parent viewgroup while inflating, there are some exceptions but this is not one of them, for more info see here: doubleencore.com/2013/05/layout-inflation-as-intended. The general problem that people are having is a wrongly configured xml.Preliminaries
This is a solution, but you are using it wrong :). Passing parent as null instantiates the object without a proper container and should be readjusted later, which is time consuming and affects your performance. Instead, use inflate (R.layout.mylayout, parent,false). So what you are saying is use the parent to measure but do not attach to it, as it will be done after returning the viewClobber
P
86

Rule of thumb

You should always try to pass in a parent while inflating a View, else the framework will not be able to identify what layout params to use for that inflated view.

The correct way of handling the exception is by passing false as third parameter, this flag indicates if a view should be added directly to the passed container or not.

In the case of an adapter, the adapter itself will add the view after you returned the view from you getview method:

view = inflater.inflate(R.layout.mylayout, parent, **false**);

BaseAdapter sample, comes from just-for-us DevBytes:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View result = convertView;
    if (result == null) {
        result = mInflater.inflate(R.layout.grid_item, parent, false);
    }

    // Try to get view cache or create a new one if needed
    ViewCache viewCache = (ViewCache) result.getTag();
    if (viewCache == null) {
        viewCache = new ViewCache(result);
        result.setTag(viewCache);
    }

    // Fetch item
    Coupon coupon = getItem(position);

    // Bind the data
    viewCache.mTitleView.setText(coupon.mTitle);
    viewCache.mSubtitleView.setText(coupon.mSubtitle);
    viewCache.mImageView.setImageURI(coupon.mImageUri);

    return result;
}

CursorAdapter sample:

@Override
public View newView(final Context context, final Cursor cursor, final ViewGroup root)          {
    return mInflater.inflate(R.layout.list_item_ticket, root, false);
}

More information about view inflation can be found in this article.

Preliminaries answered 25/8, 2014 at 12:57 Comment(1)
ViewCache does not exist as a class, and I have found this same code in many forums, is it a copy paste? Have you ever tried to make it compile?Crake
G
15

When creating an ArrayAdapter like yours, the ArrayAdapter needs a layout resource containing just a TextView. Try changing your ArrayAdapter creation with:

setListAdapter(new ArrayAdapter<String>(this, 
      android.R.layout.simple_list_item_1, 
      this.directoryEntries));

and see if it works.

Grub answered 1/1, 2011 at 23:49 Comment(7)
Great! It works thank you so much! I have a doubt about your answer, what does "android.R.layout.simple_list_item_1" include? If I use "android.R.layout.simple_list_item_1", what happens with the layout I did with a Listview and a textview? Thanks a lot!Lucania
When you create an ArrayAdapter you pass a layout resource to be used on each list item (and ArrayAdapter only wants a TextView). The layout file where you setup the "screen" is meant to be used inside onCreate, with setContentView(R.layout.your_layout).Grub
COuld I change "android.R.layout.simple_list_item_1" to R.layout.myxml if that xml file had the following code?: <?xml version="1.0" encoding="utf-8"?> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" />Lucania
I'm not sure if I get it. So, in OnCreate a should have setContentView(R.layout.my_layout with only a TextView and then on the adapter i have to pass the layout resource android.R.layout.simple_list_item_1?Lucania
Your previous comment is right, you can pass your own layout to the ArrayAdapter constructor. But your second comment is wrong, on setContentView you pass tge whole activity initial layout (headers, buttons, the ListView, etc). Although on ListActivities there's already a default layout with the ListView.Grub
So if I want to do a ListView, I don't have to creat my own layout? I just pass the default layout?Lucania
If you want to create your own layout for the whole screen, you can pass it to the setContentView method. If you want to create your own "list items" textview layout, you can pass it to the ArrayAdapter constructor.Grub
N
7

my problem was this: I override getView in arrayAdapter. then when I inflated view, I forgot to set attach to root to false and that caused this exception.

this is how must be done:

convertView = LayoutInflater.from(getContext()).inflate(R.layout.market_search_product_view, parent,false);

after that problem solved!

https://stacklearn.ir

Nanaam answered 3/9, 2019 at 8:43 Comment(0)
G
3

Delete TextView From ListView in your XML file

Gotham answered 1/5, 2018 at 7:23 Comment(0)
N
0

If you added a button/text view inside your List View, delete it. That's causing the problem.

Nocuous answered 27/9, 2022 at 14:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.