using System; using Android.Widget; using Android.App; using System.Collections.Generic; using Android.Views; using System.Collections; using System.Linq; using Xamarin.Forms.Controls; using Xamarin.Forms.Platform.Android; using Xamarin.Forms; using Xamarin.Forms.ControlGallery.Android; using Android.Graphics.Drawables; using System.Threading.Tasks; using Android.Content; using Android.Runtime; using Android.Util; using AButton = Android.Widget.Button; [assembly: ExportRenderer (typeof (Bugzilla31395.CustomContentView), typeof (CustomContentRenderer))] [assembly: ExportRenderer (typeof (NativeListView), typeof (NativeListViewRenderer))] [assembly: ExportRenderer (typeof (NativeListView2), typeof (NativeAndroidListViewRenderer))] [assembly: ExportRenderer (typeof (NativeCell), typeof (NativeAndroidCellRenderer))] namespace Xamarin.Forms.ControlGallery.Android { public class NativeListViewRenderer : ViewRenderer { public NativeListViewRenderer () { } protected override void OnElementChanged (ElementChangedEventArgs e) { base.OnElementChanged (e); if (Control == null) { SetNativeControl (new global::Android.Widget.ListView (Forms.Context)); } if (e.OldElement != null) { // unsubscribe Control.ItemClick -= Clicked; } if (e.NewElement != null) { // subscribe Control.Adapter = new NativeListViewAdapter (Forms.Context as Activity, e.NewElement); Control.ItemClick += Clicked; } } void Clicked (object sender, AdapterView.ItemClickEventArgs e) { Element.NotifyItemSelected (Element.Items.ToList()[e.Position]); } protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged (sender, e); if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) { // update the Items list in the UITableViewSource Control.Adapter = new NativeListViewAdapter (Forms.Context as Activity, Element); } } } public class NativeListViewAdapter: BaseAdapter { readonly Activity _context; IList _tableItems = new List(); public IEnumerable Items { set { _tableItems = value.ToList(); } } public NativeListViewAdapter(Activity context, NativeListView view) { _context = context; _tableItems = view.Items.ToList(); } public override string this[int position] { get { return _tableItems[position]; } } public override long GetItemId(int position) { return position; } public override int Count { get { return _tableItems.Count; } } public override global::Android.Views.View GetView(int position, global::Android.Views.View convertView, ViewGroup parent) { // Get our object for this position var item = _tableItems[position]; var view = convertView; if (view == null) { // no view to re-use, create new view = _context.LayoutInflater.Inflate(global::Android.Resource.Layout.SimpleListItem1, null); } view.FindViewById (global::Android.Resource.Id.Text1).Text = item; return view; } } /// /// This renderer uses a view defined in /Resources/Layout/NativeAndroidCell.axml /// as the cell layout /// public class NativeAndroidCellRenderer : ViewCellRenderer { public NativeAndroidCellRenderer () { } protected override global::Android.Views.View GetCellCore (Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context) { var x = (NativeCell)item; var view = convertView; if (view == null) {// no view to re-use, create new view = (context as Activity).LayoutInflater.Inflate (Resource.Layout.NativeAndroidCell, null); } else { // re-use, clear image // doesn't seem to help //view.FindViewById (Resource.Id.Image).Drawable.Dispose (); } view.FindViewById(Resource.Id.Text1).Text = x.Name; view.FindViewById(Resource.Id.Text2).Text = x.Category; // grab the old image and dispose of it // TODO: optimize if the image is the *same* and we want to just keep it if (view.FindViewById (Resource.Id.Image).Drawable != null) { using (var image = view.FindViewById (Resource.Id.Image).Drawable as BitmapDrawable) { if (image != null) { if (image.Bitmap != null) { //image.Bitmap.Recycle (); image.Bitmap.Dispose (); } } } } // If a new image is required, display it if (!string.IsNullOrWhiteSpace (x.ImageFilename)) { context.Resources.GetBitmapAsync (x.ImageFilename).ContinueWith ((t) => { var bitmap = t.Result; if (bitmap != null) { view.FindViewById (Resource.Id.Image).SetImageBitmap (bitmap); bitmap.Dispose (); } }, TaskScheduler.FromCurrentSynchronizationContext() ); } else { // clear the image view.FindViewById (Resource.Id.Image).SetImageBitmap (null); } return view; } } public class NativeAndroidListViewRenderer : ViewRenderer { public NativeAndroidListViewRenderer () { } protected override void OnElementChanged (ElementChangedEventArgs e) { base.OnElementChanged (e); if (Control == null) { SetNativeControl (new global::Android.Widget.ListView (Forms.Context)); } if (e.OldElement != null) { // unsubscribe Control.ItemClick -= Clicked; } if (e.NewElement != null) { // subscribe Control.Adapter = new NativeAndroidListViewAdapter (Forms.Context as Activity, e.NewElement); Control.ItemClick += Clicked; } } // public override void Layout (int l, int t, int r, int b) // { // base.Layout (l, t, r, b); // } void Clicked (object sender, AdapterView.ItemClickEventArgs e) { Element.NotifyItemSelected (Element.Items.ToList()[e.Position]); } protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged (sender, e); if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) { // update the Items list in the UITableViewSource Control.Adapter = new NativeAndroidListViewAdapter (Forms.Context as Activity, Element); } } } /// /// This adapter uses a view defined in /Resources/Layout/NativeAndroidListViewCell.axml /// as the cell layout /// public class NativeAndroidListViewAdapter : BaseAdapter { readonly Activity _context; IList _tableItems = new List(); public IEnumerable Items { set { _tableItems = value.ToList(); } } public NativeAndroidListViewAdapter(Activity context, NativeListView2 view) { _context = context; _tableItems = view.Items.ToList(); } public override DataSource this[int position] { get { return _tableItems[position]; } } public override long GetItemId(int position) { return position; } public override int Count { get { return _tableItems.Count; } } public override global::Android.Views.View GetView(int position, global::Android.Views.View convertView, ViewGroup parent) { var item = _tableItems[position]; var view = convertView; if (view == null) {// no view to re-use, create new view = _context.LayoutInflater.Inflate (Resource.Layout.NativeAndroidListViewCell, null); } else { // re-use, clear image // doesn't seem to help //view.FindViewById (Resource.Id.Image).Drawable.Dispose (); } view.FindViewById(Resource.Id.Text1).Text = item.Name; view.FindViewById(Resource.Id.Text2).Text = item.Category; // grab the old image and dispose of it // TODO: optimize if the image is the *same* and we want to just keep it if (view.FindViewById (Resource.Id.Image).Drawable != null) { using (var image = view.FindViewById (Resource.Id.Image).Drawable as BitmapDrawable) { if (image != null) { if (image.Bitmap != null) { //image.Bitmap.Recycle (); image.Bitmap.Dispose (); } } } } // If a new image is required, display it if (!string.IsNullOrWhiteSpace (item.ImageFilename)) { _context.Resources.GetBitmapAsync (item.ImageFilename).ContinueWith ((t) => { var bitmap = t.Result; if (bitmap != null) { view.FindViewById (Resource.Id.Image).SetImageBitmap (bitmap); bitmap.Dispose (); } }, TaskScheduler.FromCurrentSynchronizationContext()); } else { // clear the image view.FindViewById (Resource.Id.Image).SetImageBitmap (null); } return view; } } public class CustomContentRenderer : ViewRenderer { } public class CustomNativeButton : AButton { public CustomNativeButton (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) { } public CustomNativeButton (Context context) : base (context) { } public CustomNativeButton (Context context, IAttributeSet attrs) : base (context, attrs) { } public CustomNativeButton (Context context, IAttributeSet attrs, int defStyleAttr) : base (context, attrs, defStyleAttr) { } public CustomNativeButton (Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base (context, attrs, defStyleAttr, defStyleRes) { } } public class CustomButtonRenderer : ButtonRenderer { protected override void OnElementChanged (ElementChangedEventArgs