Dependency Injection and platform specific graphics

Is it possible, or more importantly good practice, to use Dependency Injection to have iOS and Android do their own graphics manipulation?

I defined an interface (Xamarin Forms button) whose implementation (to draw a box, for example) gets triggered in iOS, but my class (DrawBoxView) called by my view controller (DrawBoxViewController) fails to get UIGraphics.GetCurrentContext to return anything but a null value -- in overriding the Draw method of UIView. This class implements both UIView and the interface used for dependency inejection. But again, rather than this specific issue - is dependency injection a worthy endeavorer for this type of application?

Best Answer

Answers

  • BruceHamilton.6835BruceHamilton.6835 USUniversity ✭✭

    Thanks Adam,

    Essentially, I aim to:

    • Use Xamarin forms to derive the logic and choices to define the properties for a graphic, like the width, and X and Y coordinates of a rectangle. A Xamarin forms BoxView control can be used to prototype these choices.

    • Have the platform specific code implement the interface for dependency injection and (for iOS) use MonoTouch.CoreGraphics APIs to draw the rectangle (whose dimensions were established in the cross-platform code). Once the cross platform code defines the dimensions of the graphic, the platform specific code completes the rendering of the graphic with its platform capabilities.

    This application started off as a means for my understanding, rather than a real-world application scenario.

    In the PCL, I define IDrawBox for the dependency injection service:

    public interface IDrawBox
    {
        void DrawBox(Rectangle rect);
    }
    

    In MainPage.cs in the PCL, I have a button (drawButton) whose event handler gets the values from a BoxView control (bxView) to use for the dependency service call:

    // code to determine desired dimensions of rectangle using a BoxView
    drawButton.Clicked += (object sender, EventArgs e) => {
        Rectangle xrect;
        xrect.Width = bxView.Width;
        xrect.X = bxView.X;
        xrect.Y = bxView.Y;
        DependencyService.Get<IDrawBox> ().DrawBox(xrect);  
    };
    

    Here's my AppDelagate.cs where Xamarin forms is initialized. I thought because I don't define a root view controller here could be the reason for my null value problem with UIGraphics.GetCurrentContext. I used the code in the Core Graphics topic as the basis for my rendering.

    [Register ("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        UIWindow window;
        public override bool FinishedLaunching (UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init ();
            window = new UIWindow(UIScreen.MainScreen.Bounds);
            LoadApplication (new App ());
            return base.FinishedLaunching (app, options);
        }
    }
    

    Here's the ViewDidLoad method of my BoxDrawViewController class that adds DrawBoxView:

        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            dbView = new DrawBoxView(){Frame = UIScreen.MainScreen.Bounds};
            View.AddSubview (dbView);
        }
    

    Lastly, here's my DrawBoxView class, implementing UIView and IDrawBox. Here's where I get the null exception for using UIGraphics.GetCurrentContext. I tired also putting the using GetCurrentContext using statement in the DrawBox method itself, but have the same null result. Here's probably where I should define my own image context instead, right?

    public class DrawBoxView : UIView, IDrawBox
    {
        // CGRect for platform specific drawing
        CGRect rectCG;
        nfloat rectX;
        nfloat rectY;
        nfloat rectWidth;
    
        public DrawBoxView ()
        {
            BackgroundColor = UIColor.White;
    
        } 
        public override void Draw (CGRect rect)
        {
            base.Draw (rect);
    
            using (CGContext g = UIGraphics.GetCurrentContext ()) {
    
                g.SetLineWidth (10); // fails, null value
    
            }
    
        }
    
    
        public void DrawBox(Xamarin.Forms.Rectangle rect)
        {
            rectCG = new CGRect ();
            rectCG.Width = (nfloat) rect.Width;
            rectCG.X = (nfloat) rect.X;
            rectCG.Y = (nfloat) rect.Y;
    
            // Draw the rectangle with platform specific features
            //  I shouldn't call Draw here, right?
            Draw (rectCG);
        }
    }
    

    Thanks!

Sign In or Register to comment.