0

In the app I'm trying to develop a key part is getting the position of where the user has touched. First I thought of using a tap gesture recognizer but after a quick google search I learned that was useless (See here for an example).

Then I believe I discovered SkiaSharp and after learning how to use it, at least somewhat, I'm still not sure how I get the proper coordinates of a touch. Here are sections of the code in my project that are relevant to the problem.

  1. Canvas Touch Function

     private void canvasView_Touch(object sender, SKTouchEventArgs e)
     {
         // Only carry on with this function if the image is already on screen.
         if(m_isImageDisplayed)
         {
             // Use switch to get what type of action occurred.
             switch (e.ActionType)
             {
                 case SKTouchAction.Pressed:
                     TouchImage(e.Location);
    
                     // Update simply tries to draw a small square using double for loops.
                     m_editedBm = Update(sender);
    
                     // Refresh screen.
                     (sender as SKCanvasView).InvalidateSurface();
                     break;
                 default:
                     break;
             }
         }
     }
    
  2. Touch Image

     private void TouchImage(SKPoint point)
     {
         // Is the point in range of the canvas?
         if(point.X >= m_x && point.X <= (m_editedCanvasSize.Width + m_x) &&
             point.Y >= m_y && point.Y <= (m_editedCanvasSize.Height + m_y))
         {
             // Save the point for later and set the boolean to true so the algorithm can begin.
             m_clickPoint = point;
    
             m_updateAlgorithm = true;
         }
     }
    

Here I'm just seeing or TRYING to see if the point clicked was in range of the image and I made a different SkSize variable to help. Ignore the boolean, not that important.

  1. Update function (function that attempts to draw ON the point pressed so it's the most important)

     public SKBitmap Update(object sender) 
     {
         // Create the default test color to replace current pixel colors in the bitmap.
         SKColor color = new SKColor(255, 255, 255);
    
         // Create a new surface with the current bitmap.
         using (var surface = new SKCanvas(m_editedBm))
         {
             /* According to this:  https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/paths/finger-paint , 
                the points I have to start are in Xamarin forms coordinates, but I need to translate them to SkiaSharp coordinates which are in
               pixels. */
             Point pt = new Point((double)m_touchPoint.X, (double)m_touchPoint.Y);
             SKPoint newPoint = ConvertToPixel(pt);
    
             // Loop over the touch point start, then go to a certain value (like x + 100) just to get a "block" that's been altered for pixels.
             for (int x = (int)newPoint.X; x < (int)newPoint.X + 200.0f; ++x)
             {
                 for (int y = (int)newPoint.Y; y < (int)newPoint.Y + 200.0f; ++y)
                 {
                     // According to the x and y, change the color.
                     m_editedBm.SetPixel(x, y, color);
                 }
             }
    
             return m_editedBm;
         }
     }
    

Here I'm THINKING that it'll start, you know, at the coordinate I pressed (and these coordinates have been confirmed to be within the range of the image thanks to the function "TouchImage". And when it does get the correct coordinates (or at least it SHOULD of done that) the square will be drawn one "line" at a time. I have a game programming background so this kind of sounds simple but I can't believe I didn't get this right the first time.

Also I have another function, it MIGHT prove worthwhile because the original image is rotated and then put on screen. Why? Well by default the image, after taking the picture, and then displayed, is rotated to the left. I had no idea why but I corrected it with the following function:

    // Just rotate the image because for some reason it's titled 90 degrees to the left.
    public static SKBitmap Rotate()
    {
        using (var bitmap = m_bm)
        {
            // The new ones width IS the old ones height. 
            var rotated = new SKBitmap(bitmap.Height, bitmap.Width);

            using (var surface = new SKCanvas(rotated))
            {
                surface.Translate(rotated.Width, 0.0f);
                surface.RotateDegrees(90);
                surface.DrawBitmap(bitmap, 0, 0);
            }

            return rotated;
        }
    }

I'll keep reading and looking up stuff on what I'm doing wrong, but if any help is given I'm grateful.

Omar Moodie
  • 263
  • 3
  • 13
  • What is your actual question, or what specific problem are you having with this code? – Jason Feb 24 '21 at 01:48
  • I'm wondering why when I touch on screen that the "block" or "square" isn't at the point where I touched. – Omar Moodie Feb 24 '21 at 04:08
  • Hi, how about having a try with using view renderer to get touch point from native solution?[iOS](https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/touch/),[Android](https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/touch/) – Junior Jiang Feb 25 '21 at 07:28

0 Answers0