How to register touches while another finger is held down - silverlight

On a WP7 device I have a canvas. When the user touches anywhere on the canvas an image is displayed at that position.
I want to add a feature where if a user touches and holds the screen with one finger and then touches the screen in another place with a different finger an image is also displayed. So basically I want to be able capture and respond to the second touch in the simplest possible way. Any ideas?

Have you taken a look at the GestureService? The Pinch* events let you handle two simultanious touches.
See example.

what you need is just the GestureListener which lies in the Microsoft.Phone.Controls namespace, which can handle a couple gestures like
Flick
Pinch
Drag
Swipe
etc.
You can use it like so
var gestureListener = GestureService.GetGestureListener(myCanvas);
//registering the Events
gestureListener.PinchStarted += new EventHandler<PinchStartedGestureEventArgs>(PinchStartedHandler);
gestureListener.PinchDelta += new EventHandler<PinchGestureEventArgs>(PinchDeltaHandler);
gestureListener.PinchCompleted += new EventHandler<PinchGestureEventArgs>(PinchCompletedHandler);
In the approriate Hanler-Methods you do your rotate- and scale- transformations.

Since you are clearly in Silverlight, this post shows you how to implement multitouch for yourself - http://mine.tuxfamily.org/?p=111
Register for touches
Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
Then handle those touches:
void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
// if there are more than one finger on screen
if (e.GetTouchPoints(myCanvas).Count == 2)
{
TouchPointCollection tpc = e.GetTouchPoints(myCanvas);
// use tpc[0].Position
// use tpc[1].Position
}
}
Alternatively, if you want to use ready-build Gestures, then consider using the latest Silverlight Toolkit - see this blog post for information - http://3water.wordpress.com/2011/03/09/wp7-gesture-recognition-2/

Related

Detecting mouse click on specific SKPath using skiasharp SKControl

I am using the Skiasharp Windows Forms SKControl to handle drawing actions within my app. Part of the functionality is to be able to click on the canvas to select a specific "layer" and allow the user to apply a different color to each layer. See the image below for an example.
The three layers in this image are drawn as three separate paths. For the most part, the code that I have is working great, except for when those "layers" overlap. If I click on the lightest layer in the above image at a point that is lower than the "point" of the darkest layer, it will select the darker layer.
This makes sense since I am using path.GetBounds() which returns an SKRect. On mouse click I am creating an SKRect from the click location and then calling rect.IntersectsWith(mouseRect) to determine which "layer" I clicked on.
How can I validate layer clicked given the paths are not simple rectangles?
Here is the code that I am using for the "HitTest" (non-optimized since I was debugging)
SKRect hitRect = SKRect.Create(scaledPixelPosition, new SKSize(20f, 20f));
ElementLayerInfo elementLayerInfo = new ElementLayerInfo();
foreach(Element element in _elements)
{
foreach (KeyValuePair<int, ElementLayerInfo> kvp in element.ElementLayers)
{
if (kvp.Value.LayerRect.IntersectsWith(hitRect))
{
elementLayerInfo = kvp.Value;
}
}
}

Codename One app shown in a centered rectangle on wide screens

Note for the readers: this question is referred exclusively to Codename One.
Because I have multiple targets for the same app (Android, iOS, Javascript), that can be run on small screens (that is the typical use case) but also on wide screens, I have to do a choice about the UI.
I want to simplify my life: mobile devices held on portrait mode are my primary target, so... all wide screens (desktop and tablet) will show the app inside a vertical rectangle in the center of the screen. Maybe this is not the best solution, but it can make sense. I suppose that the width of that centered rectangle is 9 cm (my iPhone device width is about 7 cm and my Android device width is about 8 cm).
So... what is a proper way to accomplish this requirement?
Initially I thought that I can create a BaseForm with a code that override the show() method, setting a left and right margin for ContentPane, LayeredPane and Toolbar before calling super.show()... but this solution seems to me a poor way to go and also an overhead, because in that case I'll need to recalculate the margins and to revalidate the BaseForm for every change of size of screen... and, however, this solution will not work with FABs or Dialogs. So... it's not a solution.
It could be nice if I can choose a background (an image or a color) for all the space outside the centered rectangle containing the app.
Any better idea?
This is probably something that we need to implement in the system to make it seamless. Any approach you choose will require some work.
If I were doing something like this I'd create a special form with no title that acts as your background. I'd give it a special custom layout manager that centers the content. Something like:
public CenterOneCompnentLayout class Layout {
public void layoutContainer(Container parent) {
if(parent.getComponentCount() == 1) {
Component cmp = parent.getComponentAt(0);
cmp.setWidth(convertToPixels(9));
cmp.setHeight(parent.getHeight());
cmp.setY(0);
cmp.setX(parent.getWidth() / 2 - cmp.getWidth() / 2);
}
}
public Dimension getPreferredSize(Container parent) {
return new Dimension(100, 100);
}
}
Now just add the actual form to this background form. The rest should work "as is". I think you would need to guard against some things and it's possible this hack will produce some side effects due to the nesting of the forms. But ultimately it should work.

