Reputation: 351
I'm new to .Net Maui. Trying to draw my own shapes using GraphicsView
and IDrawable
. I would like to have the shapes clickable.
Is there a way how to achieve that? Maybe there is another interface something like IClickable
I'm not aware of. Or I should use different approach thanGraphicsView
.
Thanks :-)
Upvotes: 5
Views: 3326
Reputation: 11
Here is how is found a solution to the question.
My base class is implementing the GraphicsView, IDrawable and using the Draw method that you seam already be familliar with when using Maui.
First you need a class that contains your actions and list of the class
private readonly List<ClickableRectangle> _rectangles = new();
public class ClickableRectangle
{
public RectF Bounds { get; set; }
public Action OnClick { get; set; }
public ClickableRectangle(RectF bounds, Action onClick)
{
Bounds = bounds;
OnClick = onClick;
}
public bool Contains(Point point)
{
return Bounds.Contains((float)point.X, (float)point.Y);
}
}
Then we can add a TapGestureRecognizer to our GraphicsView
public View2D()
{
Drawable = this;
Initialize();
var tapGesture = new TapGestureRecognizer();
tapGesture.Tapped += OnTapped;
GestureRecognizers.Add(tapGesture);
AddRectangle(new RectF(10, 10, 100, 100), () => Debug.WriteLine("Rectangle clicked!"));
}
public void AddRectangle(RectF bounds, Action onClick)
{
_rectangles.Add(new ClickableRectangle(bounds, onClick));
}
private void OnTapped(object sender, TappedEventArgs e)
{
var touchPoint = new Point(e.GetPosition(this).Value.X, e.GetPosition(this).Value.Y);
foreach (var rectangle in _rectangles)
{
if (rectangle.Contains(touchPoint))
{
rectangle.OnClick?.Invoke();
break;
}
}
}
public void Draw(ICanvas canvas, RectF dirtyRect)
{
foreach (var rectangle in _rectangles)
{
canvas.FillColor = Colors.Red;
canvas.FillRectangle(rectangle.Bounds);
}
}
Upvotes: 0
Reputation: 69
Via XAML you would add a TapGestureRecognizer like this:
<GraphicsView
x:Name="xyz"
Drawable="{StaticResource drawable}"
.../>
<GraphicsView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnGraphicsViewTapped"/>
</GraphicsView.GestureRecognizers>
</GraphicsView>
The EventHandler looks like this:
private void OnTapGestureRecognizerTapped(object sender, TappedEventArgs args)
{
}
Alternatively, the PointerGestureRecognizer is also available. ( Swipe, Pinch, Pan, Pointer Drag and Drop GestureRecognizer are also available and used similarly. )
Upvotes: 0
Reputation: 167
You have to use StartInteraction
/EndInteraction
. These are two event handlers of GraphicsView
. StartInteraction
gets the ButtonDown
event and EndInteraction
gets the ButtonUp
event.
view.StartInteraction += OnStartInteraction;
view.EndInteraction += OnEndInteraction;
void OnStartInteraction(object Sender, TouchEventArgs evt) {
PointF p = evt.Touches.FirstOrDefault();
Trace.WriteLine($"Touch/click at {p}");
}
void OnEndInteraction(object Sender, TouchEventArgs evt) {
PointF p = evt.Touches.LastOrDefault();
Trace.WriteLine($"Released at {p}");
}
Upvotes: 1
Reputation: 11
GraphicsView has a 'StartInteraction' event that can be used to get click/touch information.
See more here: IGraphicsView.StartInteraction(PointF[])
Upvotes: 1
Reputation: 497
I was able to get this to work using the TapGestureRecognizer
and a class that implements ICommand
.
In this example I have the GraphicsView
as a member called _view
in the same class that implements both IDrawable
and ICommand
, but your design could be different and it should still work.
public class Block : IDrawable, ICommand
{
protected GraphicsView _view = new GraphicsView();
public Block()
{
_view.Drawable = this;
_view.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = this
});
}
void ICommand.Execute(object cmdObject)
{
// Handle the Clicked event here
}
bool ICommand.CanExecute(object cmdObject)
{
return true;
}
event EventHandler ICommand.CanExecuteChanged
{
add { }
remove { }
}
public void Draw(ICanvas canvas, RectF dirtyRect)
{
// Draw on canvas here
}
}
Upvotes: 2