UITableViewCell 中的自定义 UISwitch

Posted

技术标签:

【中文标题】UITableViewCell 中的自定义 UISwitch【英文标题】:Custom UISwitch inside a UITableViewCell 【发布时间】:2015-01-02 16:32:13 【问题描述】:

我已经实现了一个非常简单的自定义 UISwitch,它使用如下触摸事件:

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event

我可以毫无问题地在我的视图中使用此控件。 Control 模拟 UISwitch,因此它可以通过拖动或点击来更改值。

我的问题是我不能让这个控件在 UITableView 的单元格内工作。只有单击似乎有效(请注意,我没有使用手势......但我之前列出的事件)但我无法“滑动”开关手柄。

我在tableView:cellForRowAtIndexPath 方法中实例化控制器,将控件添加为单元格contentView 的子视图:

[cell.contentView addSubview:customSwitch];

我认为这与 UITableView 是 UIScrollView 的事实有关,我认为触摸事件会以某种方式被它“偷走”。

// 编辑--------

这里是与 Touch 事件相关的代码。

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event

    [super beginTrackingWithTouch:touch withEvent:event];

    self.dragged = NO;

    return YES;


- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event

    if (!self.enabled) 
        return NO;
    

    [super continueTrackingWithTouch:touch withEvent:event];
    self.dragged = YES;
    CGPoint touchPoint = [touch locationInView:self];

    float centerPoint = FIXED_WIDTH / 2.0;

    [self centerOn:(touchPoint.x > centerPoint) animated:YES completion:nil];

    return YES;


- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event

    [super endTrackingWithTouch:touch withEvent:event];

    CGPoint touchPoint = [touch locationInView:self];

    BOOL currentOn = self.on;
    BOOL nextOn;

    if (self.dragged) 
        float centerPoint = FIXED_WIDTH / 2.0;
        nextOn = (touchPoint.x > centerPoint);

        [self setOn:nextOn animated:NO];
    else
        nextOn = !self.on;
        [self setOn:nextOn animated:YES];
    
    self.dragged = NO;

    if (currentOn != nextOn) 
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    

如何在不干扰 UIScrollView/UITableView 的情况下使控件在 Cell 内工作?

【问题讨论】:

您是否考虑过使用点击和平移手势? @Wain 我更喜欢使用 Touch 事件。在这种情况下有什么不同吗? 查看类似***.com/questions/9350041/…的其他问题 @MatterGoal 这不是糟糕设计的好理由。如果由于某种原因,您突然需要比屏幕显示更多的单元格,则必须完全重构此代码。通过从一开始就做好架构,更容易避免(可能)难以捉摸的错误。 您没有分享tableviewCell的任何代码,请分享tableViewCellForIndexPath中的代码 【参考方案1】:

您需要使用手势来实现自定义开关,而不是尝试直接处理事件。

手势识别器在后台工作以协调他们的事件处理,例如,这就是为什么 UIScrollView 可以在另一个 UIScrollView 内工作的原因。您需要 UITableView(实际上是 UIScrollView)的协调才能正确处理其内容中的滑动手势。

在网络上搜索 Hardy Macia 的 UICustomSwitch 示例代码,以获取在自定义控件中匹配 UISwitch 行为的良好示例。

【讨论】:

【参考方案2】:

你错过了touchesBegan:touchesMoved:吗?

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event

    [super touchesBegan:touches withEvent:event];

    // Get the only touch (multipleTouchEnabled is NO)
    UITouch* touch = [touches anyObject];

    // Track the touch
    [self beginTrackingWithTouch:touch withEvent:event];


- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event

    [super touchesMoved:touches withEvent:event];

    // Get the only touch (multipleTouchEnabled is NO)
    UITouch* touch = [touches anyObject];

    // Track the touch
    [self continueTrackingWithTouch:touch withEvent:event];

【讨论】:

致投反对票的人:愿意解释投反对票的原因吗? 你确定需要这些函数吗?我可以让开关在牢房外毫无问题地工作。 也尝试在beginTrackingWithTouchcontinueTrackingWithTouch 中实现sendActionsForControlEvents:。具体来说:分别是[self sendActionsForControlEvents: UIControlEventTouchDown];[self sendActionsForControlEvents: UIControlEventTouchDragInside] @MatterGoal 我确实读过它。也许你忽略了我上面的评论。尝试在 YOUR beginTracking 和 continueTracking 方法中添加 [self sendActionsForControlEvents: UIControlEventTouchDown];[self sendActionsForControlEvents: UIControlEventTouchDragInside]。我在我的项目中实现了这些,它对我来说非常有效。 对不起,我完全忽略了你的评论

以上是关于UITableViewCell 中的自定义 UISwitch的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 中的自定义 UISwitch

自定义 UITableViewCell 中的自定义 UIView

UITableViewCell 中的自定义标签问题

UITableVIewCell 重叠图像中的自定义按钮

在 Storyboard 中设计的自定义 UITableViewCell 中的自定义 UIView

UITableViewCell 中的自定义 UIView 中的 CAGradientLayer 问题