diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..639088e --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +bin +obj +xkpg + +*.suo +*.user +*.userprefs + +*.zip + +*.userprefs + +*.exe + +*.userprefs + +iOS/ELCImagePicker/sample/ELCImagePickerSample.userprefs + +*.xam diff --git a/iOS/ELCImagePicker/ELCImagePickerViewController.cs b/iOS/ELCImagePicker/ELCImagePickerViewController.cs deleted file mode 100644 index 2f9ef2e..0000000 --- a/iOS/ELCImagePicker/ELCImagePickerViewController.cs +++ /dev/null @@ -1,552 +0,0 @@ -using System; -using MonoTouch.UIKit; -using MonoTouch.AssetsLibrary; -using Vernacular; -using System.Collections.Generic; -using System.Drawing; -using MonoTouch.Foundation; -using System.Threading.Tasks; - -namespace ELCPicker -{ - public class AssetResult - { - public UIImage Image { get; set; } - } - - - /** - * Presents a photo picker dialog capable of selecting multiple images at once. - * Usage: - * - * var picker = ELCImagePickerViewController.Instance; - * picker.MaximumImagesCount = 15; - * picker.Completion.ContinueWith (t => { - * if (t.IsCancelled || t.Exception != null) { - * // no pictures for you! - * } else { - * // t.Result is a List - * } - * }); - * - * PresentViewController (picker, true, null); - */ - public class ELCImagePickerViewController : UINavigationController - { - public int MaximumImagesCount { get; set; } - - readonly TaskCompletionSource> _TaskCompletionSource = new TaskCompletionSource> (); - public Task> Completion { - get { - return _TaskCompletionSource.Task; - } - } - - public static ELCImagePickerViewController Instance { - get { - var albumPicker = new ELCAlbumPickerController (); - var picker = new ELCImagePickerViewController (albumPicker); - albumPicker.Parent = picker; - picker.MaximumImagesCount = 4; - picker.NavigationBar.BarStyle = UIBarStyle.Black; - return picker; - } - } - - ELCImagePickerViewController (UIViewController rootController) : base (rootController) - { - - } - - void SelectedAssets (List assets) - { - var results = new List (assets.Count); - foreach (var asset in assets) { - var obj = asset.AssetType; - if (obj == default (ALAssetType)) - continue; - - var rep = asset.DefaultRepresentation; - if (rep != null) { - var result = new AssetResult (); - UIImageOrientation orientation = UIImageOrientation.Up; - var cgImage = rep.GetFullScreenImage (); - result.Image = new UIImage (cgImage, 1.0f, orientation); - results.Add (result); - } - } - - _TaskCompletionSource.TrySetResult (results); - } - - void CancelledPicker () - { - _TaskCompletionSource.TrySetCanceled (); - } - - bool ShouldSelectAsset (ALAsset asset, int previousCount) - { - var shouldSelect = MaximumImagesCount <= 0 || previousCount < MaximumImagesCount; - if (!shouldSelect) { - string title = Catalog.Format (Catalog.GetString ("Only {0} photos please!"), MaximumImagesCount); - string message = Catalog.Format (Catalog.GetString ("You can only send {0} photos at a time."), MaximumImagesCount); - var alert = new UIAlertView (title, message, null, null, Catalog.GetString ("Okay")); - alert.Show (); - } - return shouldSelect; - } - - public class ELCAlbumPickerController : UITableViewController - { - static readonly NSObject _Dispatcher = new NSObject(); - readonly List AssetGroups = new List (); - - ALAssetsLibrary Library; - - WeakReference _Parent; - public ELCImagePickerViewController Parent { - get { - return _Parent == null ? null : _Parent.Target as ELCImagePickerViewController; - } - set { - _Parent = new WeakReference (value); - } - } - - public ELCAlbumPickerController () - { - } - - public override void ViewDidLoad () - { - base.ViewDidLoad (); - - NavigationItem.Title = Catalog.GetString ("Loading..."); - var cancelButton = new UIBarButtonItem (UIBarButtonSystemItem.Cancel/*, cancelImagePicker*/); - cancelButton.Clicked += CancelClicked; - NavigationItem.RightBarButtonItem = cancelButton; - - AssetGroups.Clear (); - - Library = new ALAssetsLibrary (); - Library.Enumerate (ALAssetsGroupType.All, GroupsEnumerator, GroupsEnumeratorFailed); - } - - public override void ViewDidDisappear (bool animated) - { - base.ViewDidDisappear (animated); - if (IsMovingFromParentViewController || IsBeingDismissed) { - NavigationItem.RightBarButtonItem.Clicked -= CancelClicked; - } - } - - void CancelClicked (object sender = null, EventArgs e = null) - { - var parent = Parent; - if (parent != null) { - parent.CancelledPicker (); - } - } - - void GroupsEnumeratorFailed (MonoTouch.Foundation.NSError error) - { - Console.WriteLine ("Enumerator failed!"); - } - - void GroupsEnumerator (ALAssetsGroup agroup, ref bool stop) - { - if (agroup == null) { - return; - } - - // added fix for camera albums order - if (agroup.Name.ToString ().ToLower () == "camera roll" && agroup.Type == ALAssetsGroupType.SavedPhotos) { - AssetGroups.Insert (0, agroup); - } else { - AssetGroups.Add (agroup); - } - - _Dispatcher.BeginInvokeOnMainThread (ReloadTableView); - } - - void ReloadTableView () - { - TableView.ReloadData (); - NavigationItem.Title = Catalog.GetString ("Select an Album"); - } - - public override int NumberOfSections (UITableView tableView) - { - return 1; - } - - public override int RowsInSection (UITableView tableview, int section) - { - return AssetGroups.Count; - } - - public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) - { - const string cellIdentifier = "Cell"; - - var cell = tableView.DequeueReusableCell (cellIdentifier); - if (cell == null) { - cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier); - } - - // Get count - var g = AssetGroups [indexPath.Row]; - g.SetAssetsFilter (ALAssetsFilter.AllPhotos); - var gCount = g.Count; - cell.TextLabel.Text = string.Format ("{0} ({1})", g.Name, gCount); - try { - cell.ImageView.Image = new UIImage (g.PosterImage); - } catch (Exception e) { - Console.WriteLine ("Failed to set thumbnail {0}", e); - } - cell.Accessory = UITableViewCellAccessory.DisclosureIndicator; - - return cell; - } - - public override void RowSelected (UITableView tableView, NSIndexPath indexPath) - { - var assetGroup = AssetGroups [indexPath.Row]; - assetGroup.SetAssetsFilter (ALAssetsFilter.AllPhotos); - var picker = new ELCAssetTablePicker (assetGroup); - picker.Parent = Parent; - NavigationController.PushViewController (picker, true); - } - - public override float GetHeightForRow (UITableView tableView, NSIndexPath indexPath) - { - return 57; - } - } - - - class ELCAssetTablePicker : UITableViewController - { - static readonly NSObject _Dispatcher = new NSObject(); - - int Columns = 4; - public bool SingleSelection { get; set; } - public bool ImmediateReturn { get; set; } - readonly ALAssetsGroup AssetGroup; - - readonly List ElcAssets = new List (); - - WeakReference _Parent; - public ELCImagePickerViewController Parent { - get { - return _Parent == null ? null : _Parent.Target as ELCImagePickerViewController; - } - set { - _Parent = new WeakReference (value); - } - } - - public ELCAssetTablePicker (ALAssetsGroup assetGroup) - { - AssetGroup = assetGroup; - } - - public override void ViewDidLoad () - { - TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None; - TableView.AllowsSelection = false; - - if (ImmediateReturn) { - - } else { - var doneButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done); - doneButtonItem.Clicked += DoneClicked; - NavigationItem.RightBarButtonItem = doneButtonItem; - NavigationItem.Title = Catalog.GetString ("Loading..."); - } - - Task.Run ((Action)PreparePhotos); - } - - public override void ViewWillAppear (bool animated) - { - base.ViewWillAppear (animated); - Columns = (int)(View.Bounds.Size.Width / 80f); - } - - public override void ViewDidDisappear (bool animated) - { - base.ViewDidDisappear (animated); - if (IsMovingFromParentViewController || IsBeingDismissed) { - NavigationItem.RightBarButtonItem.Clicked -= DoneClicked; - } - } - - public override void DidRotate (UIInterfaceOrientation fromInterfaceOrientation) - { - base.DidRotate (fromInterfaceOrientation); - Columns = (int)(View.Bounds.Size.Width / 80f); - TableView.ReloadData (); - } - - void PreparePhotos () - { - AssetGroup.Enumerate (PhotoEnumerator); - - _Dispatcher.BeginInvokeOnMainThread (() => { - TableView.ReloadData (); - // scroll to bottom - int section = NumberOfSections (TableView) - 1; - int row = TableView.NumberOfRowsInSection (section) - 1; - if (section >= 0 && row >= 0) { - var ip = NSIndexPath.FromRowSection (row, section); - TableView.ScrollToRow (ip, UITableViewScrollPosition.Bottom, false); - } - NavigationItem.Title = SingleSelection ? Catalog.GetString ("Pick Photo") : Catalog.GetString ("Pick Photos"); - }); - } - - void PhotoEnumerator (ALAsset result, int index, ref bool stop) - { - if (result == null) { - return; - } - - ELCAsset elcAsset = new ELCAsset (this, result); - - bool isAssetFiltered = false; - /*if (self.assetPickerFilterDelegate && - [self.assetPickerFilterDelegate respondsToSelector:@selector(assetTablePicker:isAssetFilteredOut:)]) - { - isAssetFiltered = [self.assetPickerFilterDelegate assetTablePicker:self isAssetFilteredOut:(ELCAsset*)elcAsset]; - }*/ - - if (result.DefaultRepresentation == null) - isAssetFiltered = true; - - if (!isAssetFiltered) { - ElcAssets.Add (elcAsset); - } - } - - void DoneClicked (object sender = null, EventArgs e = null) - { - var selected = new List (); - - foreach (var asset in ElcAssets) { - if (asset.Selected) { - selected.Add (asset.Asset); - } - } - - var parent = Parent; - if (parent != null) { - parent.SelectedAssets (selected); - } - } - - bool ShouldSelectAsset (ELCAsset asset) - { - int selectionCount = TotalSelectedAssets; - bool shouldSelect = true; - - var parent = Parent; - if (parent != null) { - shouldSelect = parent.ShouldSelectAsset (asset.Asset, selectionCount); - } - - return shouldSelect; - } - - void AssetSelected (ELCAsset asset, bool selected) - { - TotalSelectedAssets += (selected) ? 1 : -1; - - if (SingleSelection) { - foreach (var elcAsset in ElcAssets) { - if (asset != elcAsset) { - elcAsset.Selected = false; - } - } - } - if (ImmediateReturn) { - var parent = Parent; - var obj = new List (1); - obj.Add (asset.Asset); - parent.SelectedAssets (obj); - } - } - - public override int NumberOfSections (UITableView tableView) - { - return 1; - } - - public override int RowsInSection (UITableView tableview, int section) - { - if (Columns <= 0) - return 4; - int numRows = (int)Math.Ceiling ((float)ElcAssets.Count / Columns); - return numRows; - } - - List AssetsForIndexPath (NSIndexPath path) - { - int index = path.Row * Columns; - int length = Math.Min (Columns, ElcAssets.Count - index); - return ElcAssets.GetRange (index, length); - } - - public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) - { - const string cellIdentifier = "Cell"; - - var cell = TableView.DequeueReusableCell (cellIdentifier) as ELCAssetCell; - if (cell == null) { - cell = new ELCAssetCell (UITableViewCellStyle.Default, cellIdentifier); - } - cell.SetAssets (AssetsForIndexPath (indexPath), Columns); - return cell; - } - - public override float GetHeightForRow (UITableView tableView, NSIndexPath indexPath) - { - return 79; - } - - public int TotalSelectedAssets; - - public class ELCAsset - { - public readonly ALAsset Asset; - readonly WeakReference _Parent; - - bool _Selected; - - public ELCAsset (ELCAssetTablePicker parent, ALAsset asset) - { - _Parent = new WeakReference (parent); - Asset = asset; - } - - public void ToggleSelected () - { - Selected = !Selected; - } - - public bool Selected { - get { - return _Selected; - } - - set { - var parent = _Parent.Target as ELCAssetTablePicker; - if (value && parent != null && !parent.ShouldSelectAsset (this)) { - return; - } - - _Selected = value; - - if (parent != null) { - parent.AssetSelected (this, value); - } - } - } - } - - class ELCAssetCell : UITableViewCell - { - List RowAssets; - int Columns; - readonly List ImageViewArray = new List (); - readonly List OverlayViewArray = new List (); - - public ELCAssetCell (UITableViewCellStyle style, string reuseIdentifier) : base (style, reuseIdentifier) - { - UITapGestureRecognizer tapRecognizer = new UITapGestureRecognizer (CellTapped); - AddGestureRecognizer (tapRecognizer); - - } - - public void SetAssets (List assets, int columns) - { - RowAssets = assets; - Columns = columns; - - foreach (var view in ImageViewArray) { - view.RemoveFromSuperview (); - } - foreach (var view in OverlayViewArray) { - view.RemoveFromSuperview (); - } - - UIImage overlayImage = null; - for (int i = 0; i < RowAssets.Count; i++) { - var asset = RowAssets [i]; - - if (i < ImageViewArray.Count) { - var imageView = ImageViewArray [i]; - imageView.Image = new UIImage (asset.Asset.Thumbnail); - } else { - var imageView = new UIImageView (new UIImage (asset.Asset.Thumbnail)); - ImageViewArray.Add (imageView); - } - - if (i < OverlayViewArray.Count) { - var overlayView = OverlayViewArray [i]; - overlayView.Hidden = !asset.Selected; - } else { - if (overlayImage == null) { - overlayImage = new UIImage ("Overlay.png"); - } - var overlayView = new UIImageView (overlayImage); - OverlayViewArray.Add (overlayView); - overlayView.Hidden = !asset.Selected; - } - } - } - - void CellTapped (UITapGestureRecognizer tapRecognizer) - { - PointF point = tapRecognizer.LocationInView (this); - var totalWidth = Columns * 75 + (Columns - 1) * 4; - var startX = (Bounds.Size.Width - totalWidth) / 2; - - var frame = new RectangleF (startX, 2, 75, 75); - for (int i = 0; i < RowAssets.Count; ++i) { - if (frame.Contains (point)) { - ELCAsset asset = RowAssets [i]; - asset.Selected = !asset.Selected; - var overlayView = OverlayViewArray [i]; - overlayView.Hidden = !asset.Selected; - break; - } - var x = frame.X + frame.Width + 4; - frame = new RectangleF (x, frame.Y, frame.Width, frame.Height); - } - } - - public override void LayoutSubviews () - { - var totalWidth = Columns * 75 + (Columns - 1) * 4; - var startX = (Bounds.Size.Width - totalWidth) / 2; - - var frame = new RectangleF (startX, 2, 75, 75); - - int i = 0; - foreach (var imageView in ImageViewArray) { - imageView.Frame = frame; - AddSubview (imageView); - - var overlayView = OverlayViewArray [i++]; - overlayView.Frame = frame; - AddSubview (overlayView); - - var x = frame.X + frame.Width + 4; - frame = new RectangleF (x, frame.Y, frame.Width, frame.Height); - } - } - } - } - } -} \ No newline at end of file diff --git a/iOS/ELCImagePicker/Rakefile b/iOS/ELCImagePicker/Rakefile new file mode 100755 index 0000000..5ce89c4 --- /dev/null +++ b/iOS/ELCImagePicker/Rakefile @@ -0,0 +1,24 @@ +require "rake/clean" + +CLEAN.include "*.xam" +CLEAN.include ".xpkg" + +file ".xpkg/xamarin-component.exe" do + puts "* Downloading xpkg..." + mkdir "xpkg" + sh "curl -L https://components.xamarin.com/submit/xpkg > xpkg.zip" + sh "unzip -q -o xpkg.zip -d .xpkg" + sh "rm xpkg.zip" +end + +task :default => ".xpkg/xamarin-component.exe" do + line = <<-END + mono .xpkg/xamarin-component.exe package + END + puts "* Creating ELCImagePicker Component" + puts line.strip.gsub "\t\t", "\\\n " + sh line, :verbose => false + puts "* Created ELCImagePicker Component" +end + + diff --git a/iOS/ELCImagePicker/component.yaml b/iOS/ELCImagePicker/component.yaml new file mode 100644 index 0000000..a172738 --- /dev/null +++ b/iOS/ELCImagePicker/component.yaml @@ -0,0 +1,29 @@ +%YAML 1.2 +--- +build: + - path: src/ELCImagePicker.sln + configuration: Release +name: ELCImagePicker +id: elcimagepicker +publisher: Dave Humphreys +license: component/License.md +icons: + - component/elcimagepicker_128x128.png + - component/elcimagepicker_512x512.png +publisher-url: https://github.com/newky2k/XamarinSharpPlus/tree/master/iOS/ELCImagePicker +libraries: + ios-unified: + - src/ELCImagePicker/bin/Release/ELCImagePicker.dll +summary: A Multi-Image picker that uses the asset library +details: component/Details.md +screenshots: + - component/screenshots/Screen1.jpg + - component/screenshots/Screen2.jpg +getting-started: component/GettingStarted.md +version: 1.4 +samples: + - path: sample/ELCImagePickerSample.sln + name: iOS Sample + nobuild: "true" + configuration: Release|iPhone +... diff --git a/iOS/ELCImagePicker/component/Details.md b/iOS/ELCImagePicker/component/Details.md new file mode 100644 index 0000000..34b39ee --- /dev/null +++ b/iOS/ELCImagePicker/component/Details.md @@ -0,0 +1,29 @@ +# ELCImagePicker + +*A clone of the UIImagePickerController using the Assets Library Framework allowing for multiple asset selection.* + + * Multi-select of images + * Support for Xamarin.iOS Unified API + * Returns UIImage, Name and Asset path of the selected items + * TPL-friendly Interface + * Localization support + +## Usage + +The image picker is created and displayed in a very similar manner to the `UIImagePickerController`. The sample application shows its use. To display the controller you instantiate it and display it modally like so. + + var picker = ELCImagePickerViewController.Instance; + picker.MaximumImagesCount = 15; + picker.Completion.ContinueWith (t => { + if (t.IsCanceled || t.Exception != null) { + // no pictures for you! + } else { + var items = t.Result as List; + } + }); + + PresentViewController (picker, true, null); + +Originally ported to C# by [bjdodson](https://github.com/bjdodson/XamarinSharpPlus) + +Ported from Original Objective-C Project - [https://github.com/B-Sides/ELCImagePickerController](https://github.com/B-Sides/ELCImagePickerController) \ No newline at end of file diff --git a/iOS/ELCImagePicker/component/GettingStarted.md b/iOS/ELCImagePicker/component/GettingStarted.md new file mode 100644 index 0000000..ce2a05d --- /dev/null +++ b/iOS/ELCImagePicker/component/GettingStarted.md @@ -0,0 +1,62 @@ +# ELCImagePicker + +*A clone of the UIImagePickerController using the Assets Library Framework allowing for multiple asset selection.* + +## Usage + +The image picker is created and displayed in a very similar manner to the `UIImagePickerController`. The sample application shows its use. To display the controller you instantiate it and display it modally like so. + + var picker = ELCImagePickerViewController.Create(15); + //picker.MaximumImagesCount = 15; + + picker.Completion.ContinueWith (t => { + if (t.IsCanceled || t.Exception != null) { + // no pictures for you! + } else { + var items = t.Result as List; + } + }); + + PresentViewController (picker, true, null); + + +The `AssetResult` class has three properties + + * Name (String) + * Path (String) + * Image (UIImage) + +You can use these to access the UIImage for the selected images and also the name and Asset Library path, for loading it later. + +**Customisation** + +You can now override the default overlay image by setting the static `OverlayImage` property on the `ELCImagePickerViewController` class. + +You can additional specify custom titles for various elements in the Picker view by passing them too the `Create` method of `ELCImagePickerViewController`. + + var picker = ELCImagePickerViewController.Create(15, "Choisir un album", "Choisir Photo", "Retour", "choix Photo"); + //picker.MaximumImagesCount = 15; + + picker.Completion.ContinueWith (t => { + if (t.IsCanceled || t.Exception != null) { + // no pictures for you! + } else { + var items = t.Result as List; + } + }); + + PresentViewController (picker, true, null); + + +**Localisation** + +Most of the labels and strings support localisation. The sample provides an english string file to use as the basis for implementing other languages. + +Simply create a folder in the resources folder within your iOS project which is prefixed with the ISO language code for the required language. Create an empty file called "Localizable.strings" and then duplicate the keys for the english language and then replace the phrases with the localised versions. + + +**Deprecations** + +Please not that the `Instance` property is now deprecated, use the `Create` method instead + + diff --git a/iOS/ELCImagePicker/component/License.md b/iOS/ELCImagePicker/component/License.md new file mode 100644 index 0000000..6535294 --- /dev/null +++ b/iOS/ELCImagePicker/component/License.md @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2010 ELC Technologies + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/iOS/ELCImagePicker/component/elcimagepicker_128x128.png b/iOS/ELCImagePicker/component/elcimagepicker_128x128.png new file mode 100644 index 0000000..79f942a Binary files /dev/null and b/iOS/ELCImagePicker/component/elcimagepicker_128x128.png differ diff --git a/iOS/ELCImagePicker/component/elcimagepicker_512x512.png b/iOS/ELCImagePicker/component/elcimagepicker_512x512.png new file mode 100644 index 0000000..ac9bef9 Binary files /dev/null and b/iOS/ELCImagePicker/component/elcimagepicker_512x512.png differ diff --git a/iOS/ELCImagePicker/component/screenshots/Screen1.jpg b/iOS/ELCImagePicker/component/screenshots/Screen1.jpg new file mode 100644 index 0000000..360d108 Binary files /dev/null and b/iOS/ELCImagePicker/component/screenshots/Screen1.jpg differ diff --git a/iOS/ELCImagePicker/component/screenshots/Screen2.jpg b/iOS/ELCImagePicker/component/screenshots/Screen2.jpg new file mode 100644 index 0000000..8af58a5 Binary files /dev/null and b/iOS/ELCImagePicker/component/screenshots/Screen2.jpg differ diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample.sln b/iOS/ELCImagePicker/sample/ELCImagePickerSample.sln new file mode 100644 index 0000000..6490575 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ELCImagePickerSample", "ELCImagePickerSample\ELCImagePickerSample.csproj", "{3B6B3A49-5688-410C-83ED-5A70849B80F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ELCImagePicker", "..\src\ELCImagePicker\ELCImagePicker.csproj", "{73314109-5606-412D-AE52-A4AA76A70B15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Ad-Hoc|iPhone = Ad-Hoc|iPhone + Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator + AppStore|iPhone = AppStore|iPhone + AppStore|iPhoneSimulator = AppStore|iPhoneSimulator + Debug|iPhone = Debug|iPhone + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.AppStore|iPhone.ActiveCfg = AppStore|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.AppStore|iPhone.Build.0 = AppStore|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Debug|iPhone.ActiveCfg = Debug|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Debug|iPhone.Build.0 = Debug|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Release|iPhone.ActiveCfg = Release|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Release|iPhone.Build.0 = Release|iPhone + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {3B6B3A49-5688-410C-83ED-5A70849B80F8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {73314109-5606-412D-AE52-A4AA76A70B15}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.AppStore|iPhone.Build.0 = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Debug|iPhone.Build.0 = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Release|iPhone.ActiveCfg = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Release|iPhone.Build.0 = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + version = 1.4 + EndGlobalSection +EndGlobal diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/AppDelegate.cs b/iOS/ELCImagePicker/sample/ELCImagePickerSample/AppDelegate.cs new file mode 100644 index 0000000..c250a75 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/AppDelegate.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +using Foundation; +using UIKit; +using ELCImagePicker; + +namespace ELCImagePickerSample +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + + public override UIWindow Window + { + get; + set; + } + public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions) + { + ELCImagePickerViewController.OverlayImage = UIImage.FromBundle ("overlay-black"); + + return true; + + } + // This method is invoked when the application is about to move from active to inactive state. + // OpenGL applications should use this method to pause. + public override void OnResignActivation(UIApplication application) + { + } + + // This method should be used to release shared resources and it should store the application state. + // If your application supports background exection this method is called instead of WillTerminate + // when the user quits. + public override void DidEnterBackground(UIApplication application) + { + } + + // This method is called as part of the transiton from background to active state. + public override void WillEnterForeground(UIApplication application) + { + } + + // This method is called when the application is about to terminate. Save data, if needed. + public override void WillTerminate(UIApplication application) + { + } + } +} + diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELCImagePickerSample.csproj b/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELCImagePickerSample.csproj new file mode 100644 index 0000000..1f43eb9 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELCImagePickerSample.csproj @@ -0,0 +1,134 @@ + + + + Debug + iPhoneSimulator + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3B6B3A49-5688-410C-83ED-5A70849B80F8} + Exe + ELCImagePickerSample + Resources + ELCImagePickerSample + 1.4 + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG; + prompt + 4 + false + i386 + None + true + true + + + full + true + bin\iPhoneSimulator\Release + prompt + 4 + i386 + false + None + + + true + full + false + bin\iPhone\Debug + DEBUG; + prompt + 4 + false + ARMv7, ARM64 + Entitlements.plist + true + iPhone Developer + true + true + + + + + full + true + bin\iPhone\Release + prompt + 4 + Entitlements.plist + ARMv7, ARM64 + false + iPhone Developer + + + full + true + bin\iPhone\Ad-Hoc + prompt + 4 + false + ARMv7, ARM64 + Entitlements.plist + true + iPhone Distribution + Automatic:AdHoc + true + + + full + true + bin\iPhone\AppStore + prompt + 4 + false + ARMv7, ARM64 + Entitlements.plist + Automatic:AppStore + iPhone Distribution + + + + + + + + + + false + + + + + + + + + + + + + + + + + ELImagePickerDemoViewController.cs + + + + + + {73314109-5606-412D-AE52-A4AA76A70B15} + ELCImagePicker + + + + + + + + + \ No newline at end of file diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELImagePickerDemoViewController.cs b/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELImagePickerDemoViewController.cs new file mode 100644 index 0000000..9de4a01 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELImagePickerDemoViewController.cs @@ -0,0 +1,124 @@ +using Foundation; +using System; +using System.CodeDom.Compiler; +using UIKit; +using ELCImagePicker; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ELCImagePickerSample +{ + partial class ELImagePickerDemoViewController : UITableViewController + { + #region Fields + + private List mResults = new List(); + + #endregion + + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// Handle. + public ELImagePickerDemoViewController(IntPtr handle) : base(handle) + { + this.Title = "ELCImagePicker Demo"; + } + + #endregion + + public override void ViewDidLoad() + { + base.ViewDidLoad(); + + var aButton = new UIBarButtonItem(UIBarButtonSystemItem.Add, (s, e) => + { + + //create a new instance of the picker view controller + var picker = ELCImagePickerViewController.Create(15); + + //Provide custom labels for the picker + //var picker = ELCImagePickerViewController.Create(4, "Choisir un album", "Choisir Photo", "Retour", "choix Photo"); + + //picker.InitCustomLabel(); + //set the maximum number of images that can be selected + //picker.MaximumImagesCount = 15; + + //setup the handling of completion once the items have been picked or the picker has been cancelled + picker.Completion.ContinueWith(t => + { + //execute any UI code on the UI thread + this.BeginInvokeOnMainThread(() => + { + //dismiss the picker + picker.DismissViewController(true, null); + + if (t.IsCanceled || t.Exception != null) + { + //cancelled or error + } + else + { + //get the selected items + var items = t.Result as List; + + foreach (AssetResult aItem in items) + { + mResults.Add(aItem); + } + + TableView.ReloadData(); + + } + }); + }); + + + this.PresentViewController(picker, true, null); + + }); + + + this.NavigationItem.RightBarButtonItem = aButton; + } + + public override nint NumberOfSections(UITableView tableView) + { + return 1; + } + + public override nint RowsInSection(UITableView tableview, nint section) + { + return mResults.Count; + } + + public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) + { + const string cellIdentifier = "Cell"; + + var cell = tableView.DequeueReusableCell(cellIdentifier); + if (cell == null) + { + cell = new UITableViewCell(UITableViewCellStyle.Default, cellIdentifier); + } + + var asset = mResults[indexPath.Row]; + + cell.ImageView.Image = asset.Image; + cell.TextLabel.Text = asset.Name; + + return cell; + } + + public override void RowSelected(UITableView tableView, NSIndexPath indexPath) + { + var asset = mResults[indexPath.Row]; + } + + public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath) + { + return 100; + } + } +} diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELImagePickerDemoViewController.designer.cs b/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELImagePickerDemoViewController.designer.cs new file mode 100644 index 0000000..9675317 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/ELImagePickerDemoViewController.designer.cs @@ -0,0 +1,21 @@ +// WARNING +// +// This file has been generated automatically by Xamarin Studio from the outlets and +// actions declared in your storyboard file. +// Manual changes to this file will not be maintained. +// +using Foundation; +using System; +using System.CodeDom.Compiler; +using UIKit; + +namespace ELCImagePickerSample +{ + [Register ("ELImagePickerDemoViewController")] + partial class ELImagePickerDemoViewController + { + void ReleaseDesignerOutlets () + { + } + } +} diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Entitlements.plist b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Entitlements.plist new file mode 100644 index 0000000..9ae5993 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Info.plist b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Info.plist new file mode 100644 index 0000000..b2d984d --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDisplayName + ELCImagePickerSample + CFBundleIdentifier + com.your-company.ELCImagePickerSample + CFBundleShortVersionString + 1.3 + CFBundleVersion + 1.3 + LSRequiresIPhoneOS + + MinimumOSVersion + 7.1 + UIDeviceFamily + + 1 + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + MainStoryboard + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Resources/Images.xcassets/AppIcons.appiconset + CFBundleName + ELCImagePickerSample + NSPhotoLibraryUsageDescription + New Entry + + diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Main.cs b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Main.cs new file mode 100644 index 0000000..7cd063f --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Main.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Foundation; +using UIKit; + +namespace ELCImagePickerSample +{ + public class Application + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/MainStoryboard.storyboard b/iOS/ELCImagePicker/sample/ELCImagePickerSample/MainStoryboard.storyboard new file mode 100644 index 0000000..0fd9e8d --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/MainStoryboard.storyboard @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/Images.xcassets/AppIcons.appiconset/Contents.json b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/Images.xcassets/AppIcons.appiconset/Contents.json new file mode 100644 index 0000000..24f9974 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/Images.xcassets/AppIcons.appiconset/Contents.json @@ -0,0 +1,108 @@ +{ + "images": [ + { + "size": "29x29", + "scale": "1x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "57x57", + "scale": "1x", + "idiom": "iphone" + }, + { + "size": "57x57", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "60x60", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "60x60", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "72x72", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "72x72", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "76x76", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "76x76", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "120x120", + "scale": "1x", + "idiom": "car" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/LaunchScreen.xib b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/LaunchScreen.xib new file mode 100644 index 0000000..17ac50b --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/LaunchScreen.xib @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/en.lproj/Localizable.strings b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000..b424d22 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/en.lproj/Localizable.strings @@ -0,0 +1,12 @@ +"Select an Album" = "Select an Album"; +"Loading" = "Loading..."; +"Okay" = "Okay"; +"Enumerator failed" = "Enumerator failed!"; +"Pick Photo" = "Pick Photo"; +"Pick Photos" = "Pick Photos"; +"Only" = "Only"; +"photos please" = "photos please!"; +"You can only send" = "You can only send"; +"photos at a time" = "photos at a time."; +"Failed to set thumbnail" = "Failed to set thumbnail"; +"Back" = "Back"; \ No newline at end of file diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/overlay-black.png b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/overlay-black.png new file mode 100644 index 0000000..91b8c47 Binary files /dev/null and b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/overlay-black.png differ diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/overlay-black@2x.png b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/overlay-black@2x.png new file mode 100644 index 0000000..ff3c0e7 Binary files /dev/null and b/iOS/ELCImagePicker/sample/ELCImagePickerSample/Resources/overlay-black@2x.png differ diff --git a/iOS/ELCImagePicker/sample/ELCImagePickerSample/fr.lproj/Localizable.strings b/iOS/ELCImagePicker/sample/ELCImagePickerSample/fr.lproj/Localizable.strings new file mode 100644 index 0000000..edcaec7 --- /dev/null +++ b/iOS/ELCImagePicker/sample/ELCImagePickerSample/fr.lproj/Localizable.strings @@ -0,0 +1,10 @@ +"Select an Album"="Choisir un album"; +"Pick Photo"="Choisir Photo"; +"Pick Photos"="Choisir Photos"; +"Loading"="Chargement..."; +"Back"="Retour"; +"You can only send"="Vous pouvez uniquement envoyer"; +"photos at a time"="Photos à la fois"; +"photos please"="Photos svp"; +"Only"="Uniquement"; +"Okay"="Ok"; diff --git a/iOS/ELCImagePicker/src/ELCImagePicker.sln b/iOS/ELCImagePicker/src/ELCImagePicker.sln new file mode 100644 index 0000000..7076b24 --- /dev/null +++ b/iOS/ELCImagePicker/src/ELCImagePicker.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ELCImagePicker", "ELCImagePicker\ELCImagePicker.csproj", "{73314109-5606-412D-AE52-A4AA76A70B15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73314109-5606-412D-AE52-A4AA76A70B15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73314109-5606-412D-AE52-A4AA76A70B15}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/iOS/ELCImagePicker/src/ELCImagePicker.userprefs b/iOS/ELCImagePicker/src/ELCImagePicker.userprefs new file mode 100644 index 0000000..fb32033 --- /dev/null +++ b/iOS/ELCImagePicker/src/ELCImagePicker.userprefs @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/iOS/ELCImagePicker/src/ELCImagePicker/ELCImagePicker.csproj b/iOS/ELCImagePicker/src/ELCImagePicker/ELCImagePicker.csproj new file mode 100644 index 0000000..9ecb162 --- /dev/null +++ b/iOS/ELCImagePicker/src/ELCImagePicker/ELCImagePicker.csproj @@ -0,0 +1,50 @@ + + + + Debug + AnyCPU + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {73314109-5606-412D-AE52-A4AA76A70B15} + Library + ELCImagePicker + Resources + ELCImagePicker + 1.4 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/iOS/ELCImagePicker/src/ELCImagePicker/ELCImagePickerViewController.cs b/iOS/ELCImagePicker/src/ELCImagePicker/ELCImagePickerViewController.cs new file mode 100644 index 0000000..a3066a4 --- /dev/null +++ b/iOS/ELCImagePicker/src/ELCImagePicker/ELCImagePickerViewController.cs @@ -0,0 +1,809 @@ +using System; +using UIKit; +using AssetsLibrary; +using System.Collections.Generic; +using System.Drawing; +using Foundation; +using System.Threading.Tasks; +using CoreGraphics; + +namespace ELCImagePicker +{ + /// + /// Asset result. + /// + public class AssetResult + { + /// + /// Gets or sets the name. + /// + /// The name. + public String Name + { + get; + set; + } + + /// + /// Selected image + /// + /// The image. + public UIImage Image { get; set; } + + /// + /// Gets or sets the path. + /// + /// The path. + public String Path + { + get; + set; + } + } + + + /** + * Presents a photo picker dialog capable of selecting multiple images at once. + * Usage: + * + * var picker = ELCImagePickerViewController.Instance; + * picker.MaximumImagesCount = 15; + * picker.Completion.ContinueWith (t => { + * if (t.IsCancelled || t.Exception != null) { + * // no pictures for you! + * } else { + * // t.Result is a List + * } + * }); + * + * PresentViewController (picker, true, null); + */ + public class ELCImagePickerViewController : UINavigationController + { + + + private static Lazy mDefaultOverlayImage = new Lazy(() => UIImage.FromBundle("overlay-image")); + + private static UIImage mOverlayImage; + + + /// + /// Gets or sets the overlay image. + /// + /// The overlay image. + public static UIImage OverlayImage + { + get + { + if (mOverlayImage == null) + mOverlayImage = mDefaultOverlayImage.Value; + + return mOverlayImage; + + + } + set { mOverlayImage = value; } + + } + + /// + /// Gets or sets the maximum images count. + /// + /// The maximum images count. + public int MaximumImagesCount { get; set; } + + readonly TaskCompletionSource> _TaskCompletionSource = new TaskCompletionSource>(); + + public Task> Completion + { + get + { + return _TaskCompletionSource.Task; + } + } + + [Obsolete("Use Create() instead")] + //static ELCAlbumPickerController albumPicker + public static ELCImagePickerViewController Instance + { + get + { + var albumPicker = new ELCAlbumPickerController(); + + var picker = new ELCImagePickerViewController(albumPicker); + albumPicker.Parent = picker; + picker.MaximumImagesCount = 4; + //picker.NavigationBar.BarStyle = UIBarStyle.Black; + return picker; + } + } + + /// + /// Create a new instance of the Picker + /// + /// Max images. + /// Select album title. + /// Pick photos title. + /// Back batton title. + /// Pick photo title. + /// Done button title. + /// Loadingtitle. + public static ELCImagePickerViewController Create(int maxImages = 4, string selectAlbumTitle = null, string pickPhotosTitle = null, string backBattonTitle = null, string pickPhotoTitle = null, string doneButtonTitle = null, string loadingtitle = null) + { + var albumPicker = new ELCAlbumPickerController() + { + SelectAlbumTitle = selectAlbumTitle, + BackButtonTitle = backBattonTitle, + DoneButtonTitle = doneButtonTitle, + LoadingTitle = loadingtitle, + PickPhotosTitle = pickPhotosTitle, + PickPhotoTitle = pickPhotoTitle, + }; + + var picker = new ELCImagePickerViewController(albumPicker); + albumPicker.Parent = picker; + picker.MaximumImagesCount = maxImages; + return picker; + + } + + ELCImagePickerViewController(UIViewController rootController) : base(rootController) + { + + } + + + void SelectedAssets(List assets) + { + var results = new List(assets.Count); + foreach (var asset in assets) + { + var obj = asset.AssetType; + if (obj == default(ALAssetType)) + continue; + + var rep = asset.DefaultRepresentation; + if (rep != null) + { + var result = new AssetResult(); + UIImageOrientation orientation = UIImageOrientation.Up; + var cgImage = rep.GetFullScreenImage(); + + //set if not null + if (cgImage != null) + result.Image = new UIImage(cgImage, 1.0f, orientation); + + result.Name = rep.Filename; + result.Path = rep.Url.AbsoluteString; + + results.Add(result); + } + } + + _TaskCompletionSource.TrySetResult(results); + } + + void CancelledPicker() + { + _TaskCompletionSource.TrySetCanceled(); + } + + bool ShouldSelectAsset(ALAsset asset, int previousCount) + { + var shouldSelect = MaximumImagesCount <= 0 || previousCount < MaximumImagesCount; + if (!shouldSelect) + { + var first = NSBundle.MainBundle.LocalizedString("Only", "Only"); + var second = NSBundle.MainBundle.LocalizedString("photos please", "photos please!"); + + string title = String.Format("{0} {1} {2}", first, MaximumImagesCount, second); + + var third = NSBundle.MainBundle.LocalizedString("You can only send", "You can only send"); + var fourth = NSBundle.MainBundle.LocalizedString("photos at a time", "photos at a time."); + + string message = String.Format("{0} {1} {2}", third, MaximumImagesCount, fourth); + var alert = new UIAlertView(title, message, null, null, NSBundle.MainBundle.LocalizedString("Okay", "Okay")); + alert.Show(); + } + return shouldSelect; + } + + public class ELCAlbumPickerController : UITableViewController + { + public string DoneButtonTitle { get; set; } + public string BackButtonTitle { get; set; } + public string SelectAlbumTitle { get; set; } + public string LoadingTitle { get; set; } + public string PickPhotoTitle { get; set; } + public string PickPhotosTitle { get; set; } + + static readonly NSObject _Dispatcher = new NSObject(); + readonly List AssetGroups = new List(); + + ALAssetsLibrary Library; + + WeakReference _Parent; + + public ELCImagePickerViewController Parent + { + get + { + return _Parent == null ? null : _Parent.Target as ELCImagePickerViewController; + } + set + { + _Parent = new WeakReference(value); + } + } + + public ELCAlbumPickerController() + { + } + + public override void ViewDidLoad() + { + base.ViewDidLoad(); + string loading = string.IsNullOrWhiteSpace(LoadingTitle) ? NSBundle.MainBundle.LocalizedString("Loading", "Loading...") : LoadingTitle; + + NavigationItem.Title = loading; + var cancelButton = new UIBarButtonItem(UIBarButtonSystemItem.Cancel); + cancelButton.Clicked += CancelClicked; + NavigationItem.RightBarButtonItem = cancelButton; + + AssetGroups.Clear(); + + Library = new ALAssetsLibrary(); + Library.Enumerate(ALAssetsGroupType.All, GroupsEnumerator, GroupsEnumeratorFailed); + } + + public override void ViewDidDisappear(bool animated) + { + base.ViewDidDisappear(animated); + if (IsMovingFromParentViewController || IsBeingDismissed) + { + NavigationItem.RightBarButtonItem.Clicked -= CancelClicked; + } + } + + void CancelClicked(object sender = null, EventArgs e = null) + { + var parent = Parent; + if (parent != null) + { + parent.CancelledPicker(); + } + } + + void GroupsEnumeratorFailed(NSError error) + { + Console.WriteLine(NSBundle.MainBundle.LocalizedString("Enumerator failed", "Enumerator failed!")); + } + + void GroupsEnumerator(ALAssetsGroup agroup, ref bool stop) + { + if (agroup == null) + { + return; + } + + // added fix for camera albums order + if (agroup.Name.ToString().ToLower() == "camera roll" && agroup.Type == ALAssetsGroupType.SavedPhotos) + { + AssetGroups.Insert(0, agroup); + } + else + { + AssetGroups.Add(agroup); + } + + _Dispatcher.BeginInvokeOnMainThread(ReloadTableView); + } + + void ReloadTableView() + { + TableView.ReloadData(); + string selectAlbum = string.IsNullOrWhiteSpace(SelectAlbumTitle) ? NSBundle.MainBundle.LocalizedString("Select an Album", "Select an Album") : SelectAlbumTitle; + NavigationItem.Title = selectAlbum; + } + + public override nint NumberOfSections(UITableView tableView) + { + return 1; + } + + public override nint RowsInSection(UITableView tableview, nint section) + { + return AssetGroups.Count; + } + + public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) + { + const string cellIdentifier = "Cell"; + + var cell = tableView.DequeueReusableCell(cellIdentifier); + if (cell == null) + { + cell = new UITableViewCell(UITableViewCellStyle.Default, cellIdentifier); + } + + // Get count + var g = AssetGroups[indexPath.Row]; + g.SetAssetsFilter(ALAssetsFilter.AllPhotos); + var gCount = g.Count; + cell.TextLabel.Text = string.Format("{0} ({1})", g.Name, gCount); + try + { + cell.ImageView.Image = new UIImage(g.PosterImage); + } + catch (Exception e) + { + Console.WriteLine("{0} {1}", NSBundle.MainBundle.LocalizedString("Failed to set thumbnail", "Failed to set thumbnail"), e); + } + cell.Accessory = UITableViewCellAccessory.DisclosureIndicator; + + return cell; + } + + public override void RowSelected(UITableView tableView, NSIndexPath indexPath) + { + var assetGroup = AssetGroups[indexPath.Row]; + assetGroup.SetAssetsFilter(ALAssetsFilter.AllPhotos); + var picker = new ELCAssetTablePicker(assetGroup); + + picker.LoadingTitle = LoadingTitle; + picker.PickPhotosTitle = PickPhotosTitle; + picker.PickPhotoTitle = PickPhotoTitle; + picker.DoneButtonTitle = DoneButtonTitle; + + picker.Parent = Parent; + + string backButtonTitle = string.IsNullOrWhiteSpace(BackButtonTitle) ? NSBundle.MainBundle.LocalizedString("Back", "Back") : BackButtonTitle; + + this.NavigationItem.BackBarButtonItem = new UIBarButtonItem(backButtonTitle, UIBarButtonItemStyle.Plain, null); + + NavigationController.PushViewController(picker, true); + } + + public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath) + { + return 57; + } + } + + + class ELCAssetTablePicker : UITableViewController + { + private string doneButtonTitle { get; set; } + private string pickPhotoTitle { get; set; } + private string pickPhotosTitle { get; set; } + private string loadingTitle { get; set; } + + public string DoneButtonTitle + { + get + { + if (string.IsNullOrWhiteSpace(doneButtonTitle)) + return NSBundle.MainBundle.LocalizedString("Done", "Done"); + + return doneButtonTitle; + } + set { doneButtonTitle = value; } + } + + public string PickPhotoTitle + { + get + { + if (string.IsNullOrWhiteSpace(pickPhotoTitle)) + return NSBundle.MainBundle.LocalizedString("Pick Photo", "Pick Photo"); + + return pickPhotoTitle; + } + set { pickPhotoTitle = value; } + } + + public string PickPhotosTitle + { + get + { + if (string.IsNullOrWhiteSpace(pickPhotosTitle)) + return NSBundle.MainBundle.LocalizedString("Pick Photos", "Pick Photos"); + + return pickPhotosTitle; + } + set { pickPhotosTitle = value; } + } + + public string LoadingTitle + { + get + { + if (string.IsNullOrWhiteSpace(loadingTitle)) + return NSBundle.MainBundle.LocalizedString("Loading", "Loading..."); + + return loadingTitle; + } + set { loadingTitle = value; } + } + + static readonly NSObject _Dispatcher = new NSObject(); + + int Columns = 4; + + public bool SingleSelection { get; set; } + + public bool ImmediateReturn { get; set; } + + readonly ALAssetsGroup AssetGroup; + + readonly List ElcAssets = new List(); + + WeakReference _Parent; + + public ELCImagePickerViewController Parent + { + get + { + return _Parent == null ? null : _Parent.Target as ELCImagePickerViewController; + } + set + { + _Parent = new WeakReference(value); + } + } + + public ELCAssetTablePicker(ALAssetsGroup assetGroup) + { + AssetGroup = assetGroup; + } + + public override void ViewDidLoad() + { + TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None; + TableView.AllowsSelection = false; + + if (ImmediateReturn) + { + + } + else + { + var doneButtonItem = new UIBarButtonItem(DoneButtonTitle, UIBarButtonItemStyle.Done, null); + doneButtonItem.Clicked += DoneClicked; + NavigationItem.RightBarButtonItem = doneButtonItem; + NavigationItem.Title = LoadingTitle; + } + + Task.Run((Action)PreparePhotos); + } + + public override void ViewWillAppear(bool animated) + { + base.ViewWillAppear(animated); + Columns = (int)(View.Bounds.Size.Width / 80f); + } + + public override void ViewDidDisappear(bool animated) + { + base.ViewDidDisappear(animated); + if (IsMovingFromParentViewController || IsBeingDismissed) + { + NavigationItem.RightBarButtonItem.Clicked -= DoneClicked; + } + } + + public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation) + { + base.DidRotate(fromInterfaceOrientation); + Columns = (int)(View.Bounds.Size.Width / 80f); + TableView.ReloadData(); + } + + void PreparePhotos() + { + AssetGroup.Enumerate(PhotoEnumerator); + + _Dispatcher.BeginInvokeOnMainThread(() => + { + TableView.ReloadData(); + // scroll to bottom + var section = NumberOfSections(TableView) - 1; + var row = TableView.NumberOfRowsInSection(section) - 1; + if (section >= 0 && row >= 0) + { + var ip = NSIndexPath.FromRowSection(row, section); + TableView.ScrollToRow(ip, UITableViewScrollPosition.Bottom, false); + } + + + NavigationItem.Title = SingleSelection ? PickPhotoTitle : PickPhotosTitle; + }); + } + + #region Not interested in + void PhotoEnumerator(ALAsset result, nint index, ref bool stop) + { + if (result == null) + { + return; + } + + ELCAsset elcAsset = new ELCAsset(this, result); + + bool isAssetFiltered = false; + /*if (self.assetPickerFilterDelegate && + [self.assetPickerFilterDelegate respondsToSelector:@selector(assetTablePicker:isAssetFilteredOut:)]) + { + isAssetFiltered = [self.assetPickerFilterDelegate assetTablePicker:self isAssetFilteredOut:(ELCAsset*)elcAsset]; + }*/ + + if (result.DefaultRepresentation == null) + isAssetFiltered = true; + + if (!isAssetFiltered) + { + ElcAssets.Add(elcAsset); + } + } + + void DoneClicked(object sender = null, EventArgs e = null) + { + var selected = new List(); + + foreach (var asset in ElcAssets) + { + if (asset.Selected) + { + selected.Add(asset.Asset); + } + } + + var parent = Parent; + if (parent != null) + { + parent.SelectedAssets(selected); + } + } + + bool ShouldSelectAsset(ELCAsset asset) + { + int selectionCount = TotalSelectedAssets; + bool shouldSelect = true; + + var parent = Parent; + if (parent != null) + { + shouldSelect = parent.ShouldSelectAsset(asset.Asset, selectionCount); + } + + return shouldSelect; + } + + void AssetSelected(ELCAsset asset, bool selected) + { + TotalSelectedAssets += (selected) ? 1 : -1; + + if (SingleSelection) + { + foreach (var elcAsset in ElcAssets) + { + if (asset != elcAsset) + { + elcAsset.Selected = false; + } + } + } + if (ImmediateReturn) + { + var parent = Parent; + var obj = new List(1); + obj.Add(asset.Asset); + parent.SelectedAssets(obj); + } + } + + public override nint NumberOfSections(UITableView tableView) + { + return 1; + } + + public override nint RowsInSection(UITableView tableview, nint section) + { + if (Columns <= 0) + return 4; + int numRows = (int)Math.Ceiling((float)ElcAssets.Count / Columns); + return numRows; + } + + List AssetsForIndexPath(NSIndexPath path) + { + int index = path.Row * Columns; + int length = Math.Min(Columns, ElcAssets.Count - index); + return ElcAssets.GetRange(index, length); + } + + public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) + { + const string cellIdentifier = "Cell"; + + var cell = TableView.DequeueReusableCell(cellIdentifier) as ELCAssetCell; + if (cell == null) + { + cell = new ELCAssetCell(UITableViewCellStyle.Default, cellIdentifier); + } + cell.SetAssets(AssetsForIndexPath(indexPath), Columns); + return cell; + } + + public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath) + { + return 79; + } + + public int TotalSelectedAssets; + + public class ELCAsset + { + public readonly ALAsset Asset; + readonly WeakReference _Parent; + + bool _Selected; + + public ELCAsset(ELCAssetTablePicker parent, ALAsset asset) + { + _Parent = new WeakReference(parent); + Asset = asset; + } + + public void ToggleSelected() + { + Selected = !Selected; + } + + public bool Selected + { + get + { + return _Selected; + } + + set + { + var parent = _Parent.Target as ELCAssetTablePicker; + if (value && parent != null && !parent.ShouldSelectAsset(this)) + { + return; + } + + _Selected = value; + + if (parent != null) + { + parent.AssetSelected(this, value); + } + } + } + } + + class ELCAssetCell : UITableViewCell + { + List RowAssets; + int Columns; + readonly List ImageViewArray = new List(); + readonly List OverlayViewArray = new List(); + + public ELCAssetCell(UITableViewCellStyle style, string reuseIdentifier) : base(style, reuseIdentifier) + { + UITapGestureRecognizer tapRecognizer = new UITapGestureRecognizer(CellTapped); + AddGestureRecognizer(tapRecognizer); + + } + + public void SetAssets(List assets, int columns) + { + RowAssets = assets; + Columns = columns; + + foreach (var view in ImageViewArray) + { + view.RemoveFromSuperview(); + } + foreach (var view in OverlayViewArray) + { + view.RemoveFromSuperview(); + } + + //UIImage overlayImage = null; + for (int i = 0; i < RowAssets.Count; i++) + { + var asset = RowAssets[i]; + + try + { + + if (asset.Asset != null + && asset.Asset.Thumbnail != null) + { + if (i < ImageViewArray.Count) + { + var imageView = ImageViewArray[i]; + imageView.Image = new UIImage(asset.Asset.Thumbnail); + } + else + { + var imageView = new UIImageView(new UIImage(asset.Asset.Thumbnail)); + ImageViewArray.Add(imageView); + } + } + + } + catch (Exception e) + { + Console.WriteLine("{0} {1}", NSBundle.MainBundle.LocalizedString("Failed to set thumbnail", "Failed to set thumbnail"), e); + } + + if (i < OverlayViewArray.Count) + { + var overlayView = OverlayViewArray[i]; + overlayView.Hidden = !asset.Selected; + } + else + { + var overlayView = new UIImageView(OverlayImage); + OverlayViewArray.Add(overlayView); + overlayView.Hidden = !asset.Selected; + } + } + } + + void CellTapped(UITapGestureRecognizer tapRecognizer) + { + var point = tapRecognizer.LocationInView(this); + var totalWidth = Columns * 75 + (Columns - 1) * 4; + var startX = (Bounds.Size.Width - totalWidth) / 2; + + var frame = new CGRect(startX, 2, 75, 75); + for (int i = 0; i < RowAssets.Count; ++i) + { + if (frame.Contains(point)) + { + ELCAsset asset = RowAssets[i]; + asset.Selected = !asset.Selected; + var overlayView = OverlayViewArray[i]; + overlayView.Hidden = !asset.Selected; + break; + } + var x = frame.X + frame.Width + 4; + frame = new CGRect(x, frame.Y, frame.Width, frame.Height); + } + } + + public override void LayoutSubviews() + { + var totalWidth = Columns * 75 + (Columns - 1) * 4; + var startX = (Bounds.Size.Width - totalWidth) / 2; + + var frame = new CGRect(startX, 2, 75, 75); + + int i = 0; + foreach (var imageView in ImageViewArray) + { + imageView.Frame = frame; + AddSubview(imageView); + + var overlayView = OverlayViewArray[i++]; + overlayView.Frame = frame; + AddSubview(overlayView); + + var x = frame.X + frame.Width + 4; + frame = new CGRect(x, frame.Y, frame.Width, frame.Height); + } + } + } + + #endregion + + + } + } +} \ No newline at end of file diff --git a/iOS/ELCImagePicker/src/ELCImagePicker/Properties/AssemblyInfo.cs b/iOS/ELCImagePicker/src/ELCImagePicker/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7222e5b --- /dev/null +++ b/iOS/ELCImagePicker/src/ELCImagePicker/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("ELCImagePicker")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("davehumphreys")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly:AssemblyVersion("1.3")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/iOS/ELCImagePicker/Resources/Overlay.png b/iOS/ELCImagePicker/src/ELCImagePicker/Resources/overlay-image.png similarity index 100% rename from iOS/ELCImagePicker/Resources/Overlay.png rename to iOS/ELCImagePicker/src/ELCImagePicker/Resources/overlay-image.png diff --git a/iOS/ELCImagePicker/Resources/Overlay@2x.png b/iOS/ELCImagePicker/src/ELCImagePicker/Resources/overlay-image@2x.png similarity index 100% rename from iOS/ELCImagePicker/Resources/Overlay@2x.png rename to iOS/ELCImagePicker/src/ELCImagePicker/Resources/overlay-image@2x.png