iOS 增加 UITableViewCell 中 UIButton 的触控区域
Posted
技术标签:
【中文标题】iOS 增加 UITableViewCell 中 UIButton 的触控区域【英文标题】:iOS increase touch area for UIButton in TableViewCell 【发布时间】:2015-10-13 11:38:59 【问题描述】:我的UITableViewCell
中有一个UIButton
我创建了UIButton
的子类覆盖pointInside
函数:
var touchMargin:CGFloat = 20.0
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool
let extendedArea = CGRectInset(self.bounds, -touchMargin, -touchMargin)
return CGRectContainsPoint(extendedArea, point)
但是,触摸区域并没有增加。如果我稍微触摸UIButton
之外的地方,我就会触摸到表格单元格。
由于按钮被放置在单元格中,此代码是否不起作用? 我该如何解决?
【问题讨论】:
如果没有问题,增加按钮的宽度/高度。单元格的其他子视图是什么? 【参考方案1】:斯威夫特 3
//
// ViewController.swift
// test
//
// Created by David Seek on 9/29/16.
// Copyright © 2016 David Seek. All rights reserved.
//
import UIKit
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
let button = MyButton(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
button.backgroundColor = UIColor.white
button.addedTouchArea = 50 // any value you want
button.addTarget(self, action:#selector(self.action), for: .touchUpInside)
self.view.addSubview(button)
func action()
print("touched")
class MyButton: UIButton
var addedTouchArea = CGFloat(0)
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool
let newBound = CGRect(
x: self.bounds.origin.x - addedTouchArea,
y: self.bounds.origin.y - addedTouchArea,
width: self.bounds.width + 2 * addedTouchArea,
height: self.bounds.width + 2 * addedTouchArea
)
return newBound.contains(point)
您正在创建一个尺寸为 100x100 的 UIButton
,而使用 .addedTouchArea
,您将拥有一个 UIButton - 光学尺寸仍为 100x100,但触摸区域为 150x150。
Swift 2.X
class MyButton: UIButton
var addedTouchArea = CGFloat(0)
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool
let newBound = CGRect(
x: self.bounds.origin.x - addedTouchArea,
y: self.bounds.origin.y - addedTouchArea,
width: self.bounds.width + 2 * addedTouchArea,
height: self.bounds.width + 2 * addedTouchArea
)
return newBound.contains(point)
界面生成器
如果您确实使用InterfaceBuilder
设置了按钮,请将我们的UIButton
子类应用于您的按钮。
然后为按钮设置一个出口,f.e.命名按钮XY。并将buttonXY.addedTouchArea = 50
设置在viewDidLoad
内,f.e.
UITableViewCell
因为您要求UITableViewCell
。它的工作原理完全相同。
在您的 ViewController 类中:
extension ViewController: UITableViewDelegate, UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int
return 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 1
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell") as! TableViewCell
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.myButton.addedTouchArea = 50 // any value you want
tableView.rowHeight = 200
return cell
在您的 Cell 类中:
class TableViewCell: UITableViewCell
@IBOutlet weak var myButton: MyButton!
override func awakeFromNib()
super.awakeFromNib()
// Initialization code
override func setSelected(_ selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
@IBAction func myButtonAction(_ sender: AnyObject)
print("touched")
唯一需要注意的是:插座被设置为UIButton
插座,即使我在InterfaceBuilder
中将其声明为 MyButton 的子类。我不得不手动将插座更改为MyButton
! @IBOutlet weak var myButton: MyButton!
【讨论】:
当您设置了 didSelectRowAtIndexPath 时,当您点击单元格时,表格视图是否不会进行选择。 没有。我已经在我的一个大项目以及一个像这样的项目中使用它来为你测试它。如果您点击按钮,不会触发 didSelectRowAtIndexPath。如果您点击按钮的点击区域以外的单元格,didSelectRowAtIndexPath 将 - 当然 - 被触发 @user694688 有什么消息吗? 如果按钮在堆栈视图中怎么办。 赏金怎么了?【参考方案2】:您应该在要放大的视图上覆盖 hitTest。
例如
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01)
return nil;
CGRect touchRect = CGRectInset(self.bounds, -10, -10);
if (CGRectContainsPoint(touchRect, point))
//TODO!? check supviews
return self;
return nil;
【讨论】:
【参考方案3】:首先你需要创建 UIButton 子类:
class ButtonWithTouchSize: UIButton
var touchAreaPadding: UIEdgeInsets? = nil
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool
if let inset = touchAreaPadding
let origin = CGPoint(x: 0 - inset.left, y: 0 - inset.top)
let size = CGSize(width: inset.left + bounds.width + inset.right,
height: inset.top + bounds.height + inset.bottom)
let rect = CGRect(origin: origin, size: size)
return rect.contains(point)
else
return super.point(inside: point, with: event)
如果你把一个ButtonWithTouchSize 的实例直接放到UITableViewCell contentView 中,你会得到它。但是,如果您将此实例包装在 UITableViewCell contentView 中的某个容器中,您还应该覆盖它的 point(inside:with) 方法:
class ContainerView: UIView
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool
return btn.point(inside: point, with: event)
override func layoutSubviews()
super.layoutSubviews()
btn.frame = self.bounds
private let btn: ButtonWithTouchSize = ButtonWithTouchSize()
所以,总而言之……你应该为每个超级视图覆盖 point(inside:with),它的大小小于按钮大小
【讨论】:
以上是关于iOS 增加 UITableViewCell 中 UIButton 的触控区域的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 7 iOS 9 UITableViewCell 分隔符插入问题
如何在自定义 UITableViewCell 中增加 Label 的高度