add sub view if it doesn't exist - ios

on item click I add sub view (UIButton) to my supper view and want to remove it old one when user click again or just change title it isn't first click.
this is my custom renderer:
var text = new UIButton ();
protected override void OnElementChanged (ElementChangedEventArgs<Image> e)
{
base.OnElementChanged (e);
if (Control == null)
return;
if (this.Element != null) {
Original = (SpecLogoImage)this.Element;
}
TargetView = Control as UIImageView;
text.Layer.CornerRadius = 5;
text.Font = UIFont.FromName ("DIN Condensed", text.Font.PointSize);
text.TouchUpInside += delegate {
text.RemoveFromSuperview ();
};
var rec = new UILongPressGestureRecognizer (() => {
text.SetTitle(Original._hint, UIControlState.Normal);
text.TitleLabel.LineBreakMode = UILineBreakMode.WordWrap;
text.SizeToFit ();
text.Frame = new CGRect ((UIApplication.SharedApplication.KeyWindow.Frame.Width / 2.0f) - (250 / 2.0f),
this.Superview.Superview.Superview.Frame.Height / 2.0f, 250, text.Frame.Height);
if (text.Superview==null) {
Animate (0.6f, () => {
this.Superview.Superview.Superview.AddSubview (text);
}, () => {
text.Layer.ZPosition = int.MaxValue;
});
}
});
text.SetTitleColor (UIColor.White, UIControlState.Normal);
text.BackgroundColor = UIColor.Black;
TargetView.UserInteractionEnabled = true;
TargetView.AddGestureRecognizer (rec);
}
}
every time user click Superview is null, what is the problem ?

Related

I'm having problems zooming into images that are in rows of an UITableView in Xamarin.iOS

I have a tableView inside a tabView, and my rows in the tableView contain images. I would like to zoom into the said images (I put them inside a scrollView and set the max/min zoom and I set ViewForZoomingInScrollView), but it seems I can't get the zoom to trigger because they are small images 50x56 or some other gesture/event is interfeiring. I use the same zoom code on another part of my app and it works perfectly. Has anyone come across the same or similar problem or knows a possible solution?
EDIT:
protected DocumentBaseCell()
: base(UITableViewCellStyle.Default, new NSString("TableCell"))
{
...
documentImage = new UIImageView();
documentImage.Image = UIImage.FromBundle("LaunchImage");
documentImage.ContentMode = UIViewContentMode.ScaleAspectFit;
documentImage.Layer.ZPosition = 0;
imageScrollView = new UIScrollView();
imageScrollView.ClipsToBounds = false;
imageScrollView.ContentSize = new CGSize(50, 56);
imageScrollView.MaximumZoomScale = 8f;
imageScrollView.MinimumZoomScale = 1f;
imageScrollView.Add(documentImage);
imageScrollView.ViewForZoomingInScrollView += (UIScrollView sv) =>
{
imageScrollView.ContentSize = new CGSize(documentImage.Frame.Width, documentImage.Frame.Height);
return documentImage;
};
imageScrollView.DidZoom += (object sender, EventArgs e) =>
{
//(sender as UIView).Layer.ZPosition = 2000;
};
imageScrollView.ZoomingEnded += (object sender, ZoomingEndedEventArgs e) =>
{
(sender as UIScrollView).SetZoomScale(0f, true);
(sender as UIView).Layer.ZPosition = 0;
this.Layer.ZPosition = 0;
};
ContentView.Add(imageScrollView);
...
}
And this is the UpdateCell method:
internal virtual void UpdateCell(DocumentModel doc, string sup, string
docType, string user, string date, UIImage image)
{
if (image != null)
{
this.documentImage.Image = image;
}
...
}
The Frame is set aswell:
public override void LayoutSubviews()
{
base.LayoutSubviews();
imageScrollView.Frame = new CGRect(0, 2, 50, 56);
documentImage.Frame = new CGRect(0, 0, 50, 56);
}
I think you should give a frame to imageScrollView and documentImage, I download the official tableView sample project and add your code there, it zooms well.
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
imageScrollView.Frame = new CGRect(ContentView.Bounds.Width - 233, 5, 133, 133);
headingLabel.Frame = new CGRect(5, 4, ContentView.Bounds.Width - 63, 25);
subheadingLabel.Frame = new CGRect(100, 18, 100, 20);
imageView.Frame = imageScrollView.Bounds;
}
I uploaded a sample project here and you can check it.

