Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Adding a new image to a Recycler View

I've got this script:

    using System;
    using Android.App;
    using Android.Content;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using Android.OS;
    using Android.Support.V7.Widget;
    using System.Collections.Generic;
    using Android.Graphics;
    using System.Net;

    namespace RecyclerViewer
    {
        [Activity (Label = "RecyclerViewer", MainLauncher = true, Icon = "@drawable/icon", Theme = "@android:style/Theme.Material.Light.DarkActionBar")]

        public class MainActivity : Activity
        {
            // RecyclerView instance that displays the photo album:
            RecyclerView mRecyclerView;

            // Layout manager that lays out each card in the RecyclerView:
            RecyclerView.LayoutManager mLayoutManager;

            // Adapter that accesses the data set (a photo album):
            PhotoAlbumAdapter mAdapter;

            // Photo album that is managed by the adapter:
            PhotoAlbum mPhotoAlbum;

            protected override void OnCreate (Bundle bundle)
            {
                base.OnCreate (bundle);

                // Instantiate the photo album:
                mPhotoAlbum = new PhotoAlbum();

                // Set our view from the "main" layout resource:
                SetContentView (Resource.Layout.Main);

                // Get our RecyclerView layout:
                mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

                //............................................................
                // Layout Manager Setup:

                // Use the built-in linear layout manager:
                mLayoutManager = new LinearLayoutManager (this);

                // Or use the built-in grid layout manager (two horizontal rows):
                mLayoutManager = new GridLayoutManager (this, 3, GridLayoutManager.Vertical, false);

                // Plug the layout manager into the RecyclerView:
                mRecyclerView.SetLayoutManager (mLayoutManager);

                //............................................................
                // Adapter Setup:

                // Create an adapter for the RecyclerView, and pass it the
                // data set (the photo album) to manage:
                mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);

                // Register the item click handler (below) with the adapter:
                mAdapter.ItemClick += OnItemClick;

                // Plug the adapter into the RecyclerView:
                mRecyclerView.SetAdapter (mAdapter);

            }

            // Handler for the item click event:
            void OnItemClick (object sender, int position)
            {
                // Display a toast that briefly shows the enumeration of the selected photo:
                int photoNum = position + 1;
                Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
            }
        }

        //----------------------------------------------------------------------
        // VIEW HOLDER

        // Implement the ViewHolder pattern: each ViewHolder holds references
        // to the UI components (ImageView and TextView) within the CardView 
        // that is displayed in a row of the RecyclerView:
        public class PhotoViewHolder : RecyclerView.ViewHolder
        {
            public ImageView Image { get; private set; }
            public TextView Caption { get; private set; }

            // Get references to the views defined in the CardView layout.
            public PhotoViewHolder (View itemView, Action<int> listener) 
                : base (itemView)
            {
                // Locate and cache view references:
                Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
                Caption = itemView.FindViewById<TextView> (Resource.Id.textView);

                // Detect user clicks on the item view and report which item
                // was clicked (by position) to the listener:
                itemView.Click += (sender, e) => listener (base.Position);
            }
        }

        //----------------------------------------------------------------------
        // ADAPTER

        // Adapter to connect the data set (photo album) to the RecyclerView: 
        public class PhotoAlbumAdapter : RecyclerView.Adapter
        {
            // Event handler for item clicks:
            public event EventHandler<int> ItemClick;

            // Underlying data set (a photo album):
            public PhotoAlbum mPhotoAlbum;

            // Load the adapter with the data set (photo album) at construction time:
            public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
            {
                mPhotoAlbum = photoAlbum;
            }

            // Create a new photo CardView (invoked by the layout manager): 
            public override RecyclerView.ViewHolder 
                OnCreateViewHolder (ViewGroup parent, int viewType)
            {
                // Inflate the CardView for the photo:
                View itemView = LayoutInflater.From (parent.Context).Inflate (Resource.Layout.PhotoCardView, parent, false);

                // Create a ViewHolder to find and hold these view references, and 
                // register OnClick with the view holder:
                PhotoViewHolder vh = new PhotoViewHolder (itemView, OnClick); 
                return vh;
            }

            // Fill in the contents of the photo card (invoked by the layout manager):
            public override void OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
            {
                PhotoViewHolder vh = holder as PhotoViewHolder;

                // Set the ImageView and TextView in this ViewHolder's CardView 
                // from this position in the photo album:
                vh.Image.SetImageBitmap(GetImageBitmapFromUrl(mPhotoAlbum[position].PhotoID));
                vh.Caption.Text = mPhotoAlbum[position].Caption;
            }

            // Return the number of photos available in the photo album:
            public override int ItemCount
            {
                get { return mPhotoAlbum.NumPhotos; }
            }

            // Raise an event when the item-click takes place:
            void OnClick (int position)
            {
                if (ItemClick != null)
                    ItemClick (this, position);
            }

            private Bitmap GetImageBitmapFromUrl(string url)
            {
                Bitmap imageBitmap = null;

                using (var webClient = new WebClient())
                {
                    var imageBytes = webClient.DownloadData(url);
                    if (imageBytes != null && imageBytes.Length > 0)
                    {
                        imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
                    }
                }

                return imageBitmap;
            }
        }
    }

