How to: gridview inside a fragment?

24,553

Solution 1

This should work fine, you just can't use a gridView in a ListFragment - just use a plain old Fragment instead, if you're going to be manually managing the grid anyway

Also, the point of checking if convertView is null is to do view recycling - the OS only declares enough views to fill the screen and no more, so if you scroll then it can reuse the view instead of having to inflate a new one. Change up your getView() like so to take advantage:

public View getView(int position, View convertView, ViewGroup parent) {
  View v;

  if (convertView == null) {
    v = LayoutInflater.from(mContext).inflate(R.layout.image_text_view,null);
    v.setLayoutParams(new GridView.LayoutParams(200,200));
  }
  else {
    v = convertView;
  }

  ImageView imageview = (ImageView)v.findViewById(R.id.image);
  imageview.setScaleType(ImageView.ScaleType.CENTER_CROP);
  imageview.setPadding(6, 6, 6, 6);
  imageDownloader.download(URLS[position], imageview);

  return v;
}

Also, getView isn't a function of BaseAdapter, try switching to ArrayAdapter instead. As a side note, always use @Override when you think you're overriding a base function - that way the compiler will give you an error if you make a mistake

Solution 2

Using a GridView in a Fragment shouldn't be any different than using it in an Activity. One glaring error I see with your code is that you are inflating a layout in onActivityCreated and then promptly ignore it. Instead you should do all of your view initialization in onCreateView which conveniently provides a LayoutInflater for your use.

As for its current behavior, it makes a lot of sense why it's acting how it is. I believe that ListFragment inflates a layout that contains a ListView if the programmer doesn't provide one (which you currently are not). The ImageAdapter you are setting is then used to provide the Views to the ListView.

So move all of your code that is in onActivityCreated to onCreateView and it should work. You shouldn't need to override onActivityCreated at all unless you need to do something with special with the Activity when your Fragment is attached to it.

And as for using GridView pre 4.0 - GridView has been around since API level 1 so I'd bet that it's fine to use it for all Android API levels.

Share:
24,553
Marckaraujo
Author by

Marckaraujo

Just me.

Updated on April 25, 2020

