I have the following test code running on my phone. It shows a circle on the map where my GeoFence is. If I walk outside of the fence, then back in then backout the events are never firing. I have no idea what Im missing:
using MonoTouch;
using CoreLocation;
using MapKit;
using System.Drawing;
using CoreGraphics;
namespace GeoFencingTest
{
public class GeoFencingController : UIViewController
{
UIWindow Parent;
CustomMapView mapView;
CLLocationManager locMgr = new CLLocationManager ();
UITextView textview;
UIButton button;
CLCircularRegion region;
CLLocationCoordinate2D FenceCenter;
public GeoFencingController (UIWindow parent)
{
var radius = 25;
FenceCenter = new CLLocationCoordinate2D (33.8399522334765, -84.3729872355209);
Parent = parent;
View = new UIView (new RectangleF ((float)Parent.Bounds.Left, (float)Parent.Bounds.Top, (float)Parent.Bounds.Width, (float)Parent.Bounds.Height));
parent.AddSubview (View);
locMgr.RequestWhenInUseAuthorization ();
locMgr.DesiredAccuracy = 5;
locMgr.StartUpdatingLocation ();
region = new CLCircularRegion (FenceCenter, radius, "TPM");
locMgr.StartMonitoring (region);
mapView = new CustomMapView ();
mapView.Frame = new RectangleF ((float)Parent.Bounds.Left + 20, (float)55, (float)Parent.Bounds.Width - 40, (float)Parent.Bounds.Height - 80);
mapView.ShowsUserLocation = true;
mapView.UserInteractionEnabled = true;
mapView.MapType = MKMapType.Hybrid;
mapView.ZoomEnabled = true;
mapView.ScrollEnabled = true;
mapView.UserTrackingMode = MKUserTrackingMode.Follow;
mapView.Delegate = new MapDelegate ();
mapView.CenterCoordinate = FenceCenter;
View.AddSubview (mapView);
var circleOverlay = MKCircle.Circle (new CLLocationCoordinate2D (FenceCenter.Latitude, FenceCenter.Longitude), radius);
mapView.AddOverlay (circleOverlay);
textview = new UITextView (new RectangleF (0, 20, 190, 50));
View.AddSubview (textview);
if (CLLocationManager.IsMonitoringAvailable (typeof(CLCircularRegion))) {
locMgr.DidStartMonitoringForRegion += (o, e) => {
textview.Text = "Now monitoring region " + e.Region.ToString ();
};
locMgr.RegionEntered += (o, e) => {
textview.Text = "Just entered " + e.Region.ToString ();
};
locMgr.RegionLeft += (o, e) => {
textview.Text = "Just left " + e.Region.ToString ();
};
} else {
textview.Text = "This app requires region monitoring, which is unavailable on this device";
}
}
public class MapDelegate : MKMapViewDelegate
{
public override MKOverlayView GetViewForOverlay (MKMapView mapView, NSObject overlay)
{
// return a view for the polygon
MKCircle circle = overlay as MKCircle;
MKCircleView circleView = new MKCircleView (circle);
circleView.FillColor = UIColor.Yellow;
circleView.Alpha = 0.5f;
circleView.LineWidth = 10;
circleView.StrokeColor = UIColor.Red;
return circleView;
}
}
public class CustomMapView : MKMapView
{
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
base.TouchesBegan (touches, evt);
UITouch touch = touches.AnyObject as UITouch;
CGPoint pointInView = touch.LocationInView (this);
CLLocationCoordinate2D touchCoordinates = base.ConvertPoint (pointInView, this);
MKMapPoint mapPoint = MKMapPoint.FromCoordinate (touchCoordinates);
Console.WriteLine ("LAT: " + touchCoordinates.Latitude);
Console.WriteLine ("LON: " + touchCoordinates.Longitude);
}
}
}
}
You may want to try setting up your event handlers before calling StartMonitoring instead of after.
Related
becauseNStokenField doesn't support scroll bars, I embed it inside scroll view, but it doesn't work ...
At first I used constraints fot NSTokenField like this :
but it seems that NTToken frame height isn't changed while typing much tags , than I tried to increase it dynamically, here is what I did :
public override void ViewWillAppear ()
{
base.ViewWillAppear ();
this.View.Window.MakeKeyAndOrderFront (this);
TxtTagField.Changed += (o, e) => {
ResizeTokenField ();
};
}
void ResizeTokenField ()
{
//
if (!TxtTagField.Cell.Wraps) {
return;
}
CGRect frame = TxtTagField.Frame;
var width = frame.Size.Width;
var size = frame.Size;
size.Height = nfloat.MaxValue;
frame.Size = size;
nfloat height = TxtTagField.Cell.CellSizeForBounds (frame).Height;
if (height > 44) {
var fr = TxtTagField.Frame;
fr.Size = new CGSize (width, height + 23);
InvokeOnMainThread (() => {
TxtTagField.Frame = fr;
});
}
}
but still get no result :(
I am trying to run some source code that I downloaded from here
This is essentially an app that will allow users to manage contacts and calendar appointments etc.
I am currently experiencing 3 errors, all seemingly related...
CS1061 - UIImageView does not contain a definition for 'SetImage' and no extension method 'SetImage' accepting a first argument of type 'UIImageView' could be found (are you missing a using directive or an assembly reference?)
It seems that SetImage is not defined somewhere?
Would someone be able to tell me what i need to do to resolve the error. I post my code below...
using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using MessageUI;
using Microsoft.Office365.OutlookServices;
using FiveMinuteMeeting.Shared.ViewModels;
using CoreGraphics;
using FiveMinuteMeeting.Shared;
namespace FiveMinuteMeeting.iOS
{
partial class ContactDetailViewController : UIViewController
{
public ContactDetailViewController(IntPtr handle)
: base(handle)
{
}
public DetailsViewModel ViewModel
{
get;
set;
}
UIBarButtonItem save;
public override void ViewDidLoad()
{
base.ViewDidLoad();
NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
save = new UIBarButtonItem(UIBarButtonSystemItem.Save,
async (sender, args) =>
{
ViewModel.FirstName = TextFirst.Text.Trim();
ViewModel.LastName = TextLast.Text.Trim();
ViewModel.Email = TextEmail.Text.Trim();
ViewModel.Phone = TextPhone.Text.Trim();
//BigTed.BTProgressHUD.Show("Saving contact...");
await ViewModel.SaveContact();
//BigTed.BTProgressHUD.Dismiss();
NavigationController.PopToRootViewController(true);
});
TextEmail.ShouldReturn += ShouldReturn;
TextFirst.ShouldReturn += ShouldReturn;
TextPhone.ShouldReturn += ShouldReturn;
TextLast.ShouldReturn += ShouldReturn;
TextEmail.ValueChanged += (sender, args) =>
{
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(TextEmail.Text, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
};
var color = new CGColor(17.0F / 255.0F, 113.0F / 255.0F, 197.0F / 255F);
TextEmail.Layer.BorderColor = color;
TextFirst.Layer.BorderColor = color;
TextPhone.Layer.BorderColor = color;
TextLast.Layer.BorderColor = color;
ButtonCall.Clicked += (sender, args) => PlaceCall();
NSNotificationCenter.DefaultCenter.AddObserver
(UIKeyboard.DidShowNotification, KeyBoardUpNotification);
// Keyboard Down
NSNotificationCenter.DefaultCenter.AddObserver
(UIKeyboard.WillHideNotification, KeyBoardDownNotification);
double min = Math.Min((float)ImagePhoto.Frame.Width, (float)ImagePhoto.Frame.Height);
ImagePhoto.Layer.CornerRadius = (float)(min / 2.0);
ImagePhoto.Layer.MasksToBounds = false;
ImagePhoto.Layer.BorderColor = new CGColor(1, 1, 1);
ImagePhoto.Layer.BorderWidth = 3;
ImagePhoto.ClipsToBounds = true;
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (ViewModel == null)
{
ViewModel = new DetailsViewModel();
NavigationItem.RightBarButtonItem = save;
}
else
{
this.Title = ViewModel.FirstName;
TextEmail.Text = ViewModel.Email;
TextFirst.Text = ViewModel.FirstName;
TextLast.Text = ViewModel.LastName;
TextPhone.Text = ViewModel.Phone;
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(ViewModel.Contact.EmailAddresses[0].Address, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
NavigationItem.RightBarButtonItem = null;
}
}
private bool ShouldReturn(UITextField field)
{
field.ResignFirstResponder();
return true;
}
private void PlaceCall()
{
var alertPrompt = new UIAlertView("Dial Number?",
"Do you want to call " + TextPhone.Text + "?",
null, "No", "Yes");
alertPrompt.Dismissed += (sender, e) =>
{
if ((int)e.ButtonIndex >= (int)alertPrompt.FirstOtherButtonIndex)
{
var url = new NSUrl("tel:" + TextPhone.Text);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Not supported",
"Scheme 'tel:' is not supported on this device",
null,
"OK",
null);
av.Show();
}
else
{
UIApplication.SharedApplication.OpenUrl(url);
}
}
};
alertPrompt.Show();
}
/*private async void SendEmail()
{
var mailController = new MFMailComposeViewController();
mailController.SetToRecipients(new string[] { TextEmail.Text });
mailController.SetSubject("5 Minute Meeting");
mailController.SetMessageBody("We are having a 5 minute stand up tomorrow at this time! Check your calendar.", false);
mailController.Finished += (object s, MFComposeResultEventArgs args) =>
{
Console.WriteLine(args.Result.ToString());
args.Controller.DismissViewController(true, (Action)null);
};
PresentViewControllerAsync(mailController, true);
}*/
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
switch(segue.Identifier)
{
case "email":
{
var vc = segue.DestinationViewController as SendEmailViewController;
vc.ViewModel.FirstName = ViewModel.FirstName;
vc.ViewModel.LastName = ViewModel.LastName;
vc.ViewModel.Email = ViewModel.Email;
}
break;
case "meeting":
{
var vc = segue.DestinationViewController as NewEventDurationViewController;
vc.ViewModel.FirstName = ViewModel.FirstName;
vc.ViewModel.LastName = ViewModel.LastName;
vc.ViewModel.Email = ViewModel.Email;
}
break;
}
}
#region Keyboard
private UIView activeview; // Controller that activated the keyboard
private float scrollamount; // amount to scroll
private float bottom; // bottom point
private const float Offset = 68.0f; // extra offset
private bool moveViewUp; // which direction are we moving
private void KeyBoardDownNotification(NSNotification notification)
{
if (moveViewUp) { ScrollTheView(false); }
}
private void ScrollTheView(bool move)
{
// scroll the view up or down
UIView.BeginAnimations(string.Empty, System.IntPtr.Zero);
UIView.SetAnimationDuration(0.3);
CGRect frame = (CGRect)View.Frame;
if (move)
{
frame.Y -= scrollamount;
}
else
{
frame.Y += scrollamount;
scrollamount = 0;
}
View.Frame = frame;
UIView.CommitAnimations();
}
private void KeyBoardUpNotification(NSNotification notification)
{
// get the keyboard size
var r = (CGRect)UIKeyboard.FrameBeginFromNotification((NSNotification)notification);
// Find what opened the keyboard
foreach (UIView view in this.View.Subviews)
{
if (view.IsFirstResponder)
activeview = view;
}
// Bottom of the controller = initial position + height + offset
bottom = ((float)activeview.Frame.Y + (float)activeview.Frame.Height + Offset);
// Calculate how far we need to scroll
scrollamount = ((float)r.Height - ((float)View.Frame.Size.Height - bottom));
// Perform the scrolling
if (scrollamount > 0)
{
moveViewUp = true;
ScrollTheView(moveViewUp);
}
else
{
moveViewUp = false;
}
}
#endregion
}
}
I am very new to Xamarin & app development and I just wanted to run this because it is a very similar project to one that I am creating.
Thanks for your help
SetImage is a extension method contained in Xamarin.SDWebImage. Ensure, that you have restored all nuget packages or have installed it via
Install-Package Xamarin.SDWebImage
see: https://www.nuget.org/packages/Xamarin.SDWebImage/
Here a explanation of the error.
https://msdn.microsoft.com/en-us/library/bb383961.aspx
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
CS1061 - UIImageView does not contain a definition for 'SetImage' and no extension method 'SetImage' accepting a first argument of type 'UIImageView' could be found (are you missing a using directive or an assembly reference?)
In your code I don't watch a declaration of ImagePhoto check right click goto definition. And verify that for imagePhoto exist a method setImage ImagePhoto I'm asumming that is object of type UIImage
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(TextEmail.Text, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
I have created a PlayPage.xaml, PlayPage.xaml.cs and Game.cs file.
The PlayPage.xaml.cs has two variable, windowWidth and windowHeight.
I would like access two public static variable from Game.cs.
Game.cs:
namespace UwpApp
{
class Game
{
static Rectangle rectangle;
PlayPage pg = new PlayPage();
//Create a rectangle
public Rectangle draw()
{
rectangle = new Rectangle();
rectangle.Width = 70;
rectangle.Height = 70;
rectangle.Fill = new SolidColorBrush(Colors.Green);
Canvas.SetLeft(rectangle, randPos());
Canvas.SetTop(rectangle, randPos());
return rectangle;
}
//Create a random X and Y position
private Int32 randPos()
{
Random rnd = new Random();
Debug.WriteLine(pg.windowWidth);
return rnd.Next(0 , (int)pg.windowWidth);
}
}
}
PlayPage.xaml.cs:
namespace UwpApp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public partial class PlayPage : Page
{
DispatcherTimer timer;
Rectangle rect;
bool isTapped;
public static double windowWidth, windowHeight;
Game game = new Game();
public PlayPage()
{
this.InitializeComponent();
startCounter.Visibility = Visibility.Collapsed;
isTapped = false;
}
private void Load_Variable(object sender, RoutedEventArgs e)
{
windowWidth = canvas.ActualWidth;
windowHeight = canvas.ActualHeight;
}
//Counter animation. (Number opacity, fall)
private void counterAnimation()
{
startCounter.Visibility = Visibility.Visible;
//Set Counter Horizontal Align
double left = (canvas.ActualWidth - startCounter.ActualWidth) / 2;
Canvas.SetLeft(startCounter, left);
Storyboard storyboard = new Storyboard();
DoubleAnimation opacityAnim = new DoubleAnimation();
DoubleAnimation fallAnim = new DoubleAnimation();
opacityAnim.From = 1;
opacityAnim.To = 0;
opacityAnim.Duration = new Duration(TimeSpan.FromSeconds(1));
opacityAnim.AutoReverse = false;
opacityAnim.RepeatBehavior = new RepeatBehavior(3);
Storyboard.SetTarget(opacityAnim, this.startCounter);
Storyboard.SetTargetProperty(opacityAnim, "(UIElement.Opacity)");
fallAnim.From = -115;
fallAnim.To = canvas.ActualHeight / 2;
fallAnim.Duration = new Duration(TimeSpan.FromSeconds(1));
fallAnim.AutoReverse = false;
fallAnim.RepeatBehavior = new RepeatBehavior(3);
Storyboard.SetTarget(fallAnim, this.startCounter);
Storyboard.SetTargetProperty(fallAnim, "(Canvas.Top)");
storyboard.Children.Add(opacityAnim);
storyboard.Children.Add(fallAnim);
storyboard.Begin();
}
//Countdown Timer
private void countDown()
{
timer = new DispatcherTimer();
timer.Tick += startCounter_CountDown;
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
//Change Countdown value
private void startCounter_CountDown(object sender, object e)
{
int counterNum = int.Parse(startCounter.Text);
counterNum -= 1;
startCounter.Text = counterNum.ToString();
if (counterNum == 1)
{
timer.Stop();
StartedGame();
}
}
//Tap or Click to start the game
private void TapToStart(object sender, TappedRoutedEventArgs e)
{
if(!isTapped)
{
isTapped = true;
counterAnimation();
countDown();
this.TapToStartText.Visibility = Visibility.Collapsed;
}
}
//Create rectangles
private void StartedGame()
{
rect = game.draw();
canvas.Children.Add(game.draw());
Debug.WriteLine(windowWidth.ToString());
}
}
}
One more thing: I get an error this line: PlayPage pg = new PlayPage();
Error (pic)
The error in your picture is due to infinite recursion, as it says. The constructor for Game instantiates a new PlayPage. The constructor for PlayPage instantiates a new Game. Which instantiates a new PlayPage. Which instantiates a new Game. and on and on.
Static members are accessed by class name, not by instance. Like so:
PlayPage.windowWidth
I've 4 panels, having same Y and different X, that are created at the program start on a picturebox. When I click on a panel, it sets the focus and is ready to get a keysDown event so i.e. if I click on up arrow key the panel moves up.
This is the code:
public partial class FormView : Form
{
List<CircleButton> myPanels = new List<CircleButton>(); // array of panels CircleButton
Point[] arrayPoints_milestones; // array of X,Y
int index;
public FormView()
{
InitializeComponent();
arrayPoints_milestones = new Point[4];
for (int i = 0; i < 4; i++ )
{
arrayPoints_milestones[i] = new Point { X = 20, Y = 20 };
}
test();
}
protected void panel_Click(object sender, EventArgs e)
{
myPanels[index].PreviewKeyDown -= new PreviewKeyDownEventHandler(panel_KeyDown);
CircleButton panel = sender as CircleButton;
index = (int)panel.Tag;
myPanels[index].Focus(); //panel.Focus();
myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}
private void panel_KeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y - 10);
MessageBox.Show("" + myPanels[index].Centre.Y);
Invalidate();
}
if (e.KeyCode == Keys.Down)
{
myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y + 10);
MessageBox.Show("" + myPanels[index].Centre.Y);
Invalidate();
}
}
private void test()
{
//for (int i = 0; i < 4; i++)
int i=0;
foreach(var value in arrayPoints_milestones)
{
CircleButton panel = new CircleButton();
panel.Tag = i;
panel.Centre = new Point(arrayPoints_milestones[i].X + i * 10, arrayPoints_milestones[i].Y);
panel.Radius = 10;
panel.BackColor = Color.Red;
panel.Message = "Index: " + panel.Tag.ToString();
myPanels.Add(panel); // qui aggiungo il pannello alla lista di pannelli myPanels
pictureBox1.Controls.Add(myPanels[i]);
myPanels[i].Click += new EventHandler(panel_Click);
i++;
}
}
}
and this is the custom panel class:
public class CircleButton : Panel
{
//Properties to draw circle
float radius;
public float Radius
{
get { return radius; }
set
{
radius = value;
this.Size = new Size((int)Radius, (int)Radius);
}
}
public string Name
{
get;
set;
}
Point centre;
public Point Centre
{
get { return centre; }
set
{
centre = value;
this.Location = Centre;
}
}
public string Message { get; set; }
public CircleButton()
{
//Default Values
Name = "panel_base";
this.BackColor = Color.Black;
Radius = 1;
Centre = new Point(0, 0);
this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//Defines a graphic path and set it as the panel's region
//For custom region use different path's
if (centre != null)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(0, 0, radius, radius);
this.Region = new Region(path);
path.Dispose();
}
}
}
Each time you click a panel, a PreviewKeyDownEventHandler is added - so 3 clicks will trigger 3 (different) eventhandlers with the same invocation target, and each will move your panel for 10 pixels up/down:
protected void panel_Click(object sender, EventArgs e) {
CircleButton panel = sender as CircleButton;
index = (int)panel.Tag;
myPanels[index].Focus(); //panel.Focus();
myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}
Updated code for FormView:
public partial class FormView : Form {
List<CircleButton> myPanels = new List<CircleButton>(); // local use only in my example
Point[] arrayPoints_milestones; //not needed anymore
int index; //not needed anymore
public FormView() {
InitializeComponent();
this.Load += FormView_Load;
}
void FormView_Load(object sender, EventArgs args) {
Point panelOffset = new Point(20, 20);
for (int i = 0; i < 4; i++) {
var panel = new CircleButton() {
Name = "panel" + i, //Attention! You have hidden the property "Name" in "Control" with a re-declaration in "CircleButton"
Tag = i, //not needed anymore, right?
Centre = new Point(panelOffset.X + i * 10, panelOffset.Y),
Radius = 10,
BackColor = Color.Red,
Message = "Index: " + i.ToString(),
};
panel.Click += (s, e) => {
panel.Focus();
};
panel.PreviewKeyDown += (s, e) => {
if(e.KeyCode == Keys.Up) {
Point centre = panel.Centre; //copy value
centre.Y -= 10;
panel.Centre = centre; //assign modified copy
Invalidate();
}
if(e.KeyCode == Keys.Down) {
Point centre = panel.Centre; //copy value
centre.Y += 10;
panel.Centre = centre; //assign modified copy
Invalidate();
}
};
myPanels.Add(panel);
pictureBox1.Controls.Add(panel);
}
}
}
I have worked on titanium in past and it was very simple to use the paging control there. Just begun Xamarin iOS development and got stuck with this paging control. Not sure how to use it. I found an example here. It worked fine. My question is ,is the UIPageControl Useless ? I read it here that it is so. Does Xamarin have any control which could work like Titanium's Scrollable View ? Please suggest any better method than the code below .
Here's the code
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
createAndAddViewsToPagerControl ();
}
void createAndAddViewsToPagerControl ()
{
try {
int pageCount = PagerControlMain.Pages;
Console.WriteLine ("Pages Count in Page Control" + pageCount);
List<UIColor> _colList = new List<UIColor> {
UIColor.Red,
UIColor.Green,
UIColor.Blue,
UIColor.Yellow
};
int i = 0;
for (i = 0; i < pageCount; i++) {
UILabel label = new UILabel ();
RectangleF rectangle = new RectangleF ();
rectangle.X = (this.PagerScrollView.Frame.Width * i) + 50;
rectangle.Y = 0;
rectangle.Size = this.PagerScrollView.Frame.Size;
label.Frame = rectangle;
label.Text = i.ToString ();
label.TextColor = _colList [i];
this.PagerScrollView.AddSubview (label);
}
this.PagerControlMain.Pages = pageCount;
PagerScrollView.BackgroundColor = UIColor.Gray;
PagerScrollView.ContentSize = new SizeF (PagerScrollView.Frame.Width * i, PagerScrollView.Frame.Height);
this.PagerScrollView.Scrolled += ScrolledEvent;
} catch (Exception ex) {
Console.WriteLine ("Exception in PagerControl : " + ex);
}
}
private void ScrolledEvent (object sender, EventArgs e)
{
this.PagerControlMain.CurrentPage =
(int)System.Math.Floor (this.PagerScrollView.ContentOffset.X
/ this.PagerScrollView.Frame.Size.Width);
Console.WriteLine ("Scroll Event Fired");
}
partial void PagerControlMain_ValueChanged (UIPageControl sender)
{
Console.WriteLine ("Current Page " + sender.CurrentPage);
//throw new NotImplementedException ();
}
Is this what you want?
Xamarin: UIPageControl and UIScrollView for iOS homescreen look
you should add this in your createAndAddViewsToPagerControl () method:
PagerScrollView.ScrollEnabled = true;
PagerScrollView.PagingEnabled = true;