touch events on views created outside visible area on scrollview - c#

So I have this problem where I have this view structure:
Controller->View->ScrollView->mainview
and I have a button that's loaded in the mainview, but outside of scrollview's visible content. When I scroll up to see the button, the touch doesn't work, but if I place the button to load in the visible area it works.
I also tried with a simple imageview and setting a gesture recognizer (with user interaction enabled) and the problem is exactly the same.
This is where I define the button:
UIButton scrapbookbackground = new UIButton(new CGRect(SPACING, progresses_view.Frame.Y + progresses_view.Frame.Height + SPACING, View.Frame.Width - SPACING * 2, 90));
scrapbookbackground.BackgroundColor = UIColor.Clear.FromHex(0x4f80bc);
scrapbookbackground.Layer.CornerRadius = 10f;
scrapbookbackground.Layer.BorderWidth = 1f;
scrapbookbackground.Layer.BorderColor = UIColor.Blue.CGColor;
scrapbookbackground.ClipsToBounds = true;
scrapbookimg = UIImage.FromFile("Images/scrap_capa.png");
scrapbookbackground.SetBackgroundImage(scrapbookimg, UIControlState.Normal);
scrapbookbackground.TouchUpInside += (args, e) => {
Console.WriteLine("scrapbooktouch");
NavigationController.PushViewController(new ScrapBookPageViewController(), true);
};
mainview.Add(scrapbookbackground);

figured it out. was not setting contentsize of scrollview properly.

Related

Creating a draggable map pin on UWP

After following the instructions in the link here How to create draggable pin in windows 10 to give pick location functionality?
I have a half working dragging pin.
Currently the map pin (Grid) starts in the correct place on the map, however, upon dragging the map pin the pin initially pops up to the top left of the screen (0,0) and starts dragging from here.
Upon dropping the pin it appears to have disconnected from the map element itself as you can then scroll the map and the pin stays in place on the screen.
I am using Xamarin.Forms with a custom map renderer.
Following the original example the map would still pan along with the pin dragging, I corrected this by disabling panning upon Grid_ManipuationStarted.
The issue seems to be with the Grid_ManipulationDelta function as this is what removes the Grid from the MapControl children.
I've uploaded a video of the issue onto YouTube. Found here: https://youtu.be/uUkB5Pi5MnA
My code is as follows:
void IMapControls.startDraggable(Location l) {
// Create the XAML
var grid = new Windows.UI.Xaml.Controls.Grid {
Height=50,
Width=32,
Background = new ImageBrush() { ImageSource= new BitmapImage(new Uri("ms-appx:///pin.png",UriKind.RelativeOrAbsolute)),Stretch = Stretch.Uniform },
};
grid.ManipulationMode = ManipulationModes.TranslateX|ManipulationModes.TranslateY;
grid.ManipulationCompleted += Grid_ManipulationCompleted;
grid.ManipulationStarted += Grid_ManipuationStarted;
grid.ManipulationDelta += Grid_ManipulationDelta;
// Set RenderTransform so not null later
CompositeTransform tran = new CompositeTransform();
grid.RenderTransform = tran;
// Add XAML to the map.
nativeMap.Children.Add(grid);
Geopoint snPoint = new Geopoint(new BasicGeoposition() { Latitude = l.lat,Longitude = l.lng });
MapControl.SetLocation(grid,snPoint);
MapControl.SetNormalizedAnchorPoint(grid,new Windows.Foundation.Point(0.5,1.0));
}
private void Grid_ManipuationStarted(Object sender,ManipulationStartedRoutedEventArgs e) {
nativeMap.PanInteractionMode=MapPanInteractionMode.Disabled;
}
private void Grid_ManipulationDelta(object sender,ManipulationDeltaRoutedEventArgs e) {
var grid = sender as Windows.UI.Xaml.Controls.Grid;
CompositeTransform xform = grid.RenderTransform as CompositeTransform;
xform.TranslateX += e.Delta.Translation.X;
xform.TranslateY += e.Delta.Translation.Y;
e.Handled = true;
}
private void Grid_ManipulationCompleted(object sender,ManipulationCompletedRoutedEventArgs e) {
nativeMap.PanInteractionMode=MapPanInteractionMode.Auto;
var grid = sender as Windows.UI.Xaml.Controls.Grid;
Rect point = grid.TransformToVisual(nativeMap).TransformBounds(new Rect(0,0,grid.Width,grid.Height));
Geopoint gPoint;
nativeMap.GetLocationFromOffset(new Windows.Foundation.Point(point.X,point.Y),out gPoint);
Debug.WriteLine(gPoint.Position.Latitude);
Debug.WriteLine(gPoint.Position.Longitude);
}
Solved this by creating a Grid and adding it to the map, then creating an Image and adding this to the Grid. You drag the Image using Delta.Translation as above and upon dropping the pin it moves the Grid using MapControl.SetLocation (Not TranslateX/Y) to where the pin drops, then TranslateX/Y the pin Image to 0,0 (relative to the parent Grid).
This works as the Grid only moves using SetLocation which seems to work fine and doesn't disconnect it from the map like before. The pin moves relative to the Grid and has no issues as before, ie. Moving to 0,0 upon start and disconnecting from the map object.
Cheers!
Can post code if anyone is interested but I think it is pretty self explanatory.

Slide Border onto screen

I need to make a border slide from the bottom of the screen into view, however i'm having issues getting the ActualHeight of my border control. Because this is animation code i'm putting it in the code-behind as it's the Views responsibility.
My Border has got it's Loaded event tied to this:
private void NotifcationWindow_Loaded(object sender, RoutedEventArgs e)
{
SlideFromBottom(sender);
}
The Sender is the Border object, so the SlideFromBottom method SHOULD be able to use this object and get it's height as it has already been rendered.
public void SlideFromBottom(object sender)
{
//The Notification container
Border notification = (sender as Border);
//The screen size
var workingArea = SystemParameters.WorkArea;
Storyboard sb = new Storyboard();
var animation = new DoubleAnimation()
{
BeginTime = TimeSpan.FromSeconds(0),
Duration = TimeSpan.FromSeconds(5),
// Get the height and turn it to a negative value, and add screen height.
From = (notification.ActualHeight * -1),
//Slide the border into view
To = notification.ActualHeight
};
Storyboard.SetTarget(animation, notification);
Storyboard.SetTargetProperty(animation, new PropertyPath("(Margin.Bottom)"));
sb.Begin();
}
I'm not receiving any errors, but the animation isn't playing, have I got something wrong? The Border is Vertically Aligned to the bottom, so the negative margin should take it off the screen.
The reason why you're not seeing anything is that you haven't added the animation to the storyboard:
sb.Children.Add(animation);
Then there are some more problems. Such that a part of the margin cannot be animated separately. You would need a ThicknessAnimation.
But there is an easier solution. Use the RenderTransform. If you give your border the following render transform:
<Border>
<Border.RenderTransform>
<TranslateTransform/>
</Border.RenderTransform>
</Border>
, then you can animate it as follows:
// ...
var animation = new DoubleAnimation()
{
BeginTime = TimeSpan.FromSeconds(0),
Duration = TimeSpan.FromSeconds(5),
From = notification.ActualHeight,
To = 0
};
Storyboard.SetTarget(animation, notification);
Storyboard.SetTargetProperty(animation, new PropertyPath("RenderTransform.Y"));
sb.Children.Add(animation);
// ...

Activating mousedown on dynamically created object

I'm working on a project where I want to "drag" data from a listview to a panel. The goal is that people can select the information on the listview and then position a panel with that information on it on a sort of flowchart on another panel.
Pretty much all of the code is already working but there's one thing which I'm still struggeling with. When I perform a Mouse Down on the listview, a panel is being generated with a few labels on it to be able to drag. The code below is a simplified version for readability.
private void createPlayerPanel()
{
var coordinates = this.PointToClient(Cursor.Position);
// CREATE THE PANEL
Panel panPlayer = new Panel();
// SETUP THE PANEL
panPlayer.Name = "panPlayer1";
panPlayer.Width = 200;
panPlayer.Height = 50;
panPlayer.BackColor = Color.Gainsboro;
panPlayer.Click += new EventHandler(this.panClick);
panPlayer.MouseDown += new MouseEventHandler(panMouseDown);
// ADD THE PANEL TO THE FORM
this.Controls.Add(panPlayer);
// BRING THE PANEL TO THE FRONT OF THE FORM
panPlayer.BringToFront();
panPlayer.Location = new Point(coordinates.X - 14, coordinates.Y - 12);
}
public bool Dragging = false;
Point location;
Panel panSelected;
private void panMouseDown(object sender, MouseEventArgs e)
{
panSelected = (Panel)sender;
Dragging = true;
location = e.Location;
}
However with the same Mouse Down I would like to drag the panel to the flowchart. So in one smooth movement, click on the information in the listview and drag it to the second panel.
When I generate the panel, I also include a Mouse Down mouseeventhandler but which is not active yet when I perform the mousedown. So when I release the mouse and then hold down the mouse again, it works fine and I can drag the panel to it's new position. But I would like to do it in one action. So MOUSE DOWN > GENERATE PANEL > ACTIVATE MOUSE EVENT > DRAG PANEL
Is there a way I can activate the mousedown-event of the panel when I've finished creating it?

Is there a way to move adjust a pushpin position manualy on windows phone 8 using bing maps?

I am working on a windows phone 8.0 application wich uses bing maps. I wnat to add a push pin with my current location. So far soo good. What I do not manage to do is to move that pin. More precisely, I want to tap that pin and to mo move it otherwhere on the map.
I tried with events like ManipulationStarted, ManipulationDelta, ManipulationCompleted and other resources on the web, but no results yet.
My C# code:
public partial class MainPage : PhoneApplicationPage
{
Pushpin pin = new Pushpin();
// Constructor
public MainPage()
{
InitializeComponent();
GetCurrentPosition();
}
async void GetCurrentPosition()
{
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracyInMeters = 50;
Geoposition geoposition = await geolocator.GetGeopositionAsync();
Grid MyGrid = new Grid();
MyGrid.RowDefinitions.Add(new RowDefinition());
MyGrid.RowDefinitions.Add(new RowDefinition());
MyGrid.Background = new SolidColorBrush(Colors.Transparent);
pin.Content = "I'm a pin";
pin.Foreground = new SolidColorBrush(Colors.Purple);
pin.ManipulationDelta += pin_ManipulationDelta;
pin.ManipulationStarted += pin_ManipulationStarted;
pin.ManipulationCompleted += pin_ManipulationCompleted;
MyGrid.Children.Add(pin);
//Creating a MapOverlay and adding the Grid to it.
MapOverlay MyOverlay = new MapOverlay();
MyOverlay.Content = MyGrid;
MyOverlay.GeoCoordinate = new GeoCoordinate(geoposition.Coordinate.Latitude, geoposition.Coordinate.Longitude);
MyOverlay.PositionOrigin = new Point(0, 0.5);
MyMap.Center = new System.Device.Location.GeoCoordinate(geoposition.Coordinate.Latitude, geoposition.Coordinate.Longitude);
MyMap.ZoomLevel = 16;
MyMap.CartographicMode = Microsoft.Phone.Maps.Controls.MapCartographicMode.Road;
MapLayer MyLayer = new MapLayer();
MyLayer.Add(MyOverlay);
MyMap.Layers.Add(MyLayer);
translateTransform = new TranslateTransform();
}
void pin_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
//MessageBox.Show("started");
}
void pin_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
MessageBox.Show("moving");
//how do a get the coordonites while I'm moving the pin?
}
void pin_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
MessageBox.Show("completed");
}
}
Aby ideas how to make the pin draggeble? If I set pin.AllowDrop=true it throws NotImplementedException.
Thank you in advance!
Just thinking a little differently...
The solution I used for NZ Topo Map was to overlay a cross-hair over the map so the user could position the pin precisely by dragging the map instead of dragging a pin. I would then use an app bar with a tick and a cross for "create pin" and "cancel".
Just an alternative UI idea for you to mull over that might be easier to implement and maybe easier for the user.
You have to set the move events on the mouse events on the map. This will let you be able to track where the user has moved to. Essentially you would add a mouse down event to the pushpin which would set a flag to capture to allow dragging the pin. Then you would use the mouse move event on the map to reposition the pushpin and the mouse up event on the map to turn the dragging flag off. You will also likely want to display panning of the map. Try capturing the center value when the mouse down event fires, then set the center of the map to this value constantly on the mouse move event when the drag flag it turned on.

Center UISegmentedControl within a UISearchBar

I am using the built-in search scope with a UISearchDisplayController, and I only have 2 segments.
The problem is that our design needs the buttons to be smaller and centered (it especially looks bad on iPad because the buttons are stretched really wide).
Is there a way to center the UISegmentedControl and make it smaller? I already have the UISegmentedControl pulled out by looping over subViews. And I can set the width of each segment with setWidth:forSegmentAtIndex, but the control is docked to the left. How can I center it?
PS - my app is MonoTouch (Xamarin.iOS), but Obj-C answers are welcome.
Are you adding this via IB or programmatically? In IB, I had to turn off "Autoresize Subviews" and do the resizing of the control dynamically via code. I put the controls I needed to resize into a view that I could bind to then center my control within that view. Here's a sample. I had 2 buttons that I put side-by-side in landscape mode, but it should give you an idea.
// get the current sizes of the things we are moving
CGRect saveRect = self.viewButtons.frame; // the enclosing view
CGRect addLocRect = self.buttonAddLocation.frame; // button 1
CGRect connectRect = self.buttonConnect.frame; // button 2
// This will be set below in one of the if-else branches
CGFloat buttonWidth = 0;
// determine the offset from the left/right based on device and orientation
int offsetLeft = 0;
int offsetRight = 0;
if ([self isIphone]) {
offsetLeft = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPHONE : OFFSET_LEFT_LANDSCAPE_IPHONE;
offsetRight = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_RIGHT_PORTRAIT_IPHONE : OFFSET_RIGHT_LANDSCAPE_IPHONE;
} else {
offsetLeft = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPAD : OFFSET_LEFT_LANDSCAPE_IPAD;
offsetRight = offsetLeft;
}
// change the size & location of the buttons to maximize the area for the location list
// no matter what orientation, the button frame will fill the bottom of the screen
saveRect.size.width = _windowWidth -offsetLeft - offsetRight;
// for Landscape, move the buttons to side-by-side at the bottom of the window
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
// size & move the buttons to fit side-by-side
buttonWidth = (saveRect.size.width)*.4;
// addLocRect.origin.x += offset;
addLocRect.origin.y = saveRect.size.height - addLocRect.size.height ;
connectRect.origin.x = saveRect.size.width - buttonWidth - offsetRight;
connectRect.origin.y = saveRect.size.height - connectRect.size.height;
} else { // Portrait
// move the buttons down to the bottom of the frame, stacked
// size the buttons to be fully across the screen
buttonWidth = saveRect.size.width-2*offsetLeft;
addLocRect.origin.y = 0 ; // at the top of the button view
addLocRect.origin.x = offsetLeft;
connectRect.origin.y = saveRect.size.height - connectRect.size.height;
connectRect.origin.x = offsetLeft;
}
connectRect.size.width = buttonWidth;
addLocRect.size.width = buttonWidth;
self.buttonAddLocation.frame = addLocRect;
self.buttonConnect.frame = connectRect;

Categories