Comments

  • Marckaraujo
    Marckaraujo about 4 years

    I want to create a gridview like android market, I want to populate this with images from a database on internet. it need to work with androidv4.support, since I want to run 2.2 until 4.0.

    Someone said, that isnt possible to create a gridview in pre-4.0, is it true?

    However It only works when I put use setListAdapter(), but it shows only one image per line, like a listview, when I change to gridview.setAdapter(), it doenst work anymore.

    Here is my try:

    This is the ListFragment class:

     public static class ArrayListFragment extends ListFragment implements OnScrollListener{
    
            ImageAdapter adapter = new ImageAdapter();
    
            @Override
            public void onActivityCreated(Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
    
    
                    LayoutInflater gridInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    View v = gridInflater.inflate(R.layout.imagelist, null);
                    GridView gridView = (GridView) v.findViewById(R.id.list);
    
    
    
    
                ImageDownloader.Mode mode = ImageDownloader.Mode.CORRECT;
    //            ImageAdapter imageAdapter = new ImageAdapter();
                adapter.getImageDownloader().setMode(mode);
                setListAdapter(adapter); 
    //            gridView.setAdapter(adapter);
                getListView().setOnScrollListener(this);
    
            }
    

    This is ImageAdapter class:

        public class ImageAdapter extends BaseAdapter {
    
                private Context mContext;
    
            private final ImageDownloader imageDownloader = new ImageDownloader();
    
                public static int count = 10;
    
    private final String[] URLS = {
            "http://lh5.ggpht.com/_mrb7w4gF8Ds/TCpetKSqM1I/AAAAAAAAD2c/Qef6Gsqf12Y/s144-c/_DSC4374%20copy.jpg",
            "http://lh5.ggpht.com/_Z6tbBnE-swM/TB0CryLkiLI/AAAAAAAAVSo/n6B78hsDUz4/s144-c/_DSC3454.jpg",
            "http://lh3.ggpht.com/_GEnSvSHk4iE/TDSfmyCfn0I/AAAAAAAAF8Y/cqmhEoxbwys/s144-c/_MG_3675.jpg",
            "http://lh6.ggpht.com/_Nsxc889y6hY/TBp7jfx-cgI/AAAAAAAAHAg/Rr7jX44r2Gc/s144-c/IMGP9775a.jpg",
            "http://lh3.ggpht.com/_lLj6go_T1CQ/TCD8PW09KBI/AAAAAAAAQdc/AqmOJ7eg5ig/s144-c/Juvenile%20Gannet%20despute.jpg",
            };
    
                public int getCount() {
                    return count;
                }
    
                public String getItem(int position) {
                    return URLS[position];
                }
    
                public long getItemId(int position) {
                    return URLS[position].hashCode();
                }
             public View getView(int position, View convertView, ViewGroup parent) {
                    View v;
    
                    if (convertView == null) {
                        v = LayoutInflater.from(mContext).inflate(R.layout.image_text_view,null);
                        v.setLayoutParams(new GridView.LayoutParams(200,200));
    
                        ImageView imageview = (ImageView)v.findViewById(R.id.image);
                        imageview.setScaleType(ImageView.ScaleType.CENTER_CROP);
                        imageview.setPadding(6, 6, 6, 6);
                        imageDownloader.download(URLS[position], imageview);
                    }
                 else {
                    v = convertView;
                }
    
                    return v;
                }
    
                public ImageDownloader getImageDownloader() {
                    return imageDownloader;
                }
        }
    

    It could help a lot if anyone have a sample. Thanks

  • Marckaraujo
    Marckaraujo about 12 years
    it works, but now it dont populate the gridview with the images, I am trying to find the error on getView.
  • JRaymond
    JRaymond about 12 years
    @Marckaraujo added a note about GetView - I don't know if it was your problem, but it might help - where are the URL's coming from?
  • Marckaraujo
    Marckaraujo about 12 years
    Nothing yet, I just update the code to show where URL comes from.
  • JRaymond
    JRaymond about 12 years
    @Marckaraujo looks like you're extending from BaseAdapter, which doesn't use getView. Use an ArrayAdapter<String> instead - most things are the same, so it shouldn't be too hard to migrate: developer.android.com/reference/android/widget/…
  • JRaymond
    JRaymond about 12 years
    @Marckaraujo well? what happened?
  • Marckaraujo
    Marckaraujo about 12 years
    Well, I really dont know why but I need to use onActivityCreated, it works with listview, I also tried to move to onCreateView then app crash.
  • Marckaraujo
    Marckaraujo about 12 years
    Sorry for delay, well everyone use extends BaseAdapter, the problem is how to manage to download the image for each position on gridview, someone said that you couldnt simple use imageDownloader.download(URLS[position], imageview); , it needs to create a method to download each image for each position. The ArrayAdapter<String> that you said only works to static/local files. I actually trying to use gridlayout instead or create my own gridlayout, but anyone actually know how to put to work gridlayout_support_v7
  • JRaymond
    JRaymond about 12 years
    @Marckaraujo why not ArrayAdapter<Uri> ? Baseadapter is an ArrayAdapter so I'm having a hard time understanding why it's not working
  • Marckaraujo
    Marckaraujo about 12 years
    See my post: stackoverflow.com/questions/10364727/…. This code sample is nearest I want, I am really hard trying to get this done, maybe is my fault because Im new as android developer
  • UpLate
    UpLate almost 11 years
    @JRaymond I came across your advice by accident, where you recommend using [at]override when you think you're overriding a base function... In my case I am indeed using [at]override above a definition for the getView method in a subclass of BaseAdapter (a method which is not a function of BaseAdapter, as you've pointed out). Yet, I'm not getting any warnings from the compiler. Do you know why? BaseAdapter does implement ListAdapter which itself implements Adapter... which does define a getView... Hmmm. (Eclipse Juno on Windows, ADT 22) Thanks for any input.
  • JRaymond
    JRaymond almost 11 years
    @UpLate Hmm... It's been awhile, so I don't honestly remember what made me write that. From the documentation it would appear I was mistaken, but it's possible that there is some issue in BaseAdapter wrt that particular call - if it's working for you though I should probably delete that part
  • UpLate
    UpLate almost 11 years
    @JRaymond I wouldn't change anything especially now that these comments are present. I checked into this a bit further by adding a new do-nothing method to my BaseAdapter subclass. The moment I put in the [at]Override, Eclipse gave me a warning, in real time (no build necessary). So I'm assuming that the non-warning, for the getView call in that subclass is due to the fact that a getView does indeed lurk, not in the parent class, but in an interface somewhere in the hierarchy. So... explicitly using [at]Override as I code is still a useful "habit" to develop. Thanks for that.