As we can see on the bottom of the screen, there are options to be chosen.
Which other options are there for this menu such that I can display longer strings fully?
For your requirement you have to make a customize one to do it:
Try to use this code:
using System;
using System.Collections.Generic;
using CoreGraphics;
using UIKit;
namespace CusActionSheet
{
public delegate void OneParameterEventHandler<T>(T data);
public class ALActionSheet : UIView
{
private nfloat maximumProportion = 0.8f;
public event OneParameterEventHandler<string> RowClicked;
//You also can use this if you don't know the generic(but remeber also change it for source):
//public delegate void OneParameterEventHandler(string data);
//public event OneParameterEventHandler SelectedPhoneNumber;
private UIView backgroundContainer;
private UIView topContainer;
private UILabel topContainerTitleView;
private UITableView topContainerTable;
private ALActionSheetSource topContainerTableSource;
private UIButton btnCancel;
private nfloat itemPadding = 10;
private nfloat itemHeight = 60;
private nfloat cornerRadius = 10;
private List<string> dataList;
private CGRect backContainerShownFrame;
private CGRect backContainerHiddenFrame;
private string selectedNumber;
public CGRect BackContainerShownFrame
{
get
{
return backContainerShownFrame;
}
set
{
backContainerShownFrame = value;
}
}
public ALActionSheet(List<string> _dataList)
{
this.BackgroundColor = UIColor.Clear;
this.dataList = _dataList;
backgroundContainer = new UIView();
backgroundContainer.Layer.CornerRadius = cornerRadius;
backgroundContainer.Layer.MasksToBounds = true;
topContainer = new UIView();
topContainer.BackgroundColor = UIColor.White;
topContainer.Layer.CornerRadius = cornerRadius;
topContainer.Layer.MasksToBounds = true;
topContainerTitleView = new UILabel();
topContainerTitleView.Text = "Select a number";
topContainerTitleView.TextAlignment = UITextAlignment.Center;
topContainerTitleView.BackgroundColor = UIColor.FromRGB(230, 230, 230);
topContainer.AddSubview(topContainerTitleView);
topContainerTableSource = new ALActionSheetSource(dataList);
topContainerTableSource.RowClicked += (data) =>
{
selectedNumber = data;
Close();
};
topContainerTable = new UITableView();
topContainerTable.RowHeight = itemHeight;
topContainerTable.Layer.CornerRadius = cornerRadius;
topContainerTable.Layer.MasksToBounds = true;
topContainerTable.BackgroundColor = UIColor.White;
topContainerTable.Source = topContainerTableSource;
topContainer.AddSubview(topContainerTable);
btnCancel = new UIButton(UIButtonType.System);
btnCancel.SetTitle("Cancel", UIControlState.Normal);
btnCancel.TitleLabel.Font = UIFont.SystemFontOfSize(18);
btnCancel.BackgroundColor = UIColor.White;
btnCancel.Layer.CornerRadius = cornerRadius;
btnCancel.Layer.MasksToBounds = true;
btnCancel.TouchUpInside += delegate
{
Close();
};
backgroundContainer.AddSubview(topContainer);
backgroundContainer.AddSubview(btnCancel);
Layout();
}
public void Layout()
{
this.Frame = UIScreen.MainScreen.Bounds;
nfloat tableMaxHeight = UIScreen.MainScreen.Bounds.Height * maximumProportion - 2 * itemPadding - 2 * itemHeight;
nfloat tableHeight = dataList.Count * itemHeight < tableMaxHeight ? dataList.Count * itemHeight : tableMaxHeight;
nfloat itemWidth = UIScreen.MainScreen.Bounds.Width - 2 * itemPadding;
nfloat backgroundContainerHeight = tableHeight + 2 * itemHeight + itemPadding;
backgroundContainer.Frame = new CGRect(0, 0, itemWidth, backgroundContainerHeight);
nfloat topContainerHeight = itemHeight + tableHeight;
topContainer.Frame = new CGRect(0, 0, itemWidth, topContainerHeight);
topContainerTitleView.Frame = new CGRect(0, 0, itemWidth, itemHeight);
topContainerTable.Frame = new CGRect(0, itemHeight, itemWidth, tableHeight);
btnCancel.Frame = new CGRect(0, topContainerHeight + itemPadding, itemWidth, itemHeight);
BackContainerShownFrame = new CGRect(new CGPoint(itemPadding, UIScreen.MainScreen.Bounds.Height - backgroundContainerHeight - itemPadding), backgroundContainer.Bounds.Size);
backContainerHiddenFrame = new CGRect(new CGPoint(itemPadding, UIScreen.MainScreen.Bounds.Height + itemPadding), backgroundContainer.Bounds.Size);
}
public void Show()
{
UIApplication.SharedApplication.KeyWindow.AddSubview(this);
backgroundContainer.Frame = backContainerHiddenFrame;
this.AddSubview(backgroundContainer);
UIView.Animate(0.3, delegate
{
this.BackgroundColor = UIColor.FromRGBA(0, 0, 0, 0.5f);
backgroundContainer.Frame = BackContainerShownFrame;
});
}
public void Close()
{
UIView.Animate(0.3, delegate
{
backgroundContainer.Frame = backContainerHiddenFrame;
this.BackgroundColor = UIColor.Clear;
}, delegate
{
this.RemoveFromSuperview();
if (null != RowClicked && null != selectedNumber)
RowClicked(selectedNumber);
});
}
}
class ALActionSheetSource : UITableViewSource
{
public event OneParameterEventHandler<string> RowClicked;
private string cellID = "ALActionSheetCell";
private List<string> dataList;
public ALActionSheetSource(List<string> _dataList)
{
dataList = _dataList;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return dataList.Count;
}
public override UITableViewCell GetCell(UITableView tableView, Foundation.NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(cellID);
if (null == cell)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, cellID);
cell.TextLabel.TextAlignment = UITextAlignment.Center;
//cell.TextLabel.AdjustsFontSizeToFitWidth = true;//Auto resize by content
cell.TextLabel.Lines = int.MaxValue;//Multiple lines
}
cell.TextLabel.Text = dataList[indexPath.Row];
return cell;
}
public override void RowSelected(UITableView tableView, Foundation.NSIndexPath indexPath)
{
if (null != RowClicked)
RowClicked(dataList[indexPath.Row]);
}
}
}
And invoke it like this:
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
List<string> testList = new List<string>();
for (int i = 0; i < 10; i++) {
testList.Add("Item " + i.ToString());
}
testList.Add("I'm a very very very very very very very very long text.");
ALActionSheet actionSheet = new ALActionSheet(testList);
actionSheet.RowClicked += (data) => {
Console.WriteLine("data = "+data);
};
UIButton btnTest = new UIButton(UIButtonType.System);
btnTest.SetTitle("Test", UIControlState.Normal);
btnTest.Frame = new CoreGraphics.CGRect(50, 50, 80, 30);
btnTest.TouchUpInside += delegate {
actionSheet.Show();
};
this.Add(btnTest);
}
Hope it can help you.
Related
I'm working on a Xamarin iOS project and have a view with a MapView that contains modified MKAnnotations and implements IMKMapViewDelegate.
The view shows a map with a few annotations on the map. Tapping an annotation displays a callout bubble with extra info.
The view also has an overlay view at the bottom of the screen which can be swiped up to display detailed info. The problem is that when an annotation is selected or deselected, the overlay view moves half way up the screen. The annotation selection event calls the methods DidSelectAnnotationView/DidDeselectAnnotationView but the movement of the overlay is triggered after those calls and I cannot hit any break points in any of my code when this event occurs.
So the question is, which iOS methods get called after DidSelectAnnotationView and DidDeselectAnnotationView which could be causing my issue?
The code below reverts the overlay back to its original position but with an obvious UI glitch.
[Export("mapView:didSelectAnnotationView:")]
public void DidSelectAnnotationView(MKMapView mapView, MKAnnotationView annotationView)
{
DelayedOverlayReset();
}
[Export("mapView:didDeselectAnnotationView:")]
public void DidDeselectAnnotationView(MKMapView mapView, MKAnnotationView annotationView)
{
DelayedOverlayReset();
}
private async Task DelayedOverlayReset()
{
await Task.Run(async () =>
{
Thread.Sleep(150);
});
_overlayView?.SetUpOverlayMinPosition();
}
I can share more code but its work related so I need to anonymise it. Happy to provide further detail or answer questions as necessary.
EDIT overlay view:
namespace Touch.Views.Detail
{
[Register("DetailsOverlayView")]
public sealed class DetailsOverlayView : UIView
{
private const float OverlayDragBarWidth = 56.0f;
private const float OverlayDragBarTopPadding = 20.0f;
private const float OverlayDragBarHeight = 6.0f;
private const float OverlayDragBarBottomPadding = 18.0f;
private const float CornerRadius = 18.0f;
private const float ScoreImageWidth = 60.0f;
private const float IconImageWidth = 16.0f;
private const float ShadowOpacity = 0.15f;
private const float ShadowRadius = 10.0f;
private const float ShadowOffsetWidth = 0f;
private const float ShadowOffsetHeight = 10.0f;
private const float ViewAnchorMidPoint = 0.5f;
private const float ImageDurationToLabelGap = 30;
private const float AddressIconWidthAndPadding = 18.0f;
private const double StartingOverlayAnimationSpeed = 0.3;
private const double AnimationSpeedThreshold = 1.3;
private const string DistanceImageName = "icon_map";
private const string DurationImageName = "icon_clock";
private static readonly TextStyle Heading3SemiBold = TextStyle.Heading3.SemiBold.BrandSecondary;
private static readonly TextStyle BodyRegularCaption = TextStyle.Body.Regular.TextCaption;
private readonly DetailOverlayDisplayData? _displayData;
private readonly double _maxPosition;
private readonly double _minPosition;
private readonly UIView? _parentView;
private readonly ElementLinksViewModel? _ActionViewModel;
private NSLayoutConstraint? _dragBarBottomPadding;
private UIView? _overlayDragBarView;
private UIView? _overlayHeaderAndContentView;
private UIPanGestureRecognizer? _panGestureRecognizer;
private UIScrollView? _scrollView;
private UIStackView? _stackView;
private double _startingPosition;
public NSLayoutConstraint? OverlayHeight;
public DetailsOverlayView(DetailOverlayDisplayData displayData, ElementLinksViewModel action,
UIView parentView)
{
_parentView = parentView;
_displayData = displayData;
_ActionViewModel = action;
TranslatesAutoresizingMaskIntoConstraints = false;
BackgroundColor = UIColor.White;
ClipsToBounds = false;
Layer.CornerRadius = CornerRadius;
Hidden = true;
Layer.ShadowOpacity = ShadowOpacity;
Layer.ShadowOffset = new CGSize(ShadowOffsetWidth, -ShadowOffsetHeight);
Layer.ShadowRadius = ShadowRadius;
SetUp();
var headerView = new DetailHeaderView();
headerView.SetUp(displayData, _scrollView!, _stackView!, parentView);
CreateContentPanel();
SetUpOverlayConstraints();
_minPosition = Math.Round(parentView.Frame.Height - GetHeaderHeight(displayData, parentView.Bounds.Width));
_maxPosition = 0;
}
public void SetUpOverlayStartingPosition()
{
if (_parentView == null)
{
return;
}
Center = new CGPoint(Center.X, _parentView.Frame.Height);
Layer.AnchorPoint = new CGPoint(ViewAnchorMidPoint, 0f);
Hidden = false;
SetOverlayPosition(StartingOverlayAnimationSpeed, _minPosition, CornerRadius, true);
_overlayDragBarView!.Hidden = false;
}
public void SetUpOverlayMinPosition()
{
SetOverlayPosition(0.01, _minPosition, CornerRadius, true);
_overlayDragBarView!.Hidden = false;
}
private void SetUp()
{
_overlayDragBarView = new UIView
{
TranslatesAutoresizingMaskIntoConstraints = false,
BackgroundColor = UIColor.LightGray,
ClipsToBounds = true
};
_overlayDragBarView.RoundCorners(ViewCornerStyle.All, OverlayDragBarHeight / 2);
_overlayHeaderAndContentView = new UIView
{
TranslatesAutoresizingMaskIntoConstraints = false,
ClipsToBounds = true
};
AddSubview(_overlayDragBarView);
AddSubview(_overlayHeaderAndContentView);
_panGestureRecognizer = new UIPanGestureRecognizer(PanOverlayView);
_panGestureRecognizer.CancelsTouchesInView = true;
AddGestureRecognizer(_panGestureRecognizer);
var (outerScrollView, _, innerStackView) =
_overlayHeaderAndContentView!.CreateScrollViewWithFooterAndStackView(UIColor.White);
_stackView = innerStackView;
_stackView.LayoutMarginsRelativeArrangement = true;
_scrollView = outerScrollView;
_scrollView.UserInteractionEnabled = false;
_scrollView.Bounces = true;
_scrollView.SetContentOffset(CGPoint.Empty, true);
_scrollView.Scrolled += ScrollViewOnScrolled;
}
private void CreateContentPanel()
{
var view = new UIView
{
TranslatesAutoresizingMaskIntoConstraints = false,
BackgroundColor = UIColor.Clear,
ClipsToBounds = true
};
var contentStackView = new UIStackView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Axis = UILayoutConstraintAxis.Vertical,
LayoutMarginsRelativeArrangement = true,
Spacing = StyleGuideDimens.PaddingSmall,
DirectionalLayoutMargins =
new NSDirectionalEdgeInsets(0, StyleGuideDimens.PaddingSmall, StyleGuideDimens.PaddingSmall,
StyleGuideDimens.PaddingSmall)
};
_stackView!.AddArrangedSubview(view);
view.AddSubview(contentStackView);
NSLayoutConstraint.ActivateConstraints(new[]
{
view.LeadingAnchor.ConstraintEqualTo(view.Superview.LeadingAnchor),
view.TrailingAnchor.ConstraintEqualTo(view.Superview.TrailingAnchor),
contentStackView.TopAnchor.ConstraintEqualTo(view.TopAnchor),
contentStackView.BottomAnchor.ConstraintEqualTo(view.BottomAnchor),
contentStackView.LeadingAnchor.ConstraintEqualTo(view.LeadingAnchor),
contentStackView.TrailingAnchor.ConstraintEqualTo(view.TrailingAnchor)
});
var milesTimePanel = SetUpDistanceAndDurationLayout();
var ActionView = ElementLinksView.Create();
_ActionViewModel!.Alignment = Alignment.Center;
ActionView.SetUp(_ActionViewModel);
var scoreSummaryView = new ScoreSummaryView();
scoreSummaryView.SetUp(_displayData!.ScoreSummary);
contentStackView.AddArrangedSubview(milesTimePanel);
contentStackView.AddArrangedSubview(ActionView);
contentStackView.AddArrangedSubview(scoreSummaryView);
contentStackView.SetCustomSpacing(StyleGuideDimens.PaddingMedium, milesTimePanel);
milesTimePanel.LayoutIfNeeded();
view.LayoutIfNeeded();
_stackView.LayoutIfNeeded();
}
private void SetUpOverlayConstraints()
{
NSLayoutConstraint.ActivateConstraints(new[]
{
_overlayDragBarView!.CenterXAnchor.ConstraintEqualTo(CenterXAnchor),
_overlayDragBarView.TopAnchor.ConstraintEqualTo(TopAnchor, OverlayDragBarTopPadding),
_overlayDragBarView.WidthAnchor.ConstraintEqualTo(OverlayDragBarWidth),
_overlayDragBarView.HeightAnchor.ConstraintEqualTo(OverlayDragBarHeight),
_dragBarBottomPadding = _overlayHeaderAndContentView!.TopAnchor.ConstraintEqualTo(
_overlayDragBarView!.BottomAnchor, OverlayDragBarBottomPadding),
_overlayHeaderAndContentView.BottomAnchor.ConstraintEqualTo(BottomAnchor),
_overlayHeaderAndContentView.LeadingAnchor.ConstraintEqualTo(LeadingAnchor),
_overlayHeaderAndContentView.TrailingAnchor.ConstraintEqualTo(TrailingAnchor)
});
_overlayDragBarView.LayoutIfNeeded();
_overlayHeaderAndContentView.LayoutIfNeeded();
}
private void PanOverlayView(UIPanGestureRecognizer gesture)
{
if (_parentView == null || OverlayHeight == null)
{
return;
}
if (gesture.State == UIGestureRecognizerState.Began)
{
_startingPosition = Frame.Y;
}
var scrollOffset = _scrollView!.ContentOffset.Y;
var velocity = gesture.VelocityInView(_parentView);
var y = _parentView.Frame.GetMinY();
var newPos = _startingPosition + gesture.TranslationInView(_parentView).Y;
if (newPos >= _minPosition)
{
SetOverlayPosition(0, _minPosition);
}
else if (newPos <= _maxPosition)
{
SetOverlayPosition(0, _maxPosition, 0, true, 0);
}
else
{
//Scroll the scrollView content to the top
_scrollView!.SetContentOffset(CGPoint.Empty, true);
if (scrollOffset <= 0)
{
Frame = new CGRect(0, newPos, Frame.Width, Frame.Height);
}
}
if (gesture.State == UIGestureRecognizerState.Ended)
{
var duration = velocity.Y < 0 ? (y - _maxPosition) / -velocity.Y : _minPosition - (y / velocity.Y);
duration = duration > AnimationSpeedThreshold ? 1 : duration;
if (velocity.Y > 0)
{
if (scrollOffset <= 0)
{
//Scroll the scrollView content to the top
_scrollView!.SetContentOffset(CGPoint.Empty, true);
_scrollView!.UserInteractionEnabled = false;
SetOverlayPosition(duration, _minPosition);
}
}
else
{
_scrollView!.UserInteractionEnabled = true;
SetOverlayPosition(duration, _maxPosition, 0, true, 0);
}
}
}
private void SetOverlayPosition(double animationDuration, double position, float cornerRadius = CornerRadius,
bool dragBarVisibility = false, float dragBarBottomPadding = 18.0f)
{
Animate(animationDuration, () =>
{
Frame = new CGRect(0, position, Frame.Width, Frame.Height);
_overlayDragBarView!.Hidden = dragBarVisibility;
_dragBarBottomPadding!.Constant = dragBarBottomPadding;
});
AnimateCornerRadius(cornerRadius);
}
private void ScrollViewOnScrolled(object sender, EventArgs e)
{
var scrollOffset = _scrollView!.ContentOffset.Y;
if (scrollOffset >= -1 && _panGestureRecognizer != null)
{
_scrollView.UserInteractionEnabled = false;
}
}
#region Helper Methods
private void AnimateCornerRadius(float cornerRadius) =>
Animate(0.1, () => { Layer.CornerRadius = cornerRadius; });
private UIView SetUpDistanceAndDurationLayout()
{
var containerView = new UIView
{
TranslatesAutoresizingMaskIntoConstraints = false,
ClipsToBounds = false
};
if (_displayData == null)
{
return containerView;
}
var imageDistance = new UIImageView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Image = UIImage.FromBundle(DistanceImageName),
ContentMode = UIViewContentMode.ScaleAspectFit
};
var imageDuration = new UIImageView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Image = UIImage.FromBundle(DurationImageName),
ContentMode = UIViewContentMode.ScaleAspectFit
};
var distanceDurationWrapperView = new UIView
{
TranslatesAutoresizingMaskIntoConstraints = false,
ClipsToBounds = true
};
var stackView = new UIStackView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Axis = UILayoutConstraintAxis.Horizontal,
Alignment = UIStackViewAlignment.Fill,
Spacing = 0
};
containerView.AddSubview(stackView);
stackView.TopAnchor.ConstraintEqualTo(containerView.TopAnchor).Active = true;
stackView.BottomAnchor.ConstraintEqualTo(containerView.BottomAnchor).Active = true;
stackView.LeadingAnchor.ConstraintEqualTo(containerView.LeadingAnchor).Active = true;
stackView.TrailingAnchor.ConstraintEqualTo(containerView.TrailingAnchor, 0).Active = true;
var distanceLabel = _displayData.TotalMiles.CreateLabel(BodyRegularCaption, ElementMargins.None(),
UITextAlignment.Left);
var durationLabel = _displayData.TotalJourneyTime.CreateLabel(BodyRegularCaption, ElementMargins.None(),
UITextAlignment.Left);
stackView.AddArrangedSubview(distanceDurationWrapperView);
distanceDurationWrapperView.AddSubview(imageDistance);
distanceDurationWrapperView.AddSubview(distanceLabel);
distanceDurationWrapperView.AddSubview(imageDuration);
distanceDurationWrapperView.AddSubview(durationLabel);
imageDistance.WidthAnchor.ConstraintEqualTo(IconImageWidth).Active = true;
imageDistance.HeightAnchor.ConstraintEqualTo(IconImageWidth).Active = true;
imageDuration.WidthAnchor.ConstraintEqualTo(IconImageWidth).Active = true;
imageDuration.HeightAnchor.ConstraintEqualTo(IconImageWidth).Active = true;
imageDistance.CenterYAnchor.ConstraintEqualTo(distanceDurationWrapperView.CenterYAnchor).Active = true;
imageDistance.LeadingAnchor.ConstraintEqualTo(distanceDurationWrapperView.LeadingAnchor).Active = true;
distanceLabel.TopAnchor.ConstraintEqualTo(distanceDurationWrapperView.TopAnchor).Active = true;
distanceLabel.BottomAnchor.ConstraintEqualTo(distanceDurationWrapperView.BottomAnchor, 0).Active = true;
distanceLabel.LeadingAnchor.ConstraintEqualTo(imageDistance.TrailingAnchor,
StyleGuideDimens.PaddingExtraSmall).Active = true;
imageDuration.CenterYAnchor.ConstraintEqualTo(distanceDurationWrapperView.CenterYAnchor).Active = true;
imageDuration.LeadingAnchor.ConstraintEqualTo(distanceLabel.TrailingAnchor, ImageDurationToLabelGap)
.Active = true;
durationLabel.TopAnchor.ConstraintEqualTo(distanceDurationWrapperView.TopAnchor).Active = true;
durationLabel.BottomAnchor.ConstraintEqualTo(distanceDurationWrapperView.BottomAnchor, 0).Active = true;
durationLabel.LeadingAnchor.ConstraintEqualTo(imageDuration.TrailingAnchor,
StyleGuideDimens.PaddingExtraSmall).Active = true;
durationLabel.TrailingAnchor.ConstraintEqualTo(distanceDurationWrapperView.TrailingAnchor).Active = true;
distanceDurationWrapperView.LayoutIfNeeded();
containerView.LayoutIfNeeded();
stackView.LayoutIfNeeded();
return containerView;
}
public static nfloat GetHeaderHeight(JourneyDetailOverlayDisplayData displayData, nfloat availableWidth)
{
//Left padding, left score panel padding, score panel width, right padding
var totalAvailableWidth = availableWidth - (StyleGuideDimens.PaddingSmall +
StyleGuideDimens.PaddingSmall + ScoreImageWidth + StyleGuideDimens.PaddingSmall);
var headerString = new NSString(displayData.JourneyDate);
var distance = new NSString(displayData.TotalMiles);
var duration = new NSString(displayData.TotalJourneyTime);
var sizeOfHeader = headerString.GetCalculatedSizeOfString(FontStyle.SemiBold.GetFont(Heading3SemiBold.Size),
totalAvailableWidth);
var (sizeOfStartAddress, sizeOfEndAddress) = GetAddressPanelHeights(displayData, availableWidth);
var sizeOfDistance = distance.GetCalculatedSizeOfString(FontStyle.Regular.GetFont(BodyRegularCaption.Size),
totalAvailableWidth);
var sizeOfDuration = duration.GetCalculatedSizeOfString(FontStyle.Regular.GetFont(BodyRegularCaption.Size),
totalAvailableWidth);
var distanceHeight = sizeOfDistance.Height > IconImageWidth
? sizeOfDistance.Height
: IconImageWidth;
var durationHeight = sizeOfDuration.Height > IconImageWidth
? sizeOfDuration.Height
: IconImageWidth;
var distanceDurationPanelHeight = distanceHeight > durationHeight ? distanceHeight : durationHeight;
return OverlayDragBarTopPadding
+ OverlayDragBarHeight
+ OverlayDragBarBottomPadding
+ sizeOfHeader.Height
+ StyleGuideDimens.PaddingSmall
+ sizeOfStartAddress.Height
+ StyleGuideDimens.PaddingExtraSmall
+ sizeOfEndAddress.Height
+ StyleGuideDimens.PaddingMedium
+ distanceDurationPanelHeight
+ StyleGuideDimens.PaddingSmall;
}
public static (CGSize startAddressHeight, CGSize endAddressHeight) GetAddressPanelHeights(
JourneyDetailOverlayDisplayData displayData, nfloat availableWidth)
{
//Left padding, Address icon width and padding, left score panel padding, score panel width, right padding
var totalAvailableWidth = availableWidth - (StyleGuideDimens.PaddingSmall + AddressIconWidthAndPadding +
StyleGuideDimens.PaddingSmall + ScoreImageWidth + StyleGuideDimens.PaddingSmall);
var startAddress = new NSString(displayData.JourneyStartAddress);
var endAddress = new NSString(displayData.JourneyEndAddress);
var sizeOfStartAddress = startAddress.GetCalculatedSizeOfString(
FontStyle.Regular.GetFont(BodyRegularCaption.Size),
totalAvailableWidth);
var sizeOfEndAddress = endAddress.GetCalculatedSizeOfString(
FontStyle.Regular.GetFont(BodyRegularCaption.Size),
totalAvailableWidth);
return (sizeOfStartAddress, sizeOfEndAddress);
}
#endregion
}
}
I've added a header to my collection view but it's not displaying the way I want it to display. I'm trying to have the header show up on the top of my view cells and to the left but instead, I'm stuck with what you see in the attached picture. I'd really appreciate help fixing this. Thanks
/*Header*/
public class Header:UICollectionReusableView
{
public const string identifier = "header";
public static UILabel text
{
get { return text; }
set
{
text.Text = "Header";
text.TextAlignment = UITextAlignment.Left;
text.TextColor = UIColor.White;
text.TranslatesAutoresizingMaskIntoConstraints = false;
}
}
public Header(CGRect frame): base(frame)
{
AddSubview(text);
text.TopAnchor.ConstraintLessThanOrEqualTo(SafeAreaLayoutGuide.TopAnchor).Active = true;
text.HeightAnchor.ConstraintLessThanOrEqualTo(SafeAreaLayoutGuide.HeightAnchor).Active = true;
text.LeadingAnchor.ConstraintLessThanOrEqualTo(SafeAreaLayoutGuide.LeadingAnchor).Active = true;
text.TrailingAnchor.ConstraintLessThanOrEqualTo(SafeAreaLayoutGuide.TrailingAnchor).Active = true;
}
public Header(IntPtr handle) : base(handle) { }
[Export("initWithCoder:")]
public Header(NSCoder coder) : base(coder) { }
public override void LayoutSubviews()
{
base.LayoutSubviews();
text.Bounds = Bounds;
}
}
/*ViewController*/
public class SectionViewController : UICollectionViewController
{
[Export("initWithCollectionViewLayout:")]
public SectionViewController(UICollectionViewLayout layout) : base(layout)
{
}
public SectionViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// initialize the method that launches all the collection views registered
CollectionView.RegisterClassForSupplementaryView(typeof(Header), UICollectionElementKindSection.Header, Header.identifier);
CollectionView.RegisterClassForCell(typeof(UICollectionViewCell), "cells");
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
CollectionView.Frame = new CGRect(0, 0, View.Frame.Width, View.Frame.Height/2);
//CollectionView.TranslatesAutoresizingMaskIntoConstraints = false;
CollectionView.BackgroundColor = UIColor.Blue;
}
[Export("numberOfSectionsInCollectionView:")]
public override nint NumberOfSections(UICollectionView collectionView)
{
return 1;
}
[Export("collectionView:numberOfItemsInSection:")]
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return 20;
}
[Export("collectionView:cellForItemAtIndexPath:")]
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell("cells", indexPath);
cell.BackgroundColor = UIColor.SystemGreenColor;
cell.Layer.CornerRadius = 10;
return cell;
}
[Export("collectionView:viewForSupplementaryElementOfKind:atIndexPath:")]
public override UICollectionReusableView GetViewForSupplementaryElement(UICollectionView collectionView, NSString elementKind, NSIndexPath indexPath)
{
var header = (Header)collectionView.DequeueReusableSupplementaryView(elementKind, Header.identifier, indexPath);
header.BackgroundColor = UIColor.SystemRedColor;
return header;
}
}
/*AppleDelegate*/
public class AppDelegate : UIApplicationDelegate
{
// class-level declarations
public override UIWindow Window
{
get;
set;
}
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// Override point for customization after application launch.
// If not required for your application you can safely delete this method
// create a new window instance based on the screen size
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var layout = new UICollectionViewFlowLayout();
var controller = new SectionViewController(layout);
layout.ScrollDirection = UICollectionViewScrollDirection.Horizontal;
layout.ItemSize = new CGSize((controller.CollectionView.Frame.Width - 50) / 1.1, (controller.CollectionView.Frame.Width - 10) / 6);
layout.MinimumLineSpacing = 50.0f;
layout.MinimumInteritemSpacing = 10.0f;
layout.SectionInset = new UIEdgeInsets(0, -200, 100, 0);
layout.SectionHeadersPinToVisibleBounds = true;
layout.HeaderReferenceSize = new CGSize(controller.CollectionView.Frame.Size.Width / 3, controller.CollectionView.Frame.Size.Height / 9);
var navController = new UINavigationController(controller);
Window.RootViewController = navController;
// make the window visible
Window.MakeKeyAndVisible();
return true;
}
image of the problem, the header is the weird red block
I think the weird red block is probably caused by the wrong layout in header and I did not see you init the text label. Here I wrote a example and it works well:
public class Header : UICollectionReusableView
{
public const string identifier = "header";
public UILabel text { get; set; }
[Export("initWithFrame:")]
public Header(CGRect frame) : base(frame)
{
text = new UILabel();
text.Frame = new CGRect(0, 0, 100, 50);
AddSubview(text);
}
}
public class SectionViewController : UICollectionViewController
{
[Export("initWithCollectionViewLayout:")]
public SectionViewController(UICollectionViewLayout layout) : base(layout)
{
}
public SectionViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// initialize the method that launches all the collection views registered
CollectionView.RegisterClassForSupplementaryView(typeof(Header), UICollectionElementKindSection.Header, Header.identifier);
CollectionView.RegisterClassForCell(typeof(UICollectionViewCell), "cells");
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
//CollectionView.TranslatesAutoresizingMaskIntoConstraints = false;
UICollectionViewFlowLayout layout = this.Layout as UICollectionViewFlowLayout;
CollectionView.Frame = new CGRect(0, 0, View.Frame.Width, View.Frame.Height / 2);
layout.ItemSize = new CGSize(100, 100);
layout.MinimumLineSpacing = 50.0f;
layout.MinimumInteritemSpacing = 10.0f;
layout.SectionInset = new UIEdgeInsets(0, -200, 100, 0);
layout.SectionHeadersPinToVisibleBounds = true;
layout.HeaderReferenceSize = new CGSize(300, 100);
CollectionView.BackgroundColor = UIColor.Blue;
}
[Export("numberOfSectionsInCollectionView:")]
public override nint NumberOfSections(UICollectionView collectionView)
{
return 1;
}
[Export("collectionView:numberOfItemsInSection:")]
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return 20;
}
[Export("collectionView:cellForItemAtIndexPath:")]
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell("cells", indexPath);
cell.BackgroundColor = UIColor.SystemGreenColor;
cell.Layer.CornerRadius = 10;
return cell;
}
[Export("collectionView:viewForSupplementaryElementOfKind:atIndexPath:")]
public override UICollectionReusableView GetViewForSupplementaryElement(UICollectionView collectionView, NSString elementKind, NSIndexPath indexPath)
{
var header = (Header)collectionView.DequeueReusableSupplementaryView(elementKind, Header.identifier, indexPath);
header.BackgroundColor = UIColor.SystemRedColor;
header.text.Text = "qweqweq";
return header;
}
}
There are also examples in the document and feel free to ask me any question.
I have UITableViewController, inside that, I added a button in the Cell.
Upon clicking the button, it shows a UIAlertController with "Ok" & "Cancel" Actions.
In my UIAlertController, I added a UIPickerView with some options.
When user clicks on the button in the cell, UIAlertController Popsup and shows the UIPickerView inside AlertBox with "OK" & "Cancel" actions.
Can you please help me in finding the value Selected by UIPickerView upon clicking the "Ok" button of UIAlertController.
namespace Navigation
{
public partial class ReviewInspectionViewController : UIViewController
{
private string filePath;
private InspectionData inspData = null;
List<ReportObservation> lstCriticalObs = new List<ReportObservation>();
List<ReportObservation> lstNonCriticalObs = new List<ReportObservation>();
public Audits Audit
{
get
{
return this._audit;
}
set
{
this._audit = value;
}
}
public ReviewInspectionViewController(IntPtr handle) : base(handle)
{
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
filePath = InProgressPath + Audit.AssessmentId.ToString() + ".xml";
inspData = ReadInspectionData(filePath);
if (inspData != null)
{
for (int i = 0; i < inspData.ReportSections.Count; i++)
{
lstCriticalObs.AddRange(inspData.ReportSections[i].ReportObservations.FindAll(x => x.Critical == true));
}
for (int i = 0; i < inspData.ReportSections.Count; i++)
{
lstNonCriticalObs.AddRange(inspData.ReportSections[i].ReportObservations.FindAll(x => x.Critical == false));
}
tblReviewInspection.Source = new ReviewInspectionSource(this, inspData, lstCriticalObs, lstNonCriticalObs);
tblReviewInspection.RowHeight = 160.0f;
}
}
}
class ReviewInspectionSource : UITableViewSource
{
NSString _cellID = new NSString("TableCell");
ReviewInspectionViewController _parent;
private InspectionData _inspectionData;
private List<ReportObservation> _lstCriticalObs;
private List<ReportObservation> _lstNonCriticalObs;
UITableView tvStatus;
public ReviewInspectionSource(ReviewInspectionViewController parent,
InspectionData inspectionData,
List<ReportObservation> lstCriticalObs,
List<ReportObservation> lstNonCriticalObs)
{
_inspectionData = inspectionData;
_lstCriticalObs = lstCriticalObs;
_lstNonCriticalObs = lstNonCriticalObs;
_parent = parent;
}
public override nint NumberOfSections(UITableView tableView)
{
return _lstCriticalObs.Count;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
int cnt = _lstCriticalObs[Convert.ToInt32(section)].ReportFindings.Count;
return cnt;
}
public override UIView GetViewForHeader(UITableView tableView, nint section)
{
UIView ctrls = new UIView();
tvStatus = new UITableView();
UILabel headerLabel = new UILabel(new CGRect(55, 4, 350, 33)); // Set the frame size you need
headerLabel.TextColor = UIColor.Red; // Set your color
headerLabel.Text = _lstCriticalObs[Convert.ToInt32(section)].ObsTitle;
UIButton btnEdit = new UIButton(new CGRect(5, 4, 50, 33));
var newFont = UIFont.SystemFontOfSize(17);
btnEdit.SetTitle("Edit", UIControlState.Normal);
btnEdit.Font = newFont;
btnEdit.BackgroundColor = UIColor.Yellow;
btnEdit.SetTitleColor(UIColor.Black, UIControlState.Normal);
btnEdit.SetTitleColor(UIColor.Black, UIControlState.Selected);
btnEdit.TouchUpInside += (object sender, EventArgs e) =>
{
tvStatus.Frame = new CGRect(((UIButton)sender).Frame.X, ((UIButton)sender).Frame.Y, 50, 230);
tvStatus.Hidden = false;
btnEdit.Hidden = true;
//string msg = "SectionIndex: " + section;
var Alert = UIAlertController.Create("Inspection", "\n\n\n\n\n\n", UIAlertControllerStyle.Alert);
Alert.ModalInPopover = true;
var picker = new UIPickerView(new CGRect(5, 20, 250, 140)) ;
picker.Model = new ObsStatusModel();
Alert.View.AddSubview(picker);
Alert.AddTextField((field) => {
field.Placeholder = "email address";
});
Alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, (action) => {
}));
Alert.AddAction(UIAlertAction.Create("Cancel", UIAlertActionStyle.Cancel, null ));
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(Alert, true, null);
/*
#IBAction func showChoices(_ sender: Any) {
let alert = UIAlertController(title: "Car Choices", message: "\n\n\n\n\n\n", preferredStyle: .alert)
alert.isModalInPopover = true
let pickerFrame = UIPickerView(frame: CGRect(x: 5, y: 20, width: 250, height: 140))
alert.view.addSubview(pickerFrame)
pickerFrame.dataSource = self
pickerFrame.delegate = self
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (UIAlertAction) in
print("You selected " + self.typeValue )
}))
self.present(alert,animated: true, completion: nil )
}
*/
};
List<string> lstStatus = new List<string>();
lstStatus.Add(" "); lstStatus.Add("IN"); lstStatus.Add("OUT"); lstStatus.Add("N/A"); lstStatus.Add("N/O");
tvStatus.Source = new StatusSource(lstStatus);
tvStatus.Layer.BorderColor = new CGColor(0, 0, 0);
tvStatus.Layer.BorderWidth = 2;
tvStatus.BackgroundColor = UIColor.White;
tvStatus.Hidden = true;
// tvStatus.Layer.ZPosition = 1;
tvStatus.ResignFirstResponder();
// btnEdit.BringSubviewToFront(tvStatus);
// btnEdit.Layer.ZPosition = 0;
//UILabel editLabel = new UILabel(new CGRect(360, 4, 100, 33)); // Set the frame size you need
//editLabel.TextColor = UIColor.Green; // Set your color
//editLabel.Text = "Edit Label";
ctrls.AddSubviews(headerLabel, btnEdit, tvStatus);
return ctrls;
}
public override nfloat GetHeightForHeader(UITableView tableView, nint section)
{
nfloat height = 50.0f;
return height;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
string msg = "Selected Row, ReviewInspection -- SectionIndex: " + indexPath.Section.ToString() + " RowIndex: " + indexPath.Row;
tvStatus.Hidden = true;
tvStatus.ResignFirstResponder();
//var Alert = UIAlertController.Create("Inspection", msg, UIAlertControllerStyle.Alert);
//Alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
//UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(Alert, true, null);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
ReportFinding currentRequirementItem = _lstCriticalObs[indexPath.Section].ReportFindings[indexPath.Row]; // _inspectionData.ReportSections[indexPath.Row];
var cell = tableView.DequeueReusableCell(_cellID) as ReviewInspectionTableCell;
if (cell == null) { cell = new ReviewInspectionTableCell(_cellID); }
UIView customColorView = new UIView();
customColorView.BackgroundColor = UIColor.FromRGB(39, 159, 218);
UIView SelectedRowcustomColorView = new UIView();
SelectedRowcustomColorView.BackgroundColor = UIColor.FromRGB(255, 255, 255);
UIColor clrChecklistButton = UIColor.White;
UIColor clrFont = UIColor.White;
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
cell.PreservesSuperviewLayoutMargins = false;
cell.LayoutMargins = UIEdgeInsets.Zero;
cell.BackgroundView = customColorView;
cell.SelectedBackgroundView = SelectedRowcustomColorView;
cell.Edit.TouchUpInside += (object sender, EventArgs e) =>
{
string msg = "SectionIndex: " + indexPath.Section.ToString() + " RowIndex: " + indexPath.Row;
var Alert = UIAlertController.Create("Inspection", msg, UIAlertControllerStyle.Alert);
Alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(Alert, true, null);
};
cell.Delete.TouchUpInside += (object sender, EventArgs e) =>
{
string msg = "SectionIndex: " + indexPath.Section.ToString() + " RowIndex: " + indexPath.Row;
var Alert = UIAlertController.Create("Inspection", msg, UIAlertControllerStyle.Alert);
Alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(Alert, true, null);
};
cell.UpdateCellControlsWithAuditData(currentRequirementItem.ViolationText,
currentRequirementItem.FindingAnswer,
currentRequirementItem.RepeatViolation,
clrChecklistButton,
clrFont);
return cell;
}
}
public class ReviewInspectionTableCell : UITableViewCell
{
UILabel violationText, findingAnswer, repeatViolation;
UIButton btnEdit, btnDelete;
public ReviewInspectionTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(110, 214, 254);
ContentView.Layer.CornerRadius = 8;
var newFont = UIFont.SystemFontOfSize(17);
violationText = new UILabel();
violationText.Font = newFont;
violationText.LineBreakMode = UILineBreakMode.WordWrap;
violationText.TextAlignment = UITextAlignment.Left;
violationText.Lines = 0;
violationText.TextColor = UIColor.White;
violationText.HighlightedTextColor = UIColor.Green;
violationText.BackgroundColor = UIColor.Gray;
findingAnswer = new UILabel();
findingAnswer.Font = newFont;
findingAnswer.BackgroundColor = UIColor.Orange;
findingAnswer.LineBreakMode = UILineBreakMode.WordWrap;
findingAnswer.TextAlignment = UITextAlignment.Left;
findingAnswer.Lines = 0;
findingAnswer.TextColor = UIColor.White;
repeatViolation = new UILabel();
repeatViolation.Font = newFont;
repeatViolation.BackgroundColor = UIColor.Purple;
btnEdit = new UIButton();
btnEdit.Font = newFont;
btnEdit.SetTitle("Edit", UIControlState.Normal);
btnEdit.SetTitleColor(UIColor.Black, UIControlState.Selected);
btnDelete = new UIButton();
btnDelete.Font = newFont;
btnDelete.SetTitle("Delete", UIControlState.Normal);
btnDelete.SetTitleColor(UIColor.Black, UIControlState.Selected);
ContentView.AddSubviews(new UIView[] { violationText, findingAnswer, repeatViolation, btnEdit, btnDelete });
}
public UIButton Delete
{
get
{
return btnDelete;
}
}
public UIButton Edit
{
get
{
return btnEdit;
}
}
public void UpdateCellControlsWithAuditData(string _violationText,
string _findingAnswer,
Boolean _repeatVilation,
UIColor btnColor,
UIColor clrFont)
{
string repeat = string.Empty;
if (_repeatVilation)
{
repeat = "Repeat Violation.";
}
violationText.Text = _violationText;
findingAnswer.Text = _findingAnswer;
repeatViolation.Text = repeat;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
//x, y, width, height
violationText.Frame = new CGRect(50, 0, 700, 80);
findingAnswer.Frame = new CGRect(50, 81, 700, 33);
repeatViolation.Frame = new CGRect(50, 110, 350, 33);
btnEdit.Frame = new CGRect(5, 0, 50, 33);
btnEdit.Layer.CornerRadius = 8;
btnEdit.BackgroundColor = UIColor.FromRGB(19, 120, 170);
btnDelete.Frame = new CGRect(5, 34, 50, 33);
btnDelete.Layer.CornerRadius = 8;
btnDelete.BackgroundColor = UIColor.FromRGB(19, 120, 170);
}
}
public class ObsStatusModel : UIPickerViewModel
{
static string[] names = new string[] {
"Monitor",
"Comprehensive",
"OutBreak Investigation",
"Complaint",
"FollowUp",
"PlanReview",
"Other"
};
public ObsStatusModel()
{
}
public override nint GetComponentCount(UIPickerView v)
{
return 1;
}
public override nint GetRowsInComponent(UIPickerView pickerView, nint component)
{
return names.Length;
}
public override string GetTitle(UIPickerView picker, nint row, nint component)
{
return names[row];
}
}
class StatusSource : UITableViewSource
{
NSString _cellID = new NSString("TableCell");
private List<string> _lstStatus;
public StatusSource(List<string> lstStatus)
{
_lstStatus = lstStatus;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return _lstStatus.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var Alert = UIAlertController.Create("Inspection", string.Empty, UIAlertControllerStyle.Alert);
Alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(Alert, true, null);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
string currentStatusItem = _lstStatus[indexPath.Row];
var cell = tableView.DequeueReusableCell(_cellID) as StatusTableCell;
if (cell == null) { cell = new StatusTableCell(_cellID); }
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
cell.PreservesSuperviewLayoutMargins = false;
cell.LayoutMargins = UIEdgeInsets.Zero;
cell.UpdateCellControlsWithAuditData(currentStatusItem);
return cell;
}
}
public class StatusTableCell : UITableViewCell
{
UILabel statusText;
public StatusTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
//ContentView.BackgroundColor = UIColor.FromRGB(110, 214, 254);
//ContentView.Layer.CornerRadius = 8;
var newFont = UIFont.SystemFontOfSize(17);
statusText = new UILabel();
statusText.Font = newFont;
statusText.LineBreakMode = UILineBreakMode.WordWrap;
statusText.TextAlignment = UITextAlignment.Center;
statusText.Lines = 0;
statusText.TextColor = UIColor.Black;
statusText.HighlightedTextColor = UIColor.Green;
statusText.BackgroundColor = UIColor.White;
ContentView.AddSubviews(new UIView[] { statusText });
}
public void UpdateCellControlsWithAuditData(string status)
{
statusText.Text = status;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
//x, y, width, height
statusText.Frame = new CGRect(5, 5, 100, 25);
}
}
}
See attached image.
You can add a UIPickerView as subview on the view of UIAlertViewController. Refer to the following code:
public void CreatAlertView()
{
UIAlertController alert = UIAlertController.Create("Inspection\n\n\n\n\n\n\n", "", UIAlertControllerStyle.Alert);
alert.AddTextField((UITextField obj) =>
{
obj.Placeholder = "email address";
});
UIAlertAction OKAction = UIAlertAction.Create("OK", UIAlertActionStyle.Default, (obj) =>
{
if(alert.TextFields[0].Text.Length!=0)
{
//do some thing
}
});
UIAlertAction CancelAction = UIAlertAction.Create("Cancel", UIAlertActionStyle.Cancel, null);
alert.AddAction(OKAction);
alert.AddAction(CancelAction);
var picker = new UIPickerView(new CGRect(0, 0,270,220));
picker.WeakDelegate = this;
picker.DataSource = this;
this.pickerView = picker;
alert.View.AddSubview(pickerView);
alertController = alert;
this.PresentViewController(alertController, false, null);
}
And don't forget to implement the methods in the delegate:
public nint GetComponentCount(UIPickerView pickerView)
{
return 1;
}
public nint GetRowsInComponent(UIPickerView pickerView, nint component)
{
if (component==0)
{
return (System.nint)itemsArray.Length;
}
else
{
return 0;
}
}
[Export("pickerView:titleForRow:forComponent:")]
public string GetTitle(UIPickerView pickerView, nint row, nint component)
{
string content = itemsArray[(nuint)row].ToString();
return content;
}
[Export("pickerView:didSelectRow:inComponent:")]
public void Selected(UIPickerView pickerView, nint row, nint component)
{
string content= itemsArray[(nuint)row].ToString();
//do some thing
}
Then you can call the method
this.itemsArray= new string[] {"apple","google","apple","google","apple","google"} ;//init the source array
CreatAlertView();
I have upload the demo to my git. you can download it for more details.demo
In my Xamarin.iOS application, I am trying to animate a loading spinner. I can draw the circle and the arc, but I do not know how to animate it. This is my class for the loading spinner:
public class LoadingSpinnerView : UIView
{
private CAShapeLayer _thinCirlce;
private CAShapeLayer _arc;
public LoadingSpinnerView()
{
_arc = new CAShapeLayer();
_arc.LineWidth = 3;
_arc.StrokeColor = UIColor.Blue.CGColor;
_arc.FillColor = UIColor.Clear.CGColor;
_thinCirlce = new CAShapeLayer();
_thinCirlce.LineWidth = 1;
_thinCirlce.StrokeColor = UIColor.Red.CGColor;
_thinCirlce.FillColor = UIColor.Clear.CGColor;
Layer.AddSublayer(_thinCirlce);
Layer.AddSublayer(_arc);
}
private nfloat _angle;
public nfloat Angle
{
get
{
return _angle;
}
set
{
_angle = value;
}
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
_thinCirlce.Path = UIBezierPath.FromOval(new CoreGraphics.CGRect(0, 0, Frame.Width, Frame.Height)).CGPath;
nfloat radius = Frame.Width / 2;
_arc.Path = UIBezierPath.FromArc(new CoreGraphics.CGPoint(radius, radius), radius, 0, Angle, true).CGPath;
}
}
I want to be able to animate it, something like this:
UIView.Animate(5, () => { _loadingSpinnerView.Angle = 3.14f; }); // This doesn't actually work...
Ready to use control. Just set control to UIView in your Storyboard.
[Register(nameof(CircleLoadingView))]
public class CircleLoadingView : UIView
{
public CircleLoadingView(IntPtr handle) : base(handle)
{
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
SetUpAnimation(this.Layer, new CGSize(Frame.Width, Frame.Height), UIColor.Red);
}
public void SetUpAnimation(CALayer layer, CGSize size, UIColor color)
{
var beginTime = 0.5;
var strokeStartDuration = 1.2;
var strokeEndDuration = 0.7;
var strokeEndAnimation = CABasicAnimation.FromKeyPath("strokeEnd");
strokeEndAnimation.Duration = strokeEndDuration;
strokeEndAnimation.TimingFunction = CAMediaTimingFunction.FromControlPoints(0.4f, 0.0f, 0.2f, 1.0f);
strokeEndAnimation.From = NSNumber.FromFloat(0);
strokeEndAnimation.To = NSNumber.FromFloat(1);
var strokeStartAnimation = CABasicAnimation.FromKeyPath("strokeStart");
strokeStartAnimation.Duration = strokeStartDuration;
strokeStartAnimation.TimingFunction = CAMediaTimingFunction.FromControlPoints(0.4f, 0.0f, 0.2f, 1.0f);
strokeStartAnimation.From = NSNumber.FromFloat(0);
strokeStartAnimation.To = NSNumber.FromFloat(1);
strokeStartAnimation.BeginTime = beginTime;
var groupAnimation = new CAAnimationGroup
{
Animations = new CAAnimation[] {/*rotationAnimation,*/ strokeEndAnimation, strokeStartAnimation },
Duration = strokeStartDuration + beginTime,
RepeatCount = float.PositiveInfinity,
RemovedOnCompletion = false,
FillMode = CAFillMode.Forwards
};
var circle = CreateCircle(size, color);
var frame = CGRect.FromLTRB(
(layer.Bounds.Width - size.Width) / 2,
(layer.Bounds.Height - size.Height) / 2,
size.Width,
size.Height
);
circle.Frame = frame;
circle.AddAnimation(groupAnimation, "animation");
layer.AddSublayer(circle);
}
private CAShapeLayer CreateCircle(CGSize size, UIColor color)
{
var layer = new CAShapeLayer();
var path = new UIBezierPath();
path.AddArc(new CGPoint(size.Width / 2, size.Height / 2),
size.Width / 2,
-(float)(Math.PI / 2),
(float)(Math.PI + Math.PI / 2),
true);
layer.FillColor = null;
layer.StrokeColor = color.CGColor;
layer.LineWidth = 2;
layer.BackgroundColor = null;
layer.Path = path.CGPath;
layer.Frame = CGRect.FromLTRB(0, 0, size.Width, size.Height);
return layer;
}
}
I figured it out. Here is my loading spinner class for other Xamarin developers to use. You can adjust it to your own requirements.
public class LoadingSpinnerView : UIView
{
private CAShapeLayer _thinCirlce;
private CAShapeLayer _arcLayer;
public LoadingSpinnerView(nfloat radius)
{
UIColor.Red.SetColor();
_thinCirlce = new CAShapeLayer();
_thinCirlce.LineWidth = 1;
_thinCirlce.Path = UIBezierPath.FromOval(new CoreGraphics.CGRect(0, 0, radius * 2, radius * 2)).CGPath;
_thinCirlce.StrokeColor = UIColor.Red.CGColor;
_thinCirlce.FillColor = UIColor.Clear.CGColor;
Layer.AddSublayer(_thinCirlce);
UIColor.Blue.SetColor();
UIBezierPath arcPath = new UIBezierPath();
arcPath.LineWidth = 4;
arcPath.LineCapStyle = CGLineCap.Round;
arcPath.LineJoinStyle = CGLineJoin.Round;
arcPath.AddArc(new CoreGraphics.CGPoint(radius, radius), radius, 0, 2 * 3.14f, true);
_arcLayer = new CAShapeLayer();
_arcLayer.Path = arcPath.CGPath;
_arcLayer.StrokeColor = UIColor.Blue.CGColor;
_arcLayer.FillColor = UIColor.Clear.CGColor;
_arcLayer.LineWidth = 4;
_arcLayer.StrokeStart = 0;
_arcLayer.StrokeEnd = 1;
if (_arcLayer.SuperLayer != null)
{
_arcLayer.RemoveAllAnimations();
_arcLayer.RemoveFromSuperLayer();
}
}
public void StartAnimation()
{
Layer.AddSublayer(_arcLayer);
CABasicAnimation animation = new CABasicAnimation();
animation.KeyPath = "strokeEnd";
animation.Duration = 3;
animation.From = NSNumber.FromFloat(0);
animation.To = NSNumber.FromFloat(1);
_arcLayer.AddAnimation(animation, null);
}
public void StopAnimation()
{
_arcLayer.RemoveAllAnimations();
_arcLayer.RemoveFromSuperLayer();
}
}
I am trying to make a CardView on IOS Xamarin Forms by subclassing the Frame and making a custom renderer. I want to achieve something like this:
Upon looking into the API on setting a shadow, I've done this:
[assembly: ExportRenderer(typeof(CardView), typeof(CardViewRenderer))]
namespace TrabbleMobile.iOS.CustomRenderers
{
public class CardViewRenderer : FrameRenderer
{
public override void Draw(CGRect rect)
{
var cardView = (CardView)this.Element;
using (var context = UIGraphics.GetCurrentContext())
{
//nfloat cornerRadius = 2;
float shadowOffsetWidth = 2;
float shadowOffsetHeight = 4;
var shadowColor = new CGColor(0, 0, 0, (nfloat)0.5);
var boxColor = new CGColor(255, 255, 255);
var shadowBlur = (float)0.5;
var offset = new CGSize(shadowOffsetWidth, shadowOffsetHeight);
context.SetShadow(offset, shadowBlur, shadowColor);
However, it does not render as it should and no shadow at all.
I've done this, and the way that I did this is thru custom rendering on IOS and here is the custom renderer code:
public class CardViewRenderer : FrameRenderer
{
public override void Draw(CGRect rect)
{
SetupShadowLayer();
base.Draw(rect);
}
void SetupShadowLayer()
{
Layer.CornerRadius = 2; // 5 Default
if (Element.BackgroundColor == Xamarin.Forms.Color.Default)
{
Layer.BackgroundColor = UIColor.White.CGColor;
}
else
{
Layer.BackgroundColor = Element.BackgroundColor.ToCGColor();
}
Layer.ShadowRadius = 2; // 5 Default
Layer.ShadowColor = UIColor.Black.CGColor;
Layer.ShadowOpacity = 0.4f; // 0.8f Default
Layer.ShadowOffset = new CGSize(0f, 2.5f);
if (Element.OutlineColor == Xamarin.Forms.Color.Default)
{
Layer.BorderColor = UIColor.Clear.CGColor;
}
else
{
Layer.BorderColor = Element.OutlineColor.ToCGColor();
Layer.BorderWidth = 1;
}
Layer.RasterizationScale = UIScreen.MainScreen.Scale;
Layer.ShouldRasterize = true;
}
}