How to detect the click on a drawn element in a GraphicsView - xamarin

I have created an IDrawable that draws different arcs of a circle in a GraphicsView in order to create a pie chart.
No problem so far, except that now I would like to detect the click or hover of one of these circle portions. But I don't see anything that would allow me to do that easily.
Even inheriting my IDrawable from View to attach a tapgesture to it doesn't seem to work (and even then it wouldn't really answer my problem which is to be able to know which portion is clicked).
public class PieChartDrawable : View, IDrawable
{
private readonly PieChart _chart;
public PieChartDrawable(PieChart chart)
{
_chart = chart;
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += OnTapped;
GestureRecognizers.Add(tapGestureRecognizer);
}
private void OnTapped(object sender, EventArgs e)
{
// Does not trigger.
}
public void Draw(ICanvas canvas, RectF dirtyRect)
{
if (_chart.Entries == null)
return;
[...]
}
}
Am I doing it wrong, or is there a way to do it?
(I'm looking for a solution for MAUI, but I guess something that works under Xamarin Forms will do very well).
Thanks in advance.

It seams it can be a solution from the first sight:
Use the solution described in this one to detect the point
Write the function PointInPolygon to detect the selected area
(Point in the big circle, Point out of small circle and angle to detect sector)
Other one I have found at the moment the more complex to quick reuse :)
ADDED:
Invoking Events from Effects

Related

How to create a "clicking effect" on a 3d-object (3d-cube) in Unity3d?

I have a 3d-object (cube), which I want to use as a button. I've written the code in order to detect, if the cube was pressed but it doesn't look like it was pressed, since it lacks the "clicking animation". How can I create a clicking animation on my 3d-object ?
A good idea is to play an aninimation which skrinks the cube a bit and releases it immediately afterwards. The handler code you want to execute on a click might block the game loop, e.g. when you load a level. Then it might be useful to load the level aysnchronously to be able to see the animation. Or you execute the handler code after the animation. Or you play the scale down animation on the press event and the scale up animation on the release event.
Technically you can use the build in animation editor, the Update() method, start a coroutine or use the assets iTween or HOTween.
http://docs.unity3d.com/ScriptReference/Transform-localScale.html
Let me know if you like the idea or questions arise.
Unity makes it easier now to do this using Unity Canvas UI. Instead of real 3d buttons, you could place a canvas UI in world space at the location where you want the buttons. Add a UI Panel to the canvas then add a UI Button.
Now, you have out of the box several clicking effects. The default it color tint, but you can choose sprite swap, or animation.
If you do want animation, when you select button animation it will create an animator for you. Click on your UI button Game Object in the scene hierarchy and open the animation window. You can choose Pressed animation from the drop down, and press RECORD button, then edit your buttons scale, say make it 0.75 for x,y,z. Now when you click on the button it will animate a cool scale down for you.
Sorry, I know that is a lot of information dumped! But you will find it pretty great once you start working with it in world space.
You can scale it down a tiny bit once click happen. For example:
void OnMouseDown() {
this.transform.localScale += new Vector3(0.05f, 0.05f, 0.05f);
}
Then after click scale it back to the original size.
Perhaps look into iTween (free on Unity Asset store).
Its very easy to use and you can produce some nice looking animations.
you can scale it when pressed or just change the color a little bit. On mouse up, rescale or recolor it.
void OnMouseDown()
{
transform.localScale -= new Vector3(0.05, 0.05 , 0);
//or
transform.GetComponent<SpriteRenderer>().color += new Color(40,40,40);
}
void OnMouseUp()
{
transform.localScale += new Vector3(0.05, 0.05 , 0);
//or
transform.GetComponent<SpriteRenderer>().color -= new Color(40,40,40);
}
You can implement your button using new Event system of unity. Here are the functions you can implement :
public class ExampleClass : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
public void OnPointerEnter(PointerEventData eventData)
{
//it is the function when you hover your mouse to the object
//You can change the color of your object to make your users
//understand that it is not just a cube but also a clickable item
}
public void OnPointerExit(PointerEventData eventData)
{
//You can revert your color back to its original
}
public void OnPointerDown (PointerEventData eventData)
{
//You can play with local scale as suggested by other answers here
}
public void OnPointerUp (PointerEventData eventData)
{
// Revert back the changes you made at onPointerDown
}
public void OnPointerClick (PointerEventData eventData)
{
//Use here for operations when your button is clicked
}
}

Image/Photo gallery like built-in WP7

I'm looking for a photo gallery for Windows Phone 7. Something that looks and works the same as the built-in photo viewer (slide photo's using a flick action, resize using pinch, drag). When you flick the image you can see it sliding to the next image...and snaps the list to that image.
I already built the resize and drag functionality for the images. I just can't figure out how to create the actual photo slider.
Can anyone point me into the right direction?
Things i've tried:
Pivot Viewer (doesn't work because it interferes with the drag functions of the image, haven't been able to disable the pivot viewer touch)
Plain listbox (can't find how to snap to the current image)
Thanks in advance
Actually I've implemented exactly what you are saying in one of my apps,
You need to use Silverlight Control TOolkit's gesture listener to capture Drag and Pinch from touch.
define a CompositeTransformation for your image and set it's scale (on pinch) and Offset (in drag).
Obviously when the image is not zoom, drag can trigger going to next image.
To make it feel smoother, you may want to define a storyboard on your page resources to use (instead of just settings Offset)
I hope it can help/
Drag handlers pseudo code for slider effect:
<Canvas>
<Image x:Name="imgImage" Source="{Binding ...}" Width="..." Height="...">
<Image.RenderTransform>
<CompositeTransform x:Name="imgImageTranslate" />
</Image.RenderTransform>
</Image>
</Canvas>
private void GestureListener_DragCompleted(object sender, DragCompletedGestureEventArgs e)
{
if (e.Direction == System.Windows.Controls.Orientation.Horizontal)
{
var abs = Math.Abs(PANEL_DRAG_HORIZONTAL);
if (abs > 75)
{
if (PANEL_DRAG_HORIZONTAL > 0) // MovePrevious;
else //MoveNext();
e.Handled = true;
}
}
}
double PANEL_DRAG_HORIZONTAL = 0;
private void GestureListener_DragDelta(object sender, DragDeltaGestureEventArgs e)
{
if (e.Direction == System.Windows.Controls.Orientation.Horizontal)
{
PANEL_DRAG_HORIZONTAL += e.HorizontalChange;
var baseLeft = -imgImage.Width / 2;
if (PANEL_DRAG_HORIZONTAL > 75) imgImageTranslate.OffsetX = baseLeft + PANEL_DRAG_HORIZONTAL;
else if (PANEL_DRAG_HORIZONTAL < -75) imgImageTranslate.OffsetX = baseLeft + PANEL_DRAG_HORIZONTAL;
else imgImageTranslate.OffsetX = baseLeft;
}
}
}
private void GestureListener_DragStarted(object sender, DragStartedGestureEventArgs e)
{
PANEL_DRAG_HORIZONTAL = 0;
}
What about using a ScrollViewer with horizontal orientation? Of course, you will have to manually detect user actions and implement the proper response (with a couple of properly set Storyboards).
Even a better approach would be writing your own custom control that will view images. A good place to start is this - a CoverFlow control in Silverlight. Once you get the idea how you can bind your image collection to a custom control, all you need is handle user gestures on the currently selected item.

Enabling slide animation on windows phone while changing textBlock text

I have a textBlock which covers the entire screen. When the user flicks the screen horizontally, textBlock content is changed. I wanted to show that the new text is shown sliding on the screen when the user does flick gesture.
I tried this:
void listener_Flick(object sender, FlickGestureEventArgs e)
{
if (e.Direction == System.Windows.Controls.Orientation.Horizontal)
{
if (e.HorizontalVelocity.CompareTo(0.0) < 0)
{
SlideTransition sTx = new SlideTransition();
sTx.Mode = SlideTransitionMode.SlideLeftFadeIn;
ITransition transition = sTx.GetTransition(textBlock1);
transition.Completed += delegate
{
transition.Stop();
};
transition.Begin();
textBlock1.Text = "New Text";
}
}
}
Though, I do see a little animation for the new text But I don't see new text really sliding from right. How do I achieve this?
Thanks
I'm not clear how your process is supposed to work as you are only doing one animation. In theory you need to animations. One for sliding out and one for sliding in. If doing this with a single control you wouldn't be able to see the items moving in and out at the same time.
A very similar question was also asked previously: how to implement textblock flick animation windows mobile 7

WP7 transition between Canvas's in a Grid

I have two canvas's in a Grid, full scene "images" that I want to transition, I wonder how I would go about transitioning between these two Canvas controls.
Programatically I add the first canvas to the grid, then I add the second canvas to the grid, and remove the first, what I really want to do is transition between them.
Any suggestions on how I might achieve this programatically?
Thanks.
Edit: I have implemented this method, but am having problems, anyone able to tell me if I'm using it wrong?
private void doTransitionIn(Canvas slide)
{
SlideTransition slideLeft = new SlideTransition();
slideLeft.Mode = SlideTransitionMode.SlideDownFadeIn;
ITransition transition = slideLeft.GetTransition(slide);
transition.Completed += delegate { transition.Stop(); }; transition.Begin();
}
private void doTransitionOut(Canvas slide)
{
SlideTransition slideLeft = new SlideTransition();
slideLeft.Mode = SlideTransitionMode.SlideDownFadeOut;
ITransition transition = slideLeft.GetTransition(slide);
transition.Completed += delegate { transition.Stop(); }; transition.Begin();
}
And here is how I use it:
SceneGrid.Children.Add(nextCanvas);
doTransitionIn(nextCanvas);
doTransitionOut(currentCanvas);
SceneGrid.Children.Remove(currentCanvas);
The problem with this is that the animation only seems to start from part way down the screen, as in, i only see it slide the last 20 or so pixels, it doesn't slide all the way.
Depending on what you mean by "transition" I'd look at creating a StoryBoard to animate the hiding/showing of each canvas.
I would recommend using the TransitioningContentControl which is part of the Silverlight Toolkit. To use this control, make your first Canvas the Content of this control. To transition, simply change the Content to your next Canvas and the TransitioningContentControl does the rest!
There are a number of blog posts that provide tutorials for this control:
http://blogs.academicclub.org/uidev/2010/06/12/transitioning-content-in-silverlight/

VisualStudio: How to add the dotted border to a UserControl at design time?

i have a user control that descends from UserControl.
When dropped onto the form the user control is invisible, because it doesn't have any kind of border to show itself.
The PictureBox and Panel controls, at design time, draws a dashed 1px border to make it visible.
What is the proper way to do that? Is there an attribute you can use to make VS add that?
There is no property that will do this automatically. However you can archive this by overriding the OnPaint in your control and manually drawing the rectangle.
Inside the overridden event you can call base.OnPaint(e) to draw the controls content and then add use the graphics object to paint the dotted line around the edge.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (this.DesignMode)
ControlPaint.DrawBorder( e.Graphics,this.ClientRectangle,Color.Gray,ButtonBorderStyle.Dashed);
}
As you can see you will need to wrap this extra code in an if statement that queries the controls DesignMode property so it only draws in your IDE.
The way that Panel does this (which suggests that this is the actual proper way of doing this) is with the DesignerAttribute. This attribute can be used for design time additions to Control-components as well as non-control components (like Timer).
When using the DesignerAttribute you need to specify a class derived from IDesigner. For a Control designer specifically, you should derive from ControlDesigner.
In your particular implementation of ControlDesigner you want to override the OnPaintAdornment. The purpose of this method is specifically drawing designer hints on top of the control, like a border for example.
Below is the implementation that Panel uses. You could copy that and use it for your control, but you obviously need to adjust the parts that specifically refer to the Panel class.
internal class PanelDesigner : ScrollableControlDesigner
{
protected Pen BorderPen
{
get
{
Color color = ((double)this.Control.BackColor.GetBrightness() < 0.5) ? ControlPaint.Light(this.Control.BackColor) : ControlPaint.Dark(this.Control.BackColor);
return new Pen(color)
{
DashStyle = DashStyle.Dash
};
}
}
public PanelDesigner()
{
base.AutoResizeHandles = true;
}
protected virtual void DrawBorder(Graphics graphics)
{
Panel panel = (Panel)base.Component;
if (panel == null || !panel.Visible)
{
return;
}
Pen borderPen = this.BorderPen;
Rectangle clientRectangle = this.Control.ClientRectangle;
int num = clientRectangle.Width;
clientRectangle.Width = num - 1;
num = clientRectangle.Height;
clientRectangle.Height = num - 1;
graphics.DrawRectangle(borderPen, clientRectangle);
borderPen.Dispose();
}
protected override void OnPaintAdornments(PaintEventArgs pe)
{
Panel panel = (Panel)base.Component;
if (panel.BorderStyle == BorderStyle.None)
{
this.DrawBorder(pe.Graphics);
}
base.OnPaintAdornments(pe);
}
}
ScrollableControlDesigner is a public class that you may or may not want to use as a base for your particular designer implementation.

Resources