Search code examples
c#androidxamaringridview

Android GridView Adapter uses wrong position


I'm developing with Xamarain Android on C# targeted at KitKat (4.4 - API19).

Setting

So I have this list of vehicles I wanted to render using the GridView. As this is within some tabbing the GridView is contained within a fragment to be created when first clicking on the corresponding tab (code not shown here). That works fine, the problem arises when the GarageFragmentAdapter starts to getting Views. I made sure the fragment and adapter are only created once, so it is not an issue of multiple instances colliding with their works. I haven't attached any bells or whistles (scrolling reaction or item reaction) at the moment its just about the rendering.

Problem

In my example, I have 4 vehicles, so my list is 4 items long. The first call to the adapter uses position 0 (ok), the second call also uses position 0 (NOT ok) and then there is only a third call which uses position 1 (definitely not ok) and no fourth call. The visual output is then only two items being shown which is also not what I'd expect but I reckon the GridView uses the position to render an item AT position x.

So my question would be, how to I convince the adapter to correctly iterate through my data list?

Code

The code as seen below is the latest iteration, beforehand the adapter was set within the fragment, which I thought was the problem due to reading somewhere this can be an issue.

public class GarageFragment : Fragment
{
    private readonly VehiclesResponse _garageResponse;
    private readonly GarageFragmentAdapter _adapter;

    public GarageFragment(VehiclesResponse garageResponse, GarageFragmentAdapter adapter)
    {
        _garageResponse = garageResponse;
        _adapter = adapter;
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var fragmentView = inflater.Inflate(Resource.Layout.fragment_garage, container, false);
        fragmentView.FindViewById<GridView>(Resource.Id.gridVehicleCards).Adapter = _adapter;
        fragmentView.FindViewById<Button>(Resource.Id.btnShowFullGarage).Visibility = _garageResponse.TotalCarsInGarageCount > 4 ? ViewStates.Visible : ViewStates.Gone;
        fragmentView.FindViewById<LinearLayout>(Resource.Id.boxAddVehicles).Visibility = _garageResponse.CanAddVehicles ? ViewStates.Visible : ViewStates.Gone;

        return fragmentView;
    }
}

public class GarageFragmentAdapter : BaseAdapter
{
    private readonly Activity _context;
    private readonly IList<Vehicle> _tileList;

    public GarageFragmentAdapter(Activity context, IList<Vehicle> vehicles)
    {
        _context = context;
        _tileList = vehicles;
    }

    public override int Count => _tileList.Count;

    public override Object GetItem(int position)
    {
        return null;
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        var view = convertView;
        if (view == null)
        {
            var item = _tileList[position];
            view = _context.LayoutInflater.Inflate(Resource.Layout.BasicVehicleCard, null);
            view.FindViewById<TextView>(Resource.Id.vehicleName).Text = item.Name;
        }

        return view;
    }
}

Solution

  • It appears GridView does not work as I would expect. It does not grow along with the provided content, it defines how much content it will show / load depending on the space it has. (something which would have been nice to be stated in the documentation of the GridView)

    As this is not feasible for my requirement I will instead use GridLayout and add the content element views therein.