And another called "PhotoAlbum.cs" which generate a list view, what I want to be able to do though is easily add another element to the recycler. Any suggestions?

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Support.V7.Widget;
using System.Collections.Generic;

namespace RecyclerViewer
{
    // Photo: contains image resource ID and caption:
    public class Photo
    {
        // Photo ID for this photo:
        public string mPhotoID;

        // Caption text for this photo:
        public string mCaption;

        // Return the ID of the photo:
        public string PhotoID 
        { 
            get { return mPhotoID; } 
        }

        // Return the Caption of the photo:
        public string Caption 
        { 
            get { return mCaption; } 
        }
    }

    // Photo album: holds image resource IDs and caption:
    public class PhotoAlbum
    {
        // Built-in photo collection - this could be replaced with
        // a photo database:

        public Photo[] mBuiltInPhotos = {
            new Photo { mPhotoID = "http://www.planwallpaper.com/static/images/cool-background-random-17506483-800-600.jpg",
                        mCaption = "Buckingham Palace" },
            new Photo { mPhotoID = "http://www.planwallpaper.com/static/images/cool-background-random-17506483-800-600.jpg",
                        mCaption = "The Eiffel Tower" },
            new Photo { mPhotoID = "http://www.planwallpaper.com/static/images/cool-background-random-17506483-800-600.jpg",
                        mCaption = "The Louvre" },
            new Photo { mPhotoID = "http://www.planwallpaper.com/static/images/cool-background-random-17506483-800-600.jpg",
                        mCaption = "Before mobile phones" },
            new Photo { mPhotoID = "http://www.planwallpaper.com/static/images/colorful-triangles-background_yB0qTG6.jpg",
                        mCaption = "Big Ben skyline" },
            };

        // Array of photos that make up the album:
        private Photo[] mPhotos;

        // Create an instance copy of the built-in photo list and
        // create the random number generator:
        public PhotoAlbum ()
        {
            mPhotos = mBuiltInPhotos;
        }

        // Return the number of photos in the photo album:
        public int NumPhotos 
        { 
            get { return mPhotos.Length; } 
        }

        // Indexer (read only) for accessing a photo:
        public Photo this[int i] 
        {
            get { return mPhotos[i]; }
        }
    }

}

Thanks
Fraser

Best Answer

Answers

  • FraserBenjaminFraserBenjamin USMember ✭✭
    > @BerayBentesen said:
    > @FraserBenjamin You can't handle images with this code :
    >
    > private Bitmap GetImageBitmapFromUrl(string url) { Bitmap imageBitmap = null; using (var webClient = new WebClient()) { var imageBytes = webClient.DownloadData(url); if (imageBytes != null && imageBytes.Length > 0) { imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length); } } return imageBitmap; }
    >
    > You will receive out of memory exception. Use Glide to load and cache images with a single line code.
    >
    > To add images : Just add a new item to list and use notifydatasetchanged method to update recycler view adapter.

    Cheers, what's the best way to add to the array since its stored in another class and then converted into yet another class?
Sign In or Register to comment.