Skip to content

Instantly share code, notes, and snippets.

@sfmskywalker
Created October 22, 2017 12:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfmskywalker/8d750f058cb83e4daca1b6928430e462 to your computer and use it in GitHub Desktop.
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/
[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