Created
October 22, 2017 12:43
-
-
Save sfmskywalker/8d750f058cb83e4daca1b6928430e462 to your computer and use it in GitHub Desktop.
A UIPickerView with support for labels. Ported from http://blog.nottoobadsoftware.com/iphone-development/a-uipickerview-with-labels/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Register(nameof(UILabeledPickerView))] | |
public class UILabeledPickerView : UIPickerView | |
{ | |
public UILabeledPickerView(IntPtr handle) : base(handle) | |
{ | |
} | |
private IDictionary<int, string> mLabelsDictionary = new Dictionary<int, string>(); | |
/// <summary> | |
/// Adds the label for the given component. | |
/// </summary> | |
public void SetLabel(string labeltext, int component) | |
{ | |
mLabelsDictionary[component] = labeltext; | |
} | |
/// <summary> | |
/// Adds the labels to the view, below the selection indicator glass-thingy. | |
/// The labels are aligned to the right side of the wheel. | |
/// The delegate is responsible for providing enough width for both the value and the label. | |
/// </summary> | |
public override void MovedToWindow() | |
{ | |
// Exit if view is removed from the window or there are no labels. | |
if (Window == null || !mLabelsDictionary.Any()) | |
return; | |
var labelFont = UIFont.BoldSystemFontOfSize(20); | |
// Find the width of all the wheels combined. | |
var widthOfWheels = 0f; | |
for (var i = 0; i < NumberOfComponents; i++) | |
{ | |
widthOfWheels += (float)RowSizeForComponent(i).Width; | |
} | |
// Find the left side of the first wheel. | |
// Seems like a misnomer, but that will soon be corrected. | |
var rightSideOfWheel = (Frame.Size.Width - widthOfWheels) / 2; | |
// Cycle through all wheels. | |
for (var component = 0; component < NumberOfComponents; component++) | |
{ | |
// Find the right side of the wheel. | |
rightSideOfWheel += RowSizeForComponent(component).Width; | |
// Get the text for the label. | |
// Move on to the next if there is no label for this wheel. | |
if (!mLabelsDictionary.ContainsKey(component)) | |
continue; | |
var text = (NSString)mLabelsDictionary[component]; | |
// Set up the frame for the label. | |
var frame = new CGRect | |
{ | |
Size = text.StringSize(labelFont) | |
}; | |
// Center it vertically. | |
frame.Y = (Frame.Size.Height / 2) - (frame.Size.Height / 2) - 0.5f; | |
// Align it to the right side of the wheel, with a margin. | |
// Use a smaller margin for the rightmost wheel. | |
frame.X = rightSideOfWheel - frame.Size.Width - (component == NumberOfComponents - 1 ? 5 : 7); | |
// Set up the label. | |
var label = new UILabel(frame) | |
{ | |
Text = text, | |
Font = labelFont, | |
BackgroundColor = UIColor.Clear, | |
ShadowColor = UIColor.White, | |
ShadowOffset = new CGSize(0, 1) | |
}; | |
// And now for the tricky bit: adding the label to the view. | |
// Kind of a hack to be honest, might stop working if Apple decides to change the inner workings of the UIPickerView. | |
if (ShowSelectionIndicator) | |
{ | |
// if this is the last wheel, add label as the third view from the top | |
if (component == NumberOfComponents - 1) | |
InsertSubview(label, Subviews.Length - 3); | |
// otherwise add label as the 5th, 10th, 15th etc view from the top | |
else | |
InsertSubviewAbove(label, Subviews.ElementAt(5 * (component + 1))); | |
} | |
else | |
// there is no selection indicator, so just add it to the top | |
AddSubview(label); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment