Commit 9182d78c authored by Mark Cogan's avatar Mark Cogan Committed by Commit Bot

[iOS] Add drag support to tab grid page control.

This CL adds drag support to the tab grid page control using the standard UIControl touch-tracking methods.

It updates the behavior of the control to call ValueChanged actions when the control is dragged, and TouchUpInside actions when a new segment is selected.


Bug: 849649
Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I365c8447f4e6ef215a7558bdab2522867154be38
Reviewed-on: https://chromium-review.googlesource.com/1093470
Commit-Queue: Mark Cogan <marq@chromium.org>
Reviewed-by: default avataredchin <edchin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566371}
parent 08c898d6
......@@ -14,6 +14,14 @@
// This is a fixed-size control; it's an error to set or change its size.
// The sections are arranged in leading-to-trailing order:
// incognito tabs, regular tabs, remote tabs.
//
// Dragging the slider will change the value of the control's |sliderPosition|
// property, and will trigger any UIControlEventValueChanged actions. Once a
// drag is completed, the UIControlEventTouchUpInside actions are triggered.
//
// Tapping on sections of the slider will change the value of the control's
// |selectedPage| property and will trigger any UIControlEventTouchUpInside
// actions.
@interface TabGridPageControl : UIControl
// The currently selected page in the control. When this value is changed by
......
......@@ -80,8 +80,8 @@ const CGFloat kBackgroundWidth = 3 * kSegmentWidth + 2 * kSeparatorWidth;
// Overall height of the control -- the larger of the slider and segment
// heights.
const CGFloat kOverallHeight = std::max(kSliderHeight, kSegmentHeight);
// Overall width of the control -- the background width plusand twice
// the slider overhang.
// Overall width of the control -- the background width plus twice the slider
// overhang.
const CGFloat kOverallWidth = kBackgroundWidth + 2 * kSliderOverhang;
// Radius used to draw the background and the slider.
......@@ -152,6 +152,10 @@ NSString* StringForItemCount(long count) {
// the positive-x direction.
@property(nonatomic) CGFloat sliderRange;
@property(nonatomic, strong) NSArray* accessibilityElements;
// YES if the slider is currently being dragged
@property(nonatomic) BOOL dragging;
@property(nonatomic) CGPoint dragStart;
@property(nonatomic) CGFloat dragStartPosition;
@end
@implementation TabGridPageControl
......@@ -176,6 +180,9 @@ NSString* StringForItemCount(long count) {
@synthesize sliderOrigin = _sliderOrigin;
@synthesize sliderRange = _sliderRange;
@synthesize accessibilityElements = _accessibilityElements;
@synthesize dragging = _dragging;
@synthesize dragStart = _dragStart;
@synthesize dragStartPosition = _dragStartPosition;
+ (instancetype)pageControl {
return [[TabGridPageControl alloc] init];
......@@ -264,6 +271,49 @@ NSString* StringForItemCount(long count) {
}
}
#pragma mark - UIControl
- (BOOL)beginTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event {
CGPoint locationInSlider = [touch locationInView:self.sliderView];
if ([self.sliderView pointInside:locationInSlider withEvent:event]) {
self.dragging = YES;
self.dragStart = [touch locationInView:self];
self.dragStartPosition = self.sliderPosition;
return YES;
}
return NO;
}
- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event {
if (!self.dragging)
return NO;
// Compute x-distance offset
CGPoint position = [touch locationInView:self];
CGFloat deltaX = position.x - self.dragStart.x;
// Convert to position change.
CGFloat postionChange = deltaX / self.sliderRange;
self.sliderPosition = self.dragStartPosition + postionChange;
[self sendActionsForControlEvents:UIControlEventValueChanged];
// If the touch is now outside of the control, stop tracking it.
return self.touchInside;
}
- (void)endTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event {
// endTracking is called when -continueTracking returns NO. There's no
// additional logic in this case, so just forward to -cancelTracking
[self cancelTrackingWithEvent:event];
}
- (void)cancelTrackingWithEvent:(UIEvent*)event {
// cancelTracking is called when there are no more touches (that is, when the
// user lifts their finger).
self.dragging = NO;
[self setSelectedPage:self.selectedPage animated:YES];
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
#pragma mark - UIView
- (CGSize)intrinsicContentSize {
......@@ -365,6 +415,7 @@ NSString* StringForItemCount(long count) {
// used to position the section content.
- (void)setupViews {
UIView* backgroundView = [[TabGridPageControlBackground alloc] init];
backgroundView.userInteractionEnabled = NO;
backgroundView.layer.cornerRadius = kCornerRadius;
backgroundView.layer.masksToBounds = YES;
[self addSubview:backgroundView];
......@@ -409,6 +460,7 @@ NSString* StringForItemCount(long count) {
// Add the slider above the section images and labels.
CGRect sliderFrame = CGRectMake(0, 0, kSliderWidth, kSliderHeight);
UIView* slider = [[UIView alloc] initWithFrame:sliderFrame];
slider.userInteractionEnabled = NO;
slider.layer.cornerRadius = kCornerRadius;
slider.layer.masksToBounds = YES;
slider.backgroundColor = UIColorFromRGB(kSliderColor);
......@@ -420,6 +472,7 @@ NSString* StringForItemCount(long count) {
// will be clipped by the slider.
UIView* selectedImageView = [[UIView alloc]
initWithFrame:(CGRectMake(0, 0, kOverallWidth, kOverallHeight))];
selectedImageView.userInteractionEnabled = NO;
[self.sliderView addSubview:selectedImageView];
self.selectedImageView = selectedImageView;
......@@ -519,7 +572,7 @@ NSString* StringForItemCount(long count) {
}
if (page != self.selectedPage) {
[self setSelectedPage:page animated:YES];
[self sendActionsForControlEvents:UIControlEventValueChanged];
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
......
......@@ -483,8 +483,12 @@ NSUInteger GetPageIndexFromPage(TabGridPage page) {
self.topToolbar = topToolbar;
// Configure and initialize the page control.
[self.topToolbar.pageControl addTarget:self
action:@selector(pageControlChanged:)
action:@selector(pageControlChangedValue:)
forControlEvents:UIControlEventValueChanged];
[self.topToolbar.pageControl addTarget:self
action:@selector(pageControlChangedPage:)
forControlEvents:UIControlEventTouchUpInside];
NSArray* constraints = @[
[topToolbar.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[topToolbar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
......@@ -830,7 +834,25 @@ NSUInteger GetPageIndexFromPage(TabGridPage page) {
[self.tabPresentationDelegate showActiveTabInPage:self.currentPage];
}
- (void)pageControlChanged:(id)sender {
- (void)pageControlChangedValue:(id)sender {
// Map the page control slider position (in the range 0.0-1.0) to an
// x-offset for the scroll view.
CGFloat offset = self.topToolbar.pageControl.sliderPosition;
// In RTL, flip the offset.
if (UseRTLLayout())
offset = 1.0 - offset;
// Total space available for the scroll view to scroll (horizontally).
CGFloat offsetWidth =
self.scrollView.contentSize.width - self.scrollView.frame.size.width;
CGPoint contentOffset = self.scrollView.contentOffset;
// Find the final offset by using |offset| as a fraction of the available
// scroll width.
contentOffset.x = offsetWidth * offset;
self.scrollView.contentOffset = contentOffset;
}
- (void)pageControlChangedPage:(id)sender {
[self setCurrentPage:self.topToolbar.pageControl.selectedPage animated:YES];
}
......
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