Last active
January 23, 2016 07:05
-
-
Save Cheesebaron/ddec891e5eedfcf3db75 to your computer and use it in GitHub Desktop.
Port of SSSnackbar https://github.com/stonesam92/SSSnackbar
This file contains 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
public sealed class Snackbar : UIView | |
{ | |
public TimeSpan Duration { get; set; } | |
public Action<Snackbar> OnAction { get; set; } | |
public Action<Snackbar> OnDismiss { get; set; } | |
private static Snackbar _currentlyVisibleSnackbar; | |
private readonly UILabel _messageLabel; | |
private readonly UIButton _actionButton; | |
private readonly UIView _separator; | |
private NSLayoutConstraint[] _horizontalLayoutConstraints; | |
private NSLayoutConstraint[] _visibleVerticalLayoutConstraints; | |
private NSLayoutConstraint[] _hiddenVerticalLayoutConstraints; | |
private NSTimer _dismissalTimer; | |
private bool _actionDispatched; | |
public static Snackbar WithMessage(string message, string actionText, TimeSpan duration, | |
Action<Snackbar> onAction, Action<Snackbar> onDismiss) | |
{ | |
var snackBar = new Snackbar(message, actionText, duration, onAction, onDismiss); | |
return snackBar; | |
} | |
private Snackbar(string message, string actionText, TimeSpan duration, | |
Action<Snackbar> onAction, Action<Snackbar> onDismiss) : base(new CGRect(0,0,0,0)) | |
{ | |
TranslatesAutoresizingMaskIntoConstraints = false; | |
Duration = duration; | |
OnAction = onAction; | |
OnDismiss = onDismiss; | |
_messageLabel = new UILabel { | |
Text = message, | |
TranslatesAutoresizingMaskIntoConstraints = false, | |
Font = UIFont.SystemFontOfSize(14f), | |
TextColor = UIColor.White | |
}; | |
_messageLabel.SizeToFit(); | |
_actionButton = new UIButton(UIButtonType.System) { | |
TranslatesAutoresizingMaskIntoConstraints = false | |
}; | |
_actionButton.TitleLabel.Font = UIFont.SystemFontOfSize(14f, UIFontWeight.Bold); | |
_actionButton.SetTitle(actionText, UIControlState.Normal); | |
_actionButton.SetTitleColor(UIColor.White, UIControlState.Normal); | |
_actionButton.SizeToFit(); | |
_actionButton.TouchUpInside += ExecuteAction; | |
_separator = new UIView { | |
BackgroundColor = UIColor.FromWhiteAlpha(0.99f, 0.1f), | |
TranslatesAutoresizingMaskIntoConstraints = false | |
}; | |
AddSubview(_messageLabel); | |
AddSubview(_actionButton); | |
AddSubview(_separator); | |
Opaque = false; | |
} | |
public override void Draw(CGRect rect) | |
{ | |
base.Draw(rect); | |
using (var context = UIGraphics.GetCurrentContext()) | |
{ | |
context.SaveState(); | |
UIColor.FromWhiteAlpha(0.1f, 0.9f).SetFill(); | |
var clippath = UIBezierPath.FromRoundedRect(rect, 3f); | |
clippath.Fill(); | |
context.RestoreState(); | |
} | |
} | |
public void Show() | |
{ | |
var topController = UIApplication.SharedApplication.KeyWindow.RootViewController; | |
while (topController?.PresentedViewController != null) { | |
topController = topController?.PresentedViewController; | |
} | |
if (topController == null) | |
{ | |
Console.WriteLine("I have no top controller, I am drunk..."); | |
return; | |
} | |
var superView = topController.View; | |
var shouldReplaceExistingSnackbar = _currentlyVisibleSnackbar != null; | |
if (shouldReplaceExistingSnackbar) | |
{ | |
_currentlyVisibleSnackbar.InvalidateTimer(); | |
_currentlyVisibleSnackbar.Dismiss(false); | |
} | |
superView.AddSubview(this); | |
superView.AddConstraints(HorizontalLayoutConstraints); | |
superView.AddConstraints(shouldReplaceExistingSnackbar | |
? VisibleVerticalLayoutConstraints | |
: HiddenVerticalLayoutConstraints); | |
superView.LayoutIfNeeded(); | |
SetupContentLayout(); | |
if (!shouldReplaceExistingSnackbar) | |
{ | |
superView.RemoveConstraints(HiddenVerticalLayoutConstraints); | |
superView.AddConstraints(VisibleVerticalLayoutConstraints); | |
Animate(0.2, 0, UIViewAnimationOptions.CurveEaseOut, | |
() => superView.LayoutIfNeeded(), () => { }); | |
} | |
_dismissalTimer = NSTimer.CreateScheduledTimer(Duration, TimeoutForDismissal); | |
_currentlyVisibleSnackbar = this; | |
} | |
private void TimeoutForDismissal(NSTimer nsTimer) | |
{ | |
Dismiss(); | |
} | |
private void Dismiss(bool animated = true) | |
{ | |
InvalidateTimer(); | |
Superview.RemoveConstraints(VisibleVerticalLayoutConstraints); | |
Superview.AddConstraints(HiddenVerticalLayoutConstraints); | |
_currentlyVisibleSnackbar = null; | |
if (!animated) | |
{ | |
ExecuteDismissal(); | |
RemoveFromSuperview(); | |
} | |
else | |
{ | |
Animate(0.2, 0, UIViewAnimationOptions.CurveEaseIn, | |
() => Superview.LayoutIfNeeded(), | |
() => { | |
if (!_actionDispatched) | |
ExecuteDismissal(); | |
RemoveFromSuperview(); | |
}); | |
} | |
} | |
private void InvalidateTimer() | |
{ | |
_dismissalTimer?.Invalidate(); | |
_dismissalTimer?.Dispose(); | |
_dismissalTimer = null; | |
} | |
private void SetupContentLayout() | |
{ | |
var constraints = new List<NSLayoutConstraint>(); | |
constraints.AddRange( | |
NSLayoutConstraint.FromVisualFormat( | |
"|-8-[label]-(>=8)-[sep(1)]-8-[button]-8-|", | |
NSLayoutFormatOptions.AlignAllCenterY, | |
"label", _messageLabel, "button", _actionButton, "sep", _separator)); | |
constraints.AddRange( | |
NSLayoutConstraint.FromVisualFormat( | |
"V:|-0-[sep]-0-|", 0, "sep", _separator)); | |
constraints.Add(NSLayoutConstraint.Create(_messageLabel, NSLayoutAttribute.CenterY, | |
NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1, 0)); | |
AddConstraints(constraints.ToArray()); | |
LayoutIfNeeded(); | |
} | |
private NSLayoutConstraint[] HorizontalLayoutConstraints => | |
_horizontalLayoutConstraints ?? (_horizontalLayoutConstraints = | |
NSLayoutConstraint.FromVisualFormat(@"H:|-5-[bar]-(5)-|", 0, "bar", this)); | |
private NSLayoutConstraint[] VisibleVerticalLayoutConstraints => | |
_visibleVerticalLayoutConstraints ?? (_visibleVerticalLayoutConstraints = | |
NSLayoutConstraint.FromVisualFormat(@"V:[bar(44)]-(5)-|", 0, "bar", this)); | |
private NSLayoutConstraint[] HiddenVerticalLayoutConstraints => | |
_hiddenVerticalLayoutConstraints ?? (_hiddenVerticalLayoutConstraints = | |
NSLayoutConstraint.FromVisualFormat(@"V:[bar(44)]-(-50)-|", 0, "bar", this)); | |
private void ExecuteAction(object sender, EventArgs eventArgs) | |
{ | |
InvalidateTimer(); | |
ExecuteAction(); | |
Dismiss(); | |
} | |
private void ExecuteAction() | |
{ | |
_actionDispatched = true; | |
OnAction?.Invoke(this); | |
} | |
private void ExecuteDismissal() | |
{ | |
if (!_actionDispatched) | |
OnDismiss?.Invoke(this); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment