将手势识别器添加到表格单元格中的图像视图

Posted

技术标签:

【中文标题】将手势识别器添加到表格单元格中的图像视图【英文标题】:Adding a gesture recognizer to an image view in a table cell 【发布时间】:2017-07-12 05:10:56 【问题描述】:

如何将手势识别器添加到表格单元格中的UIImageView?我想要这样,如果用户点击单元格中的图像,图像将会改变并且数据模型将会更新。

我知道这需要在UITableViewController 中进行设置。如果点击单元格中的任何位置,我的代码当前可以执行命令,但我希望它仅在点击图像时执行,而不是单元格中的任何位置。

我在viewDidLoad中设置了手势识别器

override func viewDidLoad() 
    super.viewDidLoad()

    // Load sample data
    loadSampleHabits()

    // Initialize tap gesture recognizer
    var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
    // Add gesture recognizer to the view
    self.tableView.addGestureRecognizer(recognizer)

这就是函数

//action method for gesture recognizer
func tapEdit(recognizer: UITapGestureRecognizer) 
    if recognizer.state == UIGestureRecognizerState.ended 
        let tapLocation = recognizer.location(in: self.tableView)
        if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) 
            if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? HabitTableViewCell 
                print("Row Selected")

            
        
    

作为第二个问题,如果我想将手势识别器添加到单元格和单元格内的图像视图,是否有任何冲突?

【问题讨论】:

您可以尝试从您的方法中删除 if Recognizer.state == UIGestureRecognizerState.ended 条件。检查我的答案。 @b.gibson:我会适应luckyShubhra 的回答。我也在我的一个项目中的某个地方使用了相同的东西,没有遇到任何问题 如果您要在图像视图中使用UITapGestureRecognizer,则无需检查state。这实际上只与连续手势相关(如长按或平移手势)。但对我来说,仅仅使用带有图像的按钮(如ios Dev suggested)就更有意义了。 【参考方案1】:

您正在根据需要在 tableview 而不是 imageView 上添加手势识别器。您需要将代码从 viewDidLoad 移动到 cellForRowAtIndexPath 并在配置单元格时向每个单元格中的 imageView 添加手势。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
     var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
     // Add gesture recognizer to your image view
     cell.yourimageview.addGestureRecognizer(recognizer)

注意:请确保启用图像视图的userinteraction

cell.yourimageview.userInteractionEnabled = YES;

根据您的要求,我建议使用 UILongPressGestureRecognizer,因为它在手势和 didselect 中发生冲突的可能性较小。您可以在 viewDidLoad 中添加 UILongPressGestureRecognizer 并根据您的要求访问它。

let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.handleLongPress(_:)))
lpgr.minimumPressDuration = 1
tableView.addGestureRecognizer(lpgr)

定义方法为

func handleLongPress(_ gesture: UILongPressGestureRecognizer)
if gesture.state != .began  return 
let tapLocation = gesture.location(in: self.tableView)
    if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) 
        if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? HabitTableViewCell 
            print("Row Selected")

        

您可以尝试从您的方法中删除if recognizer.state == UIGestureRecognizerState.ended 条件。

UITapGestureRecognizer 是一个离散的手势,因此,当手势被识别时,您的事件处理程序只会被调用一次。您根本不必检查状态。当然,您不会收到关于 .Began 状态的调用。有关更多信息,请考虑 @Rob 和 here。

【讨论】:

