Can you use OnPaint and Invalidate() in C# Xamarin Android

joe puhich 96 Reputation points
2020-12-13T20:55:16.207+00:00

I am trying to OnPaint() in c# Xamarin Android. Is this possible in VS 2019 Community?? Or do i need to upgrade to professional

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,334 questions
0 comments No comments
{count} votes

12 answers

Sort by: Most helpful
  1. JessieZhang-MSFT 7,706 Reputation points Microsoft Vendor
    2020-12-14T07:26:10.587+00:00

    Hello,

    Welcome to our Microsoft Q&A platform!

    For this ,we can check document Compare Visual Studio 2019 Editions.

    This table lists the differences between them. But it doesn't list the differences you said about theOnPaint() in c# Xamarin Android.

    So it doesn't matter if you are in VS 2019 Community or VS 2019 Professional.

    Best Regards,

    Jessie Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Jon Goldberger - MSFT 16 Reputation points Microsoft Employee
    2020-12-22T01:17:57.487+00:00

    Whether you can use OnPaint is a matter of the target platform, not the edition of Visual Studio.

    Are you asking about the Windows.Forms.Control.OnPaint()?
    If so, then no, that is not available on Android as that is a Windows method.
    Android has an OnDraw() method that you can override for any Android View to draw that View.


  3. joe puhich 96 Reputation points
    2020-12-22T16:32:35.567+00:00
        static void OnDraw(PaintEventArgs e)
    
        {
            //base.OnDraw(e);
            OnDraw(e);
            Graphics g = e.Graphics;
    
            g.Clear(System.Drawing.Color.White);
            Pen p = new Pen(System.Drawing.Color.Black, 1);
    
            g.DrawRectangle(p, 0, 0, 250, 150);
    

    The OnDraw code compiles.
    I tried to use Invalidate(), Update and Restore() to call OnDraw and none of them worked.

            Invalidate();
            Update();
            Refresh();
    
            zl1800.Tester.OnDraw();
    

    how do i get OnDraw to work????


  4. joe puhich 96 Reputation points
    2020-12-22T21:30:05.763+00:00

    50517-screenshot-693.png50572-screenshot-692.png

    I am new to C# xamarin android ?
    I am use to c++ win32.
    I used Invalidate() to run Paint() in win32;

    I do not think I am using OnDraw right.
    Because Invalidate() still does not call OnDraw.
    It is highlight in red.

    Plus I get an error on base(context)

    I am using your code in my .cs file.
    Should I be using your code in MainActivity.cs

    0 comments No comments

  5. Jon Goldberger - MSFT 16 Reputation points Microsoft Employee
    2020-12-22T22:37:17.853+00:00

    There are 2 types with name Context. Somewhere in that file you have a using statement that would be

    using System.Runtime.Remoting.Contexts  
    

    Because of this, the Context in the

     public DrawnView(Context context): base(context)  
    

    constructor is resolving to fully qualified System.Runtime.Remoting.Contexts.Context type, however the Android View constructor needs an Android.Content.Context, so in order to make that distinction, you will have to specify the fully qualified type name, e.g.:

    public class DrawnView : View  
    {  
        public DrawnView(Android.Content.Context context): base(context)  
        {  
        }  
    
        protected override void OnDraw(Canvas canvas)  
        {  
            base.OnDraw(canvas);  
            // drawing code here  
        }  
    }  
    

    And when you call Invalidate(), you have to call it either from inside the DrawnView class, or on the instance of the DrawnView class that you want OnDraw to be called on, e.g.:

    DrawnView drawnViewInstance = new DrawnView(context);  
    drawnViewInstance.Invalidate();  
    

    In the above, context is an Android.Content.Context, which can be the instance of your MainActivity (which is a subclass of Android.Content.Context). If the code above is in an Activity class, you can just pass in this for the context.

    For a complete example, try this:

    First start with a new template Xamarin.Android Single View app project.

    Then add a new C# class file and create the DrawnView class with the OnDraw override:

    using Android.Graphics;  
    using Android.Views;  
    
    namespace YourNamespace  
    {  
        public class DrawnView : View  
        {  
            public DrawnView(Android.Content.Context context) : base(context)  
            {  
            }  
            bool turnBlue = false;  
            protected override void OnDraw(Canvas canvas)  
            {  
                base.OnDraw(canvas);  
                if (turnBlue)  
                {  
                    canvas.DrawColor(Color.Blue);  
                }  
                else  
                {  
                    canvas.DrawColor(Color.Red);  
                }  
                turnBlue = !turnBlue;  
            }  
        }  
    }  
    

    The above will toggle itself to draw the background of the view as alternately blue or red every time OnDraw runs (i.e. when Invalidate() is called)

    Then open the content_main.xml file in the Resources/layout folder and add an id to the RelativeLayout (leaving the other lines in place (...), i.e. just add the android:id):

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        ...  
        android:id="@+id/relativeLayout1">  
    

    Then in MainActivity, create and add the DrawnView and change the FabOnClick method so that it invalidates the DrawnView (full code for MainActivity)

    using System;  
    using Android.App;  
    using Android.Graphics;  
    using Android.OS;  
    using Android.Runtime;  
    using Android.Support.Design.Widget;  
    using Android.Support.V7.App;  
    using Android.Views;  
    using Android.Widget;  
    
    namespace YourNamespace  
    {  
        [Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]  
        public class MainActivity : AppCompatActivity  
        {  
            DrawnView _drawnView;  
    
            protected override void OnCreate(Bundle savedInstanceState)  
            {  
                base.OnCreate(savedInstanceState);  
                Xamarin.Essentials.Platform.Init(this, savedInstanceState);  
                SetContentView(Resource.Layout.activity_main);  
    
                Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);  
                SetSupportActionBar(toolbar);  
    
                FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);  
                fab.Click += FabOnClick;  
    
                // This is added code to get a reference to the layout and add the new DrawnView instance to it  
                RelativeLayout layout = FindViewById<RelativeLayout>(Resource.Id.relativeLayout1);  
                _drawnView = new DrawnView(this);                 
                layout.AddView(_drawnView);  
            }  
    
            public override bool OnCreateOptionsMenu(IMenu menu)  
            {  
                MenuInflater.Inflate(Resource.Menu.menu_main, menu);  
                return true;  
            }  
    
            public override bool OnOptionsItemSelected(IMenuItem item)  
            {  
                int id = item.ItemId;  
                if (id == Resource.Id.action_settings)  
                {  
                    return true;  
                }  
    
                return base.OnOptionsItemSelected(item);  
            }  
    
            private void FabOnClick(object sender, EventArgs eventArgs)  
            {  
                 // Invalidate the DrawnView so that it redraws with the new color  
                _drawnView.Invalidate();  
            }  
    
            public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)  
            {  
                Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);  
    
                base.OnRequestPermissionsResult(requestCode, permissions, grantResults);  
            }  
    

    }
    }

    Make sure that YourNamespace in the above code examples is changed to the actual namespace that your app is using.

    Hope this helps. I would suggest you go through the Xamarin Android Getting Started docs to learn some fundamentals though:
    https://learn.microsoft.com/en-us/xamarin/android/get-started/


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.