Commit c14074ef authored by stkhapugin@chromium.org's avatar stkhapugin@chromium.org Committed by Commit Bot

Add new constraint utils.

In many situations two views are constrained by three sides, and:
a) the fourth side is constraint to another view
b) the fourth side is constraint with an offset

This implements a new helper:
void AddSameConstraintsToSidesWithInsets(
    id<LayoutGuideProvider> innerView,
    id<LayoutGuideProvider> outerView,
    ios::LayoutSides sides,
    ios::ChromeDirectionalEdgeInsets insets);

This should allow writing things like:

AddSameConstraintsToSidesWithInsets(view1, view2,
  LayoutSides::kTop|LayoutSides::kLeading,
  ChromeDirectionalEdgeInsets{10, 5, 8, 8});

and a simplified version with no insets:

AddSameConstraintsToSides(view1, view2,
  LayoutSides::kTop|LayoutSides::kLeading);

These helpers should reduce boilerplate in layout code.

Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: If1ef5427dde1fe7e098f212b6917d9566d1df0e6
Reviewed-on: https://chromium-review.googlesource.com/859789
Commit-Queue: Stepan Khapugin <stkhapugin@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537328}
parent 6f4884c0
......@@ -7,6 +7,49 @@
#import <UIKit/UIKit.h>
// A bitmask to refer to sides of a layout rectangle.
enum class LayoutSides {
kTop = 1 << 0,
kLeading = 1 << 1,
kBottom = 1 << 2,
kTrailing = 1 << 3,
};
// Implementation of bitwise "or", "and" operators (as those are not
// automatically defined for "class enum").
constexpr LayoutSides operator|(LayoutSides lhs, LayoutSides rhs) {
return static_cast<LayoutSides>(
static_cast<std::underlying_type<LayoutSides>::type>(lhs) |
static_cast<std::underlying_type<LayoutSides>::type>(rhs));
};
constexpr LayoutSides operator&(LayoutSides lhs, LayoutSides rhs) {
return static_cast<LayoutSides>(
static_cast<std::underlying_type<LayoutSides>::type>(lhs) &
static_cast<std::underlying_type<LayoutSides>::type>(rhs));
};
// Returns whether the |flag| is set in |mask|.
constexpr bool IsLayoutSidesMaskSet(LayoutSides mask, LayoutSides flag) {
return (mask & flag) == flag;
}
// Same as NSDirectionalEdgeInsets but available on iOS 10.
struct ChromeDirectionalEdgeInsets {
CGFloat top, leading, bottom, trailing; // specify amount to inset (positive)
// for each of the edges. values can
// be negative to 'outset'
};
inline ChromeDirectionalEdgeInsets ChromeDirectionalEdgeInsetsMake(
CGFloat top,
CGFloat leading,
CGFloat bottom,
CGFloat trailing) {
ChromeDirectionalEdgeInsets insets = {top, leading, bottom, trailing};
return insets;
}
// Defines a protocol for common -...Anchor methods of UIView and UILayoutGuide.
@protocol LayoutGuideProvider<NSObject>
@property(nonatomic, readonly, strong) NSLayoutXAxisAnchor* leadingAnchor;
......@@ -130,6 +173,25 @@ void AddSameConstraints(id<LayoutGuideProvider> view1,
// anchors equals to |outerView| safe area (or view bounds) anchors.
void PinToSafeArea(id<LayoutGuideProvider> innerView, UIView* outerView);
// Constraints |side_flags| of |view1| and |view2| together.
// Example usage: AddSameConstraintsToSides(view1, view2,
// LayoutSides::kTop|LayoutSides::kLeading)
void AddSameConstraintsToSides(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2,
LayoutSides side_flags);
// Constraints |side_flags| sides of |innerView| and |outerView| together, with
// |innerView| inset by |insets|. Example usage:
// AddSameConstraintsToSidesWithInsets(view1, view2,
// LayoutSides::kTop|LayoutSides::kLeading, ChromeDirectionalEdgeInsets{10, 5,
// 10, 5}) - This will constraint innerView to be inside of outerView, with
// leading/trailing inset by 10 and top/bottom inset by 5.
// Edge insets for sides not listed in |side_flags| are ignored.
void AddSameConstraintsToSidesWithInsets(id<LayoutGuideProvider> innerView,
id<LayoutGuideProvider> outerView,
LayoutSides side_flags,
ChromeDirectionalEdgeInsets insets);
#pragma mark - Safe Area.
// Returns a safeAreaLayoutGuide for a given view.
......
......@@ -150,3 +150,39 @@ id<LayoutGuideProvider> SafeAreaLayoutGuideForView(UIView* view) {
return view;
}
}
void AddSameConstraintsToSides(id<LayoutGuideProvider> view1,
id<LayoutGuideProvider> view2,
LayoutSides side_flags) {
AddSameConstraintsToSidesWithInsets(
view1, view2, side_flags, ChromeDirectionalEdgeInsetsMake(0, 0, 0, 0));
}
void AddSameConstraintsToSidesWithInsets(id<LayoutGuideProvider> innerView,
id<LayoutGuideProvider> outerView,
LayoutSides side_flags,
ChromeDirectionalEdgeInsets insets) {
NSMutableArray* constraints = [[NSMutableArray alloc] init];
if (IsLayoutSidesMaskSet(side_flags, LayoutSides::kTop)) {
[constraints addObject:[innerView.topAnchor
constraintEqualToAnchor:outerView.topAnchor
constant:insets.top]];
}
if (IsLayoutSidesMaskSet(side_flags, LayoutSides::kLeading)) {
[constraints addObject:[innerView.leadingAnchor
constraintEqualToAnchor:outerView.leadingAnchor
constant:insets.leading]];
}
if (IsLayoutSidesMaskSet(side_flags, LayoutSides::kBottom)) {
[constraints addObject:[innerView.bottomAnchor
constraintEqualToAnchor:outerView.bottomAnchor
constant:-insets.bottom]];
}
if (IsLayoutSidesMaskSet(side_flags, LayoutSides::kTrailing)) {
[constraints addObject:[innerView.trailingAnchor
constraintEqualToAnchor:outerView.trailingAnchor
constant:-insets.trailing]];
}
[NSLayoutConstraint activateConstraints:constraints];
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment