I read the following article and tried it, but it won't work:
How to make a uiactionsheet dismiss when you tap outside eg above it?
I have a Menu-Class (Superclass from uiactionsheet) and register a TapRecognizer in it. When the UIActionSheet is visible and a tap on it (not outside) occurd, it executes the Taprecognizer. But on a tap outside, nothing happend.
public class MyMenu: UIActionSheet
{
/// <summary>
/// Constructor
/// </summary>
public MyMenu(UIView owner)
{
_owner = owner;
}
public override void Show()
{
ShowInView(_owner);
var rec = new UITapGestureRecognizer(CheckTapOutside);
rec.CancelsTouchesInView = false;
this.Superview.AddGestureRecognizer(rec);
// Add controls to it
}
public void Hide()
{
DismissWithClickedButtonIndex(0, true);
}
private void CheckTapOutside(UITapGestureRecognizer rec)
{
var p = rec.LocationInView(this);
if (p.Y < 0)
{
this.Hide();
}
}
}
The following code initializes the menu and shows it.
var menu = new MyMenu(View);
menu.Show();
Can anyone tell me what's going wrong? Thanks.
Related
i have web-view that i need to create for it context menu when click on link type this what i did :
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Webview);
wv = (WebView)FindViewById(Resource.Id.WV);
RegisterForContextMenu(wv);
wv.SetWebChromeClient(new WebChromeClient());
wv.SetWebViewClient(new WebViewClient());
wv.Settings.JavaScriptEnabled = true;
wv.Settings.DomStorageEnabled = true;
wv.Settings.SetSupportZoom(true);
wv.Settings.DisplayZoomControls = false;
wv.Settings.BuiltInZoomControls = true;
wv.Settings.CacheMode = CacheModes.Default;
wv.Settings.UseWideViewPort = true;
wv.Settings.LoadWithOverviewMode = true;
wv.SetInitialScale(1);
wv.LoadUrl("file:///android_asset/index.html");
}
public override void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
{
base.OnCreateContextMenu(menu, v, menuInfo);
WebView webView = (WebView)v;
result = webView.GetHitTestResult();
if (result.GetType().ToString().Equals("SRC_ANCHOR_TYPE") || result.GetType().ToString().Equals("ANCHOR_TYPE"))
{
var item = menu.Add("copylink");
item.SetOnMenuItemClickListener(this);
}
}
but "result.GetType()" its its not detect anchor type link the "result.GetType()" is not detect any link in webview when it get pressed longtoch..
If you want to add a item to the menu, you should override OnActionModeStarted method. then add the SetOnMenuItemClickListenerlike following code.
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Add("Add To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
base.OnActionModeStarted(mode);
}
internal class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
{
private MainActivity mainActivity;
public MyMenuItemOnMenuItemClickListener(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public bool OnMenuItemClick(IMenuItem item)
{
Toast.MakeText(mainActivity, "You click the Add To Notes", ToastLength.Short).Show();
return true;
}
}
Here is running GIF.
If you want to create a new menu, you can use menu.Clear();
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Clear();
menu.Add("Add To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
base.OnActionModeStarted(mode);
}
Here is running screenshot.
Update
If you want to get the Type of long click, you should make sure type of result.Type is Webkit.HitTestResult, you use result.GetType(), Type is System.Type. So you can get the correct type, you can refer to the following code.
WebView.HitTestResult result = webView.GetHitTestResult();
Android.Webkit.HitTestResult myresult = result.Type;
You can refer to the debug gif.
I have a small app, that does read QR-Codes for a login and alternatively offers the possibility to hand-type the code and login.
The app starts and heads directly to the login (View). When I try to scan a qr code that does not work - the delegate is never called/the event never raised.
I adapted the approach from Larry OBrien http://www.knowing.net/index.php/2013/10/09/natively-recognize-barcodesqr-codes-in-ios-7-with-xamarin-ios/
And created my own ScannerView class for that use:
public sealed partial class ScannerView : UIView
{
private readonly AVCaptureVideoPreviewLayer _layer;
public AVCaptureSession Session { get; }
private readonly AVCaptureMetadataOutput _metadataOutput;
public event EventHandler<AVMetadataMachineReadableCodeObject> MetadataFound = delegate { };
public ScannerView (IntPtr handle) : base (handle)
{
Session = new AVCaptureSession();
var camera = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
var input = AVCaptureDeviceInput.FromDevice(camera);
Session.AddInput(input);
//Add the metadata output channel
_metadataOutput = new AVCaptureMetadataOutput {RectOfInterest = Bounds};
var metadataDelegate = new MetadataOutputDelegate();
var dispatchQueue = new DispatchQueue("scannerQueue");
_metadataOutput.SetDelegate(metadataDelegate, dispatchQueue);
Session.AddOutput(_metadataOutput);
_layer = new AVCaptureVideoPreviewLayer(Session)
{
MasksToBounds = true,
VideoGravity = AVLayerVideoGravity.ResizeAspectFill,
Frame = Bounds
};
Layer.AddSublayer(_layer);
// Hand event over to subscriber
metadataDelegate.MetadataFound += (s, e) => MetadataFound(s, e);
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
_layer.Frame = Bounds;
_metadataOutput.RectOfInterest = Bounds;
}
public void SetMetadataType(AVMetadataObjectType type)
{
//Confusing! *After* adding to session, tell output what to recognize...
_metadataOutput.MetadataObjectTypes = type;
}
}
And in my LoginView I do the following:
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
// Manipulate navigation stack
NavigationController.SetViewControllers(
NavigationController.ViewControllers.Where(
viewController => viewController is LoginView).ToArray(), false);
ScannerView.MetadataFound += (s, e) =>
{
Console.WriteLine($"Found: [{e.Type.ToString()}] {e.StringValue}");
LoginViewModel.BarCode = e.StringValue;
if (LoginViewModel.DoneCommand.CanExecute())
{
ScannerView.Session.StopRunning();
LoginViewModel.DoneCommand.Execute();
}
};
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
ScannerView.Session.StartRunning();
ScannerView.SetMetadataType(AVMetadataObjectType.QRCode | AVMetadataObjectType.EAN13Code);
}
Funny thing is, that this works once I logged in with the manual input and logged out again, so I'm on the same screen again (possibly not the same but a new instance of it as the GC may destroy the view as it is removed from the navigation stack?)
I have put the scannerview as a subview on the LoginView in the storyboard. For navigation I use MVVMCross. (just for info)
So: What am I doing wrong? What do I need to do to make it work on the first load? (I got it to do that once - with the same code... maybe it is a timing issue?)
Obviously this is a timing issue.
I solved it by adding a "Tap to scan" paradigm.
When tapping I execute the following code:
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
Console.WriteLine($"Current types to scan: {this.MetadataOutput.MetadataObjectTypes}");
this.SetMetadataType(this.MetadataObjectType);
Console.WriteLine($"New types to scan: {this.MetadataOutput.MetadataObjectTypes}");
}
public void SetMetadataType(AVMetadataObjectType type)
{
//Confusing! *After* adding to session, tell output what to recognize...
this.Session.BeginConfiguration();
this.MetadataOutput.MetadataObjectTypes = type;
this.Session.CommitConfiguration();
}
Where MetadataObjectType is set to the codes we're looking for before.
And that solves the problem - the scanning now works every time.
I think the magic part is the Begin- and CommitConfiguration call, as this also works, if I do not use the touch to scan paradigm.
I have created a tutorial window in storyboard with two views, one to hold show the tutorial the other used as a template for each page of content.
Some elements are coded programmatically on the ViewDidLoad event.
The PageViewController is working 100% as required, it shows the three pages of content and allows swiping backwards and forwards without issue.
I've added a UIPageControl programmatically to the main ViewController but for the life of me cannot update its CurrentPage value correctly. Accessing the datasources PageIndex value gives me odd results when swiping back and forth.
Is there a reliable way to know exactly which page is been displayed ?
Or to know which direction the page transition moved, this way I can manually update? Not entirely sure how UIPageViewControllerNavigationDirection is accessed from the pagecontrollers 'DidFinishAnimating' event.
My main view controller code is as follows:
using Foundation;
using System;
using UIKit;
namespace Performance
{
partial class VCOnboardHome : UIViewController
{
const int pageCount = 3;
public UIPageViewController pvcOnboarding{ get; set; }
private OnboardingDataSource onboardDataSource;
UIStoryboard board;
public UIPageControl pgControlIndicator;
public VCOnboardHome (IntPtr handle) : base (handle)
{
}
/// <summary>
/// ViewDidLoad event method
/// </summary>
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
board = UIStoryboard.FromName ("Main", null);
// Programmatically create a PageView controller
pvcOnboarding = new UIPageViewController (UIPageViewControllerTransitionStyle.Scroll,
UIPageViewControllerNavigationOrientation.Horizontal,
UIPageViewControllerSpineLocation.None, 20f);
// PageView Controller datasource
var views = CreateViews ();
onboardDataSource = new OnboardingDataSource (views);
pvcOnboarding.DataSource = onboardDataSource;
pvcOnboarding.SetViewControllers (new UIViewController[] { views [0] },
UIPageViewControllerNavigationDirection.Forward,
false, null);
// Set PageView size
pvcOnboarding.View.Frame = View.Bounds;
// Add the page view control to this view controller
Add (pvcOnboarding.View);
// Create Page Control
var frame = UIScreen.MainScreen.Bounds;
pgControlIndicator = new UIPageControl ();
pgControlIndicator.Frame = new CoreGraphics.CGRect (20f, frame.Height - 60f, frame.Width - 40f, 40f);
pgControlIndicator.Pages = pageCount;
pgControlIndicator.UserInteractionEnabled = false;
Add (pgControlIndicator);
// Update the Page Control to indicate the current page we are showing.
// Only do this if the full page transition happened and not a partial page turn
pvcOnboarding.DidFinishAnimating += (sender, e) => {
foreach(UIViewController u in e.PreviousViewControllers){
// TODO - Not needed, remove once page control working
// u = the previous viewcontroller
}
if(e.Finished && e.Completed){
// Page transition completed
// Update Page Control here
}else{
// Incomplete page transition
}
};
}
// Content for each page
VCOnboardContentNew[] CreateViews ()
{
var pageData = new [] {
new ContentOnBoardData {
headerLblText = #"Page 1",
bodyContentText = #"Page 1 body text blah blah blah blah",
buttonText = #"Ok, next no. 1",
pageImage = UIImage.FromBundle("ios_images_v2/onboarding/icon-qr-code.png"),
currentPage = 1,
totalPages = 3
},
new ContentOnBoardData {
headerLblText = #"Page 2",
bodyContentText = #"Page 2 body text blah blah blah blah",
buttonText = #"Ok, next no. 2",
pageImage = UIImage.FromBundle("ios_images_v2/onboarding/icon-id-check.png"),
currentPage = 2,
totalPages = 3
},
new ContentOnBoardData {
headerLblText = #"Page 3",
bodyContentText = #"Page 3 body text blah blah blah blah",
buttonText = #"Ok, got it",
pageImage = null,
currentPage = 3,
totalPages = 3
}
};
var views = new VCOnboardContentNew[pageData.Length];
for (int i = 0; i < pageCount; i++) {
int pageIndex = i;
views [i] = (VCOnboardContentNew)board.InstantiateViewController ("sbid_onboardcontent");
views [i].PageIndex = pageIndex;
views [i].HeaderText = pageData [i].headerLblText;
views [i].ContentText = pageData [i].bodyContentText;
views [i].PageImage = pageData [i].pageImage;
views [i].CurrentPage = pageData [i].currentPage;
views [i].TotalPages = pageCount;
views [i].ButtonText = pageData [i].buttonText;
views [i].ButtonClicked += (s, e) => {
DismissViewController (true, null);
};
}
return views;
}
}
/// <summary>
/// Onboarding data source.
/// </summary>
class OnboardingDataSource : UIPageViewControllerDataSource
{
readonly VCOnboardContentNew[] _views;
public OnboardingDataSource (VCOnboardContentNew[] views)
{
_views = views;
}
/// <summary>
/// Gets the previous view controller.
/// </summary>
/// <returns>The previous view controller.</returns>
/// <param name="pageViewController">Page view controller.</param>
/// <param name="referenceViewController">Reference view controller.</param>
public override UIViewController GetPreviousViewController (UIPageViewController pageViewController, UIViewController referenceViewController)
{
int index = ((VCOnboardContentNew)referenceViewController).PageIndex;
bool controlCheck = (index <= 0);
UIViewController vcToReturn = controlCheck ? null : (_views [index - 1]);
return vcToReturn;
}
/// <summary>
/// Gets the next view controller.
/// </summary>
/// <returns>The next view controller.</returns>
/// <param name="pageViewController">Page view controller.</param>
/// <param name="referenceViewController">Reference view controller.</param>
public override UIViewController GetNextViewController (UIPageViewController pageViewController, UIViewController referenceViewController)
{
int index = ((VCOnboardContentNew)referenceViewController).PageIndex;
bool controlCheck = index + 1 >= _views.Length;
UIViewController vcToReturn = controlCheck ? null : _views [index + 1];
return vcToReturn;
}
}
/// <summary>
/// Content onboard data.
/// </summary>
struct ContentOnBoardData
{
public string headerLblText;
public string bodyContentText;
public string buttonText;
public UIImage pageImage;
public int currentPage;
public int totalPages;
}
}
My Page content code view controller is as follows:
using System;
using UIKit;
namespace Performance
{
/// <summary>
/// Class: VCOnboardContentNew
/// </summary>
partial class VCOnboardContentNew : UIViewController
{
public EventHandler ButtonClicked;
public int PageIndex { get; set; }
public string HeaderText{ get; set; }
public UIImage PageImage{ get; set; }
public int CurrentPage{ get; set; }
public int TotalPages{ get; set; }
public string ContentText{ get; set; }
public string ButtonText{ get; set; }
public VCOnboardContentNew (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Set text for the main title
lblTest.Font = UIFont.FromName("FreightDispLight", 26f);
lblTest.Text = HeaderText;
// Set text for body content
lblContentBodyText.Font = UIFont.FromName("FreightDispLight", 14f);
lblContentBodyText.Text = ContentText;
pgCtrlWhichPageWeOn.Hidden = true;
if(PageImage != null){
pageContentImage.Hidden = false;
pageContentImage.Image = PageImage;
}else{
pageContentImage.Hidden = true;
}
btnCallToAction.SetTitle (ButtonText, UIControlState.Normal);
btnCallToAction.TouchUpInside += (object sender, EventArgs e) => {
if (ButtonClicked != null) {
ButtonClicked.Invoke (this, null);
}
};
}
}
}
When the transition style is set to scroll, the page view controller seems to:
As soon as one transition finishes, it immediately calls for the next (or previous) View Controller (with GetNextViewController), even though the user might not have started the next swipe; and
It keeps the view controller that was transitioned from, and assumes that it is the previous VC, so it doesn't call for the previous VC (with GetPreviousViewController) if the user swipes back.
This makes it pretty difficult to keep track of which VC is actually currently showing pretty difficult. If found (see this answer) that I had to use both the WillTransition event and the DidFinishAnimating event. I'm not familiar with Xamarin and C#, so forgive me if this syntax is way off, but I think something like this:
pvcOnboarding.WillTransition += (sender, e) => {
nextVCIndex = ((VCOnboardContentNew)e.PendingViewControllers[0]).PageIndex
}
pvcOnboarding.DidFinishAnimating += (sender, e) => {
if(e.Finished && e.Completed){
// Page transition completed
currentVCIndex = nextVCIndex
// Update Page Control here
}else{
// Incomplete page transition
}
};
You'll need to add currentVCIndex and nextVCIndex as class level variables.
Old question but was recently struggling with the same issue. Finally found a nice solution.
Provide your UIPageViewController with:
public static int pageIndex = 0; // or whatever start index
Then for each of your UIViewControllers to be loaded override ViewDidAppear:
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
MyCystomPageViewController.pageIndex = 1; // the index of this viewcontroller
}
This works since ViewDidAppear gets called when the view is added as subview. And thus will be called everytime you swipe.
I am developing an app for iOS using MvvmCross. On one of my Views I have some basic report data that is displayed in a tableview.
When the table row is touched a new view containing a detail report is displayed by making the call to ShowViewModel passing some parameters in a Dictionary. This works fine.
When the user swipes left or right the app needs to show the detail report for the next or previous item in the original list. I am doing this by updating some parameters and calling ShowViewModel again. The logic behind this is all working fine.
My problem; ShowViewModel animates the new view coming in from the right. This is perfect when the user has swiped left. However when swiping right it seems counter intuitive. How can I make ShowViewModel animate or transition in from the left side?
if you look to the MvvmCross source code here you see how the default behavior is showing the ViewControllers
You need to change that by doing something like the following:
How to change the Push and Pop animations in a navigation based app
for that, one idea is to have a custom view presenter and catch navigation to that particular view-model (override Show(IMvxTouchView view) )
or, maybe derive from UINavigationController, set it to MvvmCross to use it (look to the MvxSetup), and on some events change transition to that particular view
similar to this question
How to specify view transitions on iPhone
This is the solution I was able to come up with following the helpful pointers in the answer from Andrei N. In the end I opted for a TransitionFlipFromRight and TransitionFlipFromLeft when scrolling between detail reports. Hopefully it is useful to somebody else.
I already had a presenter class that was inherited from MvxModalSupportTouchViewPresenter
public class BedfordViewPresenter : MvxModalSupportTouchViewPresenter
Within this class I added a property of MvxPresentationHint.
private MvxPresentationHint _presentationHint;
In the override of method ChangePresentation the above property is used to store the passed in parameter
public override void ChangePresentation (MvxPresentationHint hint)
{
_presentationHint = hint;
base.ChangePresentation (hint);
}
Two new MvxPresentationHint class were declared (see later)
In the presenter class the Show method was overridden
public override void Show(IMvxTouchView view)
{
if (_presentationHint is FlipFromRightPresentationHint) {
var viewController = view as UIViewController;
MasterNavigationController.PushControllerWithTransition (viewController, UIViewAnimationOptions.TransitionFlipFromRight);
}
else
if (_presentationHint is FlipFromLeftPresentationHint) {
var viewController = view as UIViewController;
MasterNavigationController.PushControllerWithTransition (viewController, UIViewAnimationOptions.TransitionFlipFromLeft);
}
else {
base.Show (view);
}
_presentationHint = null;
}
A new class that provides extensions to a UINavigationController was created with the method PushControllerWithTransition
public static class UINavigationControllerExtensions
{
public static void PushControllerWithTransition(this UINavigationController
target, UIViewController controllerToPush,
UIViewAnimationOptions transition)
{
UIView.Transition(target.View, 0.75d, transition, delegate() {
target.PushViewController(controllerToPush, false);
}, null);
}
}
All that needs to be defined now are the two new MvxPresentationHint class derivations. These belong in your Core class library project rather than the iOS application project.
public class FlipFromLeftPresentationHint : MvxPresentationHint
{
public FlipFromLeftPresentationHint ()
{
}
}
and
public class FlipFromRightPresentationHint: MvxPresentationHint
{
public FlipFromRightPresentationHint ()
{
}
}
I hope this is a help to someone else trying to do something similar
Share my solution for android:
On view:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = base.OnCreateView(inflater, container, savedInstanceState);
var layout = view.FindViewById<LinearLayout>(Resource.Id.swippeable);
var swipeListener = new SwipeListener(this.Activity);
swipeListener.OnSwipeLeft += (sender, e) => this.ViewModel.LeftCommand?.Execute(); //Here use command into view model
swipeListener.OnSwipeRight += (sender, e) => this.ViewModel.RightCommand?.Execute();
layout.SetOnTouchListener(swipeListener);
return view;
}
Gesture listener:
public class SwipeListener : SimpleOnGestureListener, View.IOnTouchListener
{
private const int SWIPE_THRESHOLD = 100;
private const int SWIPE_VELOCITY_THRESHOLD = 100;
private readonly GestureDetector gestureDetector;
public SwipeListener(Context ctx)
{
this.gestureDetector = new GestureDetector(ctx, this);
}
public Boolean OnTouch(View v, MotionEvent e)
{
return this.gestureDetector.OnTouchEvent(e);
}
public event EventHandler OnSwipeRight;
public event EventHandler OnSwipeLeft;
public event EventHandler OnSwipeTop;
public event EventHandler OnSwipeBottom;
public override Boolean OnDown(MotionEvent e)
{
return true;
}
public override Boolean OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
Boolean result = false;
float diffY = e2.GetY() - e1.GetY();
float diffX = e2.GetX() - e1.GetX();
if (Math.Abs(diffX) > Math.Abs(diffY))
{
if (Math.Abs(diffX) > SWIPE_THRESHOLD && Math.Abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffX > 0)
{
SwipeRight();
}
else
{
SwipeLeft();
}
result = true;
}
}
else if (Math.Abs(diffY) > SWIPE_THRESHOLD && Math.Abs(velocityY) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffY > 0)
{
SwipeBottom();
}
else
{
SwipeTop();
}
result = true;
}
return result;
}
public void SwipeRight()
{
this.OnSwipeRight?.Invoke(this, EventArgs.Empty);
}
public void SwipeLeft()
{
this.OnSwipeLeft?.Invoke(this, EventArgs.Empty);
}
public void SwipeTop()
{
this.OnSwipeTop?.Invoke(this, EventArgs.Empty);
}
public void SwipeBottom()
{
this.OnSwipeBottom?.Invoke(this, EventArgs.Empty);
}
}
The card.io component (http://components.xamarin.com/view/cardioios) has a fallback screen that has a Cancel and a Done button on them.
Neither of which actually do anything. I assume it is up to me to subscribe to and event, however, there is no event to subscribe to.
Here is the code:
var paymentDelegate = new PaymentViewControllerDelegate();
var paymentViewController = new Card.IO.PaymentViewController(paymentDelegate);
paymentDelegate.OnScanCompleted += (viewController, cardInfo) =>
{
viewController.DismissViewController(true, null);
if (cardInfo == null)
{
}
else
{
new UIAlertView("Card Scanned!", cardInfo.CardNumber, null, "OK", null).Show();
}
};
paymentViewController.AppToken = "app-token";
// Display the card.io interface
base.PresentViewController(paymentViewController, true, () => { });
There is a method on the PaymentViewControllerDelegate, but I can't figure out what to do with it:
public override void UserDidCancel(PaymentViewController paymentViewController);
public override void UserDidProvideCreditCardInfo(CreditCardInfo cardInfo, PaymentViewController paymentViewController);
I guess the problem is that the Component doesn't expose any events for the Fallback View.
You need to subclass PaymentViewControllerDelegate:
public class MyPaymentDelegate : PaymentViewControllerDelegate
{
public MyPaymentDelegate ()
{
}
public override void UserDidCancel (PaymentViewController paymentViewController)
{
// Implement on-cancel logic here...
base.UserDidCancel (paymentViewController);
}
public override void UserDidProvideCreditCardInfo (CreditCardInfo cardInfo, PaymentViewController paymentViewController)
{
// Implement logic for credit card info provided here...
base.UserDidProvideCreditCardInfo (cardInfo, paymentViewController);
}
}
And then provide an instance of this class into the constructor for Card.IO.PaymentViewController:
var paymentDelegate = new MyPaymentDelegate();
var paymentViewController = new Card.IO.PaymentViewController(paymentDelegate);
So, I figured this out by looking at the working sample application and comparing it to what I had done.
All I had to do was widen the scope of the paymentDelegate and paymentViewController variables.
If you look at the sample, you really just need to subscribe to the OnScanCompleted event which is called in both cases of UserDidCancel (where cardInfo will be null), and UserDidProvideCreditCardInfo (where it will not be null).
In fact, this is the code for the binding, so you can see the Event was made as a 'helper' to make it so you didn't have to make your own delegate implementation:
namespace Card.IO
{
public partial class PaymentViewControllerDelegate : BasePaymentViewControllerDelegate
{
public delegate void ScanCompleted(PaymentViewController viewController, CreditCardInfo cardInfo);
public event ScanCompleted OnScanCompleted;
public override void UserDidCancel (PaymentViewController paymentViewController)
{
var evt = OnScanCompleted;
if (evt != null)
evt(paymentViewController, null);
}
public override void UserDidProvideCreditCardInfo (CreditCardInfo cardInfo, PaymentViewController paymentViewController)
{
var evt = OnScanCompleted;
if (evt != null)
evt(paymentViewController, cardInfo);
}
}
}
If you still really want to implement the delegate yourself, subclass BasePaymentViewController instead, however I don't think you really need to make your own subclass of it...
Hopefully that helps!