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 :(
Related
I'm in the process of porting my Xamarin.Android app to Xamarin.iOS, I can't make my progress bar update, where am I going wrong?
The values are set in updateProgressBar() correctly and progressBarValue in this example is set as 0.25 as expected, but the UIProgressView is not updated on the screen. progressBar is a UIProgressView on the storyboard.
public BackgroundWorker backgroundWorker { get; private set; }
private float progressBarValue { get; set; }
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
startBackgroundWorker();
}
private void startBackgroundWorker()
{
if (backgroundWorker == null || backgroundWorker.CancellationPending) backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s, e) =>
{
//do stuff
backgroundWorker.ReportProgress(25);
//do stuff
};
backgroundWorker.RunWorkerCompleted += (s, e) => { //do stuff };
backgroundWorker.ProgressChanged += (s, e) => { updateProgressBar(e.ProgressPercentage); };
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.RunWorkerAsync();
}
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
progressBar.Progress = progressBarValue;
}
}
I also tried using SetProgress(progressBarValue,true)
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
progressBar.SetProgress(progressBarValue,true);
}
}
and using InvokeOnMainThread
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
InvokeOnMainThread ( () => {
// manipulate UI controls
progressBar.SetProgress(progressBarValue,true);
});
}
}
you need to be sure your UI updates are running on the main thread
InvokeOnMainThread ( () => {
// manipulate UI controls
progressBar.SetProgress(progressBarValue,true);
});
As is often the case, my problem was not related to my code in the question, or the question at all, I copied it into a new solution and it worked fine.
Incase anyone finds this in the future and has made the same mistake:
My problem was that I had set UIProgressView.TintColor to an invalid value elsewhere in my code so the ProgressView was updating all along but it just wasn't visible.
progressView.TintColor = iOSHelpers.GetColor(GenericHelpers.colorPrimaryGreenRGBA);
iOSHelpers
public static UIColor GetColor(int[] rgba)
{
if (rgba.Length == 4)
return UIColor.FromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
else return UIColor.Black;
}
GenericHelpers
public static int[] colorPrimaryGreenRGBA = { 140, 185, 50, 1 };
Once I had changed thecolorPrimaryGreenRGBA values to floats and divided the RGB channels by 255 in the GetColor method it was then a visible color.
Hiiho! I am developing a dashboard view using Xamarin.Forms.
Now I want to allow a user to drag and drop my icons to rearrange my Grid. But for some reason I get no visual representation of the drag event on UWP. The "DragStarted" event those fire tho. Here is my code
This is my custom renderer in UWP.
[assembly: ExportRenderer(typeof(DashboardIcon), typeof(DashboardIconRenderer))]
namespace Paraply.Droid.Custom_Renderers
{
class DashboardIconRenderer : ViewRenderer<DashboardIcon, Windows.UI.Xaml.FrameworkElement>
{
public DashboardIconRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<DashboardIcon> e)
{
base.OnElementChanged(e);
if (this == null)
return;
this.CanDrag = true;
this.DragStarting += OnDragStarting;
//this.Holding += HandleHoldEvent;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
this.CanDrag = true;
}
private void OnDragStarting(object sender, DragStartingEventArgs e)
{
//This fires
}
}
My contentpage in Xamarin.Forms, or its the funciton that fills my Grid
public void InflateServices(IList<InstalledServiceModel> services)
{
int count = 0;
serviceBoard.Children.Clear();
foreach (InstalledServiceModel service in services)
{
DashboardIcon icon = new DashboardIcon(service.Name, service.IconURL, service.Id);
var p = new TapGestureRecognizer();
p.CommandParameter = icon;
p.SetBinding(TapGestureRecognizer.CommandProperty, "IconClick");
icon.GestureRecognizers.Add(p);
icon.Holding += HandleHoldEvent;
serviceBoard.Children.Add(icon, count % 3, count / 3);
count++;
}
}
Now every DashboardIcon is a class that derives from Grid. It looks like this
public class DashboardIcon : Grid
{
//public event EventHandler<DashboardHoldingEventArgs> Holding;
//public void OnHolding(DashboardHoldingEventArgs e) { Holding(this, e); }
public DashboardIcon(string title, string url, int id = -1)
{
Title = title;
URL = url;
ServiceId = id;
/*
UI design
*/
HorizontalOptions = LayoutOptions.FillAndExpand;
VerticalOptions = LayoutOptions.FillAndExpand;
RowDefinitions.Add(new RowDefinition() { Height = new GridLength(0.6, GridUnitType.Star) });
RowDefinitions.Add(new RowDefinition() { Height = new GridLength(0.4, GridUnitType.Star) });
image = new Image()
{
Source = url,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Aspect = Aspect.AspectFit
};
text = new Label()
{
Text = title,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Color.Black
};
Children.Add(image, 0, 0);
Children.Add(text, 0, 1);
}
Now my OnDragStarting function does fire just fine. But for some reason I get no visual representation of the view I'm dragging, I was expecting the view to follow my finger until I drop it?
In OnDragStarting you can set e.DragUI.SetContentFromBitmap() for example. There you can specify what you want to see while dragging (the image probably). Also here you could set this.Opacity = 0.2; so it gets transparent or invisible.
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.
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;
The content inside the child window changes, which causes my child window to lose it's center alignment.... After the content has changed is there anyway to reposition the child window to center... I tried the following and it did not work:
this.horizontalalignment = horizontalalignment.center;
this.verticalalignment = verticalalignment.center;
Thanks
The presence of a RenderTransform on the ChildWindow template seems to be to blame. The TransformGroup is part of the default template to allow you to move around the window.
Here is a hack to reset the transform after you change the layout:
//after you do some change to the childwindow layout
sp.Children.Add(new Button() { Content = "a" });
Dispatcher.BeginInvoke(() =>
{
//reset the transform to zero
(this.GetTemplateChild("ContentRoot") as Grid).RenderTransform = new TransformGroup()
{
Children = { new ScaleTransform(), new SkewTransform(), new RotateTransform(), new TranslateTransform() }
};
});
or more automatically:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var contentRoot = this.GetTemplateChild("ContentRoot") as FrameworkElement;
contentRoot.LayoutUpdated += contentRoot_LayoutUpdated;
}
void contentRoot_LayoutUpdated(object sender, EventArgs e)
{
var contentRoot = this.GetTemplateChild("ContentRoot") as FrameworkElement;
var tg = contentRoot.RenderTransform as TransformGroup;
var tts = tg.Children.OfType<TranslateTransform>();
foreach (var t in tts)
{
t.X = 0; t.Y = 0;
}
}
LayoutUpdated gets called often, so you may want to check if contentRoot.ActualWidth and ActualHeight changed to see if you really need to wipe out the transform.
Code
public partial class DialogOptions : ChildWindow
{
public DialogOptions()
{
InitializeComponent();
Loaded += (sender, args) =>
{
VerticalAlignment = VerticalAlignment.Top;
this.SetWindowPosition(new Point(0, 200));
};
}
}
And extention:
public static void SetWindowPosition(this ChildWindow childWindow, Point point)
{
var root = VisualTreeHelper.GetChild(childWindow, 0) as FrameworkElement;
if (root == null)
{
return;
}
var contentRoot = root.FindName("ContentRoot") as FrameworkElement;
if (contentRoot == null)
{
return;
}
var group = contentRoot.RenderTransform as TransformGroup;
if (group == null)
{
return;
}
TranslateTransform translateTransform = null;
foreach (var transform in group.Children.OfType<TranslateTransform>())
{
translateTransform = transform;
}
if (translateTransform == null)
{
return;
}
translateTransform.X = point.X;
translateTransform.Y = point.Y;
}