App crashes after tap on UITextField in iOS

I created an app for iOS in VS with Xamarin. It works well both on iOS Simulator and real devices, but once I get a message from the user, that app crashes after a tap on UITextField. This is default iOS UITextField on the login screen. Strange, that this crash appears only on iPhone 6s with iOS v10.2.1. On iPhone with iOS >= v10.3 this crash doesn't appear.
This UITextField has only one event overriding
loginInput.EditingChanged += (s, e) =>
{
UITextField textInput = (UITextField)s;
if (textInput.Text.Length == 10)
{
textInput.ResignFirstResponder();
}
else if (textInput.Text.Length > 10)
{
char[] originalText = textInput.Text.ToCharArray();
char[] maskedText = new char[10];
for (int i = 0; i < 10; i++)
{
maskedText[i] = originalText[i];
}
textInput.Text = new string(maskedText);
textInput.ResignFirstResponder();
}
};
Also, I use UIKeyboard.Notifications.ObserveWillShow and UIKeyboard.Notifications.ObserveWillHide in ViewWillAppear overriding to translate the whole view depending on keyboard height. It's needed because otherwise, keyboard hides UITextField and user can't see, what he types.
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
UIKeyboard.Notifications.ObserveWillShow((s, e) =>
{
var r = UIKeyboard.FrameEndFromNotification(e.Notification);
keyboardHeight = r.Height;
_originalPosition = mainPageView.Center.Y;
if (keyboardHeight == 0)
{
keyboardHeight = r.Height;
}
Action keyboardShift = () => {
var xpos = mainPageView.Center.X;
var ypos = mainPageView.Center.Y - keyboardHeight;
mainPageView.Center = new CGPoint(xpos, ypos);
};
UIViewPropertyAnimator propertyAnimator = new UIViewPropertyAnimator(0.25, UIViewAnimationCurve.EaseInOut, keyboardShift);
propertyAnimator.StartAnimation();
});
UIKeyboard.Notifications.ObserveWillHide((s, e) =>
{
var r = UIKeyboard.FrameEndFromNotification(e.Notification);
keyboardHeight = r.Height;
if (keyboardHeight == 0)
{
keyboardHeight = r.Height;
}
Action keyboardUnShift = () => {
var xpos = mainPageView.Center.X;
var ypos = _originalPosition;
mainPageView.Center = new CGPoint(xpos, ypos);
};
UIViewPropertyAnimator propertyAnimator = new UIViewPropertyAnimator(0.25, UIViewAnimationCurve.EaseInOut, keyboardUnShift);
propertyAnimator.StartAnimation();
});
}
Hope somebody help me with this.

How to draw rectangle when form is resized

enter code hereI'm using OpenCv and displaying frames which i get from video file on the imagebox. Now I'm drawing multiple rectangles on the frame and trying to move and delete them. This is working fine. But, when i'm resizing the form...i can't draw,move or delete the rectangles at the correct position as the frame coordinates are not getting changed but only imagebox coordinates are being changed and the frame is fitted into it.Please help me out.
black rectangle is where i have drawn the rectangle after form is resized...red rectangle is where the rectangle is being drawn
private void imageBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
drawRect = true;
RectStartpt = e.Location;
if (count > 0)
{
foreach (Rectangle allRect in Rect_List)
{
rect_count++;
if (allRect.Contains(e.Location))
{
Cursor cursor = Cursors.Cross;
drawRect = false;
RectStartpt = new Point(e.X, e.Y);
rect = allRect;
break;
}
}
}
}this.Invalidate();}
private void imageBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left && e.Button != MouseButtons.Right)
{
return;
}
else if (e.Button == MouseButtons.Left)
{
Point EndPt = new Point(e.X, e.Y);
Size shift = new Size(Math.Abs(RectStartpt.X - EndPt.X), Math.Abs(RectStartpt.Y - EndPt.Y));
if (drawRect == true)
{
rect.Location = new Point(Math.Min(RectStartpt.X, EndPt.X), Math.Min(RectStartpt.Y, EndPt.Y));
rect.Size = shift;
count = 1;
}
else if (drawRect == false)
{
rect.X += e.X - RectStartpt.X;
rect.Y += e.Y - RectStartpt.Y;
RectStartpt = new Point(e.X, e.Y);
}
}
}
private void imageBox1_MouseUp(object sender, MouseEventArgs e)
{
if (frame != null)
{
if (drawRect == true)
{
frame.Draw(rect, new Bgr(Color.Red), 2);
Rect_List.Add(rect);
}
else if (drawRect == false)
{
frame.Draw(rect, new Bgr(Color.Red), 2);
Rect_List.RemoveAt(rect_count - 1);
Rect_List.Add(rect);
if (Timer_enabled == false)
{
frame = captureFrame.QueryFrame().ToImage<Bgr, Byte>();
foreach (Rectangle allRect in Rect_List)
{
frame.Draw(allRect, new Bgr(Color.Red), 2);
}
imageBox1.Image = frame;
imageBox1.Refresh();
rect = new Rectangle();
frame_no++;
}
}
imageBox1.Image = frame;
imageBox1.Refresh();
//rect = new Rectangle();
rect_count = 0;
}
}
private void Form1_Resize(object sender, EventArgs e)
{
formGraphics = null;
formGraphics = imageBox1.CreateGraphics();
frame = frame.Resize(imageBox1.Width, imageBox1.Height, Inter.Linear);
imageBox1.Image = frame;
}

How do I remove gesture recogniser from a label in a UITableViewCell?