在单元格中的 UIimage 上添加类似点击手势的位置相似,一个好的技巧是最小化 lpgr.minimumPressDuration = 0.01 以复制点击 效果很好!我创建了一个单选按钮组,可以无缘无故快速消除!我在两个 UIImageView 中添加了一个水龙头(两个不同的图像(circle 和 largecircle.fill.circle)。#selector 函数交换两个 UIImageView 的图像并更新链接到 Radio Button Group 状态的 NSManagedObject。函数: func tapEdit(recognizer: UITapGestureRecognizer) 成功了!他们使用相同的函数来交换按钮的状态。谢谢。【参考方案2】:

在单元格中添加这一行作为索引路径处的行

     var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
        // Add gesture recognizer to the view
        cell.yourimageviewname.addGestureRecognizer(recognizer)

cell.yourimageviewname.userInteractionEnabled = true;

【讨论】:

更改 cell.youtimageviewname.isUserInteractionEnabled = true【参考方案3】:

对于我的建议,您必须在单元格中使用UIButton,以提高性能 改进,

UIButtons

专门为此而设计,并已被 Apple 针对触控进行了广泛优化。

如果你想在单元格中使用图片,你可以使用UIButton 和里面的图片。

【讨论】:

【参考方案4】:

我曾设计过这样的解决方案。我只是在下面写了一个示例代码:

import UIKit

protocol CellImageTapDelegate 
    func tableCell(didClickedImageOf tableCell: UITableViewCell)


class SampleCell : UITableViewCell 

    var delegate : CellImageTapDelegate?
    var tapGestureRecognizer = UITapGestureRecognizer()

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        initialize()
    

    private func initialize() 
        tapGestureRecognizer.addTarget(self, action: #selector(SampleCell.imageTapped(gestureRecgonizer:)))
        self.addGestureRecognizer(tapGestureRecognizer)
    

    func imageTapped(gestureRecgonizer: UITapGestureRecognizer) 
        delegate?.tableCell(didClickedImageOf: self)
    


class ViewController: UITableViewController, CellImageTapDelegate 

    // CellImageTapDelegate
    func tableCell(didClickedImageOf tableCell: UITableViewCell) 
        if let rowIndexPath = tableView.indexPath(for: tableCell) 
            print("Row Selected of indexPath: \(rowIndexPath)")
        
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 10
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "SampleCellID", for: indexPath) as! SampleCell
        cell.delegate = self
        return cell
    

记得在情节提要中进行以下操作 1.启用imageview的用户交互 2.设置tableviewcell的类 3.设置tableviewcell的复用标识

【讨论】:

此解决方案的测试项目。 zip project on google drive 它只检测单元格是否被点击,但手势识别器没有附加到任何控件,例如 UIImageView 或 UIButton 。【参考方案5】:
// create an instance of UITapGestureRecognizer and tell it to run 
// an action we'll call "handleTap:"
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
// we use our delegate
tap.delegate = self
// allow for user interaction
cell.imageViewName.userInteractionEnabled = true
// add tap as a gestureRecognizer to tapView
cell.imageViewName.addGestureRecognizer(tap)

【讨论】:

【参考方案6】:
import UIKit

class UserInfoCell: UITableViewCell

    @IBOutlet weak var imagePlaceholder: UIImageView!


class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UIImagePickerControllerDelegate,UINavigationControllerDelegate 

    @IBOutlet weak var tableView: UITableView!


    let imagePicker = UIImagePickerController()
    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: "UserInfoCell" ,for: indexPath ) as! UserInfoCell
            let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.openGallery))

            cell.imagePlaceholder.addGestureRecognizer(recognizer)
            recognizer.numberOfTapsRequired = 1
            cell.imagePlaceholder.isUserInteractionEnabled = true
            cell.name.text = "Akshay"

            if let data = UserDefaults.standard.data(forKey: "savedImage") 
                cell.imagePlaceholder.image = UIImage(data: data as Data)
            

            return cell




    
    @objc func openGallery()
        imagePicker.sourceType = .photoLibrary
        present(imagePicker,animated:  true, completion: nil)
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) 

        let userimage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
        let imageData = userimage.jpegData(compressionQuality: 1)!
        UserDefaults.standard.setValue(imageData, forKey: "savedImage")
        print("image found")
        self.imagePicker.dismiss(animated: true, completion: nil)

        self.tableView.reloadData()
    

    override func viewDidLoad() 
        super.viewDidLoad()

        imagePicker.delegate = self
tableView.tableFooterView = UIView()

    

此代码使用 TableViewCell 内 ImageView 的 Tapgesture 从图库中选择图像

【讨论】:

以上是关于将手势识别器添加到表格单元格中的图像视图的主要内容,如果未能解决你的问题,请参考以下文章

如何从表格视图单元格中的图像手势获取 indexPath

表格视图单元格中 UIView 上的手势识别器

ios 滑动手势在子视图上未被识别,父视图上的手势

如何将手势识别器添加到collectionview单元格中的uiview

如何将手势识别器添加到 UITableViewCell 的 UIImage 和 UIButton?

我可以在 tableviewcell 中发现 tableview 手势识别器的状态吗