How to keep an MKAnnotation View Image fixed on the center of the map as the user pans and moves the map around (iOS 6)?

using iOS 6 MapKit, I would like to define an MKAnnotation (such as a pin, or a custom one) that remains fixed on the center of the map view as the user moves the map around. Once the user stops moving the map, I would like to be able to read the new coordinates of the annotation. How can I do this?
Thanks
The easiest way is to simply add your custom UIView to your MKMapView as a subview. This means when your user moves the map it will stay fixed. You will most likely have to pass through the touch events so that users can move over your custom view but worry about that later.
When your map view stops moving take its center coordinate. The MKMapView can calculate its coordinate based on its center etc [mapView centerCoordinate];
I know this is a bit old but I recommend you DSCenterPinMapView
It is a custom MapView with an animated and customizable center pin useful for selecting locations in map.
You should install the Pod and then, as a solution to your question you should implement the delegate so that you can get the location where pin drops.
pinMapView.delegate = self
extension MyViewController: DSCenterPinMapViewDelegate {
func didStartDragging() {
// My custom actions
}
func didEndDragging() {
// My custom actions
selectedLocation = pinMapView.mapview.centerCoordinate
}
}

Silverlight MapLayer right click issue

I am currently developing a Silverlight OOB application using the Bing Map Control, however I have come across an issue I am struggling to resolve. Basically I have three map layers:-
Base Map (bottom layer)
Icon / Pushpin layer (middle layer)
Shape / drawing layer (top layer)
This all works fine, I have put mouse right click functionality on each of my icons (pushpins if you prefer), if I add a map polygon or polyline to the top layer and this item happens to cover the same area as one of my icons in the middle layer I can no longer get any of the mouse events to fire on my icon.
If anyone can think of a way I can pass the mouse operations from my top layer objects to the middle layer objects please let me know.
Many thanks in advance
Set the IsHitTestVisible of your top layer to false. I feel I need to type more text here but there really isn't much more to say.
It's not clear from your question if you need both the shape and the icon to get the mouse event.
If all you need is for the icon to get the event, then switch the order of your layers so Icon layer is on top.
If you need both shape and icon to get the event, then (if you keep your order with shapes on top) you would need to have some way to tell what icons a shape covers. Do you have a parent/child releationship between them? If not, can you create one? If you set up an event on the shape, and set up OnEvent handlers for the icons that listen to the events, then you can have the icons react as well.
If you are more clear about what your situation is, I could post some code that could help.

SL 4 -- Force redraw of visual tree

Our application has a number of objects on a canvas; the canvas is contained in a scroll viewer. We also have a slider control and some buttons, always centered at the top of the window.
I am trying to print the application by capturing a bitmap of the app, but without any 'decorations' -- slider, buttons, or scroll bars.
_scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
_scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
var s = xSlider;
s.Visibility = Visibility.Collapsed;
var b = xPlusButton;
b.Visibility = Visibility.Collapsed;
b = xMinusButton;
b.Visibility = Visibility.Collapsed;
b = xButton;
b.Visibility = Visibility.Collapsed;
The slider and buttons are hidden, as expected, but the scrollbars are not.
I suspect the application needs to redraw the layout in order to hide the scrollbars. Is there a way to make that happen? This is made more complicated by the fact that the print operation in SL 4 must be initiated by a UI gesture; there is no way (AFAIK) to initiate programatically, so this redraw must happen in one of the PrintDocument event handlers.
Thanks for any suggestions....
Try following,
canvas.InvalidateMeasure();
canvas.InvalidateArrange();
You can alternatively use WritableBitmap to capture runtime image and send image to print document if in case print document is ignoring render transform.
Also if you are using WritableBitmap to capture the element then you should give RenderTransform as second argument. Can you post your code to capture screen?
In addition to the InvalidateMeasure and InvalidateArrange methods, as suggested by Akash, you can try the UpdateLayout method.
The two invalidate methods will mark the control's measure or arrange as needing to be executed again, but won't necessarily do it immediately. The UpdateLayout will force it to execute some updates immediately.
It's a bit of a black box, so you may need to invalidate then call UpdateLayout. Sometimes you may just need to call UpdateLayout.

Resources