I've bottom toolbar in my ViewController and a TableView above it. The toolbar has a date label in the middle, and next and previous buttons on the left and right. based on the selected date tableview content changes..
Now TableViewCell contains a UILabel. I want to add Gesture to the label only if the selected day is today.
So I wrote in my cell update method
UITapGestureRecognizer gesture = new UITapGestureRecognizer();
gesture.AddTarget(() => HandleValueLabelClick());
if (source.parentController.selectedDateTime.Day == DateTime.Now.Day)
{
AddEditAction();
ValueLabel.AddGestureRecognizer(gesture);
}
else
{
ValueLabel.RemoveGestureRecognizer(gesture);
}
But the gesture remove if the selected date is not today, is not working. Any help is appreciated..
Edit:
public partial class ProgramCalendarCell : UITableViewCell
{
NSIndexPath indexPath;
ProgramVitalsCalendarTableSource source;
ProgramVital vital;
ProgramVitalCalendar calendar;
public ProgramCalendarCell (IntPtr handle) : base (handle)
{
}
public void UpdateCell(ProgramVital vital, ProgramVitalCalendar calendar, NSIndexPath indexPath, ProgramVitalsCalendarTableSource source)
{
this.source = source;
this.indexPath = indexPath;
this.vital = vital;
this.calendar = calendar;
InitVitalName();
InitVitalValue();
NewValueTextField.Hidden = true;
ValueLabel.Hidden = false;
UIView separatorLine = new UIView(new CoreGraphics.CGRect(0, 44, 1200f, 0.5f));
separatorLine.BackgroundColor = AZConstants.SeparatorColor;
ContentView.AddSubview(separatorLine);
UITapGestureRecognizer gesture = new UITapGestureRecognizer();
gesture.AddTarget(() => HandleValueLabelClick());
if (source.parentController.selectedDateTime.Day == DateTime.Now.Day)
{
AddEditAction();
ValueLabel.AddGestureRecognizer(gesture);
}
else
{
ValueLabel.RemoveGestureRecognizer(gesture);
}
}
void InitVitalName()
{
string name = vital.vitalName;
if (!String.IsNullOrEmpty(vital.unitName))
name += " (" + System.Net.WebUtility.HtmlDecode(vital.unitName) + ")";
VitalNameLabel.Text = name;
}
void InitVitalValue()
{
string value = "";
string color = "";
if (calendar != null)
{
value = calendar.values[0].value;
color = calendar.values[0].color;
}
UIHelper.SetVitalValueTileBackGround(ValueLabel, value, color);
}
void HandleValueLabelClick()
{
ValueLabel.Hidden = true;
NewValueTextField.Hidden = false;
NewValueTextField.BecomeFirstResponder();
}
void AddEditAction()
{
ValueLabel.UserInteractionEnabled = true;
NewValueTextField.ShouldReturn = (textField) =>
{
textField.ResignFirstResponder();
ValueLabel.Hidden = false;
NewValueTextField.Hidden = true;
Console.WriteLine("Row: " + indexPath.Row);
return true;
};
UIToolbar toolbar = new UIToolbar(new RectangleF(0.0f, 0.0f, (float)UIScreen.MainScreen.Bounds.Size.Width, 44.0f));
toolbar.BarTintColor = AZConstants.PrimaryColor;
toolbar.TintColor = UIColor.White;
toolbar.Items = new UIBarButtonItem[]{
new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace),
new UIBarButtonItem(UIBarButtonSystemItem.Done, delegate {
Console.WriteLine("Row: " + indexPath.Row);
SaveReading();
NewValueTextField.ResignFirstResponder();
})
};
toolbar.BarTintColor = AZConstants.PrimaryColor;
toolbar.TintColor = UIColor.White;
toolbar.Translucent = true;
toolbar.SizeToFit();
NewValueTextField.InputAccessoryView = toolbar;
int vId = Int32.Parse(vital.vitalId);
if (vId == 20 || vId == 5 || vId == 496)
NewValueTextField.KeyboardType = UIKeyboardType.DecimalPad;
else
NewValueTextField.KeyboardType = UIKeyboardType.NumberPad;
}
async void SaveReading()
{
var hud = UIHelper.GetProgressHud(source.parentController.View, "");
hud.Show(animated: true);
Status status = await VitalHelper.postVitalValue(Constants.__IOS__, vital, NewValueTextField.Text, 0,
DateTime.Now.ToString("MM/dd/yyyy"), DateTime.Now.ToString("hh:mm tt"), "");
if (status.status)
{
source.parentController.FetchAndDisplayVitalValues();
}
else
{
new UIAlertView("Error", status.message, null, "OK", null).Show();
}
hud.Hide(animated: true, delay: 0);
}
}
It doesn't work 'cause you are removing a newly created gesture, not the gesture it already may have.
You must retrive the gestures array with ValueLabel.gestureRecognizers then remove each one with a for loop.

AS2: don't perform rollout until motion finished

I have an mc with some tweens applied to it, but if you roll out before they are done they break. I don't want to disable the button while tweens are running because if you roll out while they run you confuse the user because nothing happens and you get stuck in that frame.
What I want is to acknowledge the rollout during the tween (or after) but not run until the tweens are finished. I cannot seem to access the onmotionfinished of the tween in the rollover function from the rollout function however.
Any ideas?
If it helps here is my rollover:
buttons[i].onRollOver = function() {
var oppX:Number = Stage.width-this._x;
var oppY:Number = Stage.height-this._y;
if (oppX-209.8<=20) {
var difference:Number = Math.abs(20-(oppX-209.8));
oppX += difference;
} else if (oppX+209.8>=780) {
var difference:Number = Math.abs(780-(oppX+209.8));
oppX -= difference;
}
if (oppY-172.1<=20) {
var difference:Number = Math.abs(20-(oppY-172.1));
oppY += difference;
} else if (oppY+172.1>=580) {
var difference:Number = Math.abs(580-(oppY+172.1));
oppY -= difference;
}
var TweenX:Tween = new Tween(circle, "_x", mx.transitions.easing.Strong.easeOut, circle._x, oppX, 1, true);
var TweenY:Tween = new Tween(circle, "_y", mx.transitions.easing.Strong.easeOut, circle._y, oppY, 1, true);
circle.gotoAndPlay("out");
myColor = new Color(this);
myColor.setTint(153,255,0,30);
for (MovieClip in buttons) {
delete buttons[MovieClip].onEnterFrame;
if (buttons[MovieClip] != this) {
buttons[MovieClip].enabled = false;
myColor = new Color(buttons[MovieClip]);
myColor.setTint(255,255,255,80);
myColor = new Color(buttons[MovieClip]._line);
myColor.setTint(255,255,255,80);
}
}
};
and my rollOut:
buttons[i].onRollOut = function() {
this.onMotionComplete = function() {
var TweenX:Tween = new Tween(circle, "_x", mx.transitions.easing.Strong.easeOut, circle._x, 400, 0.5, true);
var TweenY:Tween = new Tween(circle, "_y", mx.transitions.easing.Strong.easeOut, circle._y, 300, 0.5, true);
TweenY.onMotionFinished = function() {
for (MovieClip in buttons) {
buttons[MovieClip].enabled = true;
}
};
this._parent.circle.gotoAndPlay("in");
for (MovieClip in buttons) {
buttons[MovieClip].onEnterFrame = function() {
moveButtons(this);
controlButtons(this);
};
myColor = new Color(buttons[MovieClip]);
myColor.setTint(255,255,255,0);
}
};
Realised that it wasn't the tween causing most of the problems that it was the gotoandplay because i had my stop(); calls on the same frame as the markers on that movieclip causing them to get stuck.
Did have some trouble with tween (the rollout jumped back to the rollover position if its tweens were called mid tween) but I decided to push the tweens to an array making them globally accessible and purge the array onmotionfinished then in the rollout check to see if the array contains anything and if so kill off the old tweens first.
Final product:
buttons[i].onRollOver = function() {
circle.active = this;
var oppX:Number = Stage.width-this._x;
var oppY:Number = Stage.height-this._y;
if (oppX-209.8<=20) {
var difference:Number = Math.abs(20-(oppX-209.8));
oppX += difference;
} else if (oppX+209.8>=780) {
var difference:Number = Math.abs(780-(oppX+209.8));
oppX -= difference;
}
if (oppY-172.1<=20) {
var difference:Number = Math.abs(20-(oppY-172.1));
oppY += difference;
} else if (oppY+172.1>=580) {
var difference:Number = Math.abs(580-(oppY+172.1));
oppY -= difference;
}
var TweenX:Tween = new Tween(circle, "_x", mx.transitions.easing.Strong.easeOut, circle._x, oppX, 1, true);
var TweenY:Tween = new Tween(circle, "_y", mx.transitions.easing.Strong.easeOut, circle._y, oppY, 1, true);
TweenY.onMotionFinished = function () {
tweens.length = 0;
}
tweens.push(TweenX,TweenY);
circle.gotoAndPlay("out");
myColor = new Color(this);
myColor.setTint(153,255,0,30);
for (MovieClip in buttons) {
delete buttons[MovieClip].onEnterFrame;
if (buttons[MovieClip] != this) {
buttons[MovieClip].enabled = false;
myColor = new Color(buttons[MovieClip]);
myColor.setTint(255,255,255,80);
myColor = new Color(buttons[MovieClip]._line);
myColor.setTint(255,255,255,80);
}
}
};
buttons[i].onRollOut = function() {
if (tweens.length != 0) {
tweens[0].stop();
tweens[1].stop();
delete tweens[0];
delete tweens[1];
tweens.length = 0;
}
circle.gotoAndPlay("in");
var TweenX:Tween = new Tween(circle, "_x", mx.transitions.easing.Strong.easeOut, circle._x, 400, 0.5, true);
var TweenY:Tween = new Tween(circle, "_y", mx.transitions.easing.Strong.easeOut, circle._y, 300, 0.5, true);
TweenY.onMotionFinished = function() {
circle._x = 400;
circle._y = 300;
for (MovieClip in buttons) {
buttons[MovieClip].enabled = true;
}
};
for (MovieClip in buttons) {
buttons[MovieClip].onEnterFrame = function() {
moveButtons(this);
controlButtons(this);
};
myColor = new Color(buttons[MovieClip]);
myColor.setTint(255,255,255,0);
}
};

Resources