簡體   English   中英

UITableViewCell 內的 UIScrollView 觸摸檢測

[英]UIScrollView inside UITableViewCell touch detect

我有一個帶有 8 個自定義單元格的表格視圖。 在第 8 個單元格中,我添加了一個啟用分頁的滾動視圖,這樣我就可以顯示第 1 頁和第 2 頁(或 3、4...10)而沒有非常高的單元格。

問題出在滾動視圖上,我無法使用 didSelectRowAtIndexPath,因為單元格位於滾動視圖后面,所以我試圖檢測滾動視圖的點擊(而不是滑動)。

我玩過 touchesBegan 和 touchesEnded 但它們從未被調用(我知道 touches 僅適用於 UIView,但也許......)

非常感謝任何幫助。

謝謝,馬克斯

在這種情況下,Apple 建議使用一個技巧,在他們的WWDC 2014 session “高級滾動視圖”中(參見 8:10 開始的演示):

[cell.contentView addSubview:_scrollView];
[_scrollView setUserInteractionEnabled:NO];
[cell.contentView addGestureRecognizer:_scrollView.panGestureRecognizer];

這就是所有需要做的,不需要覆蓋touchesBegan:touchesMoved:和其他。


我使用了基於覆蓋touchesBegan:touchesMoved:touchesEnded:touchesCancelled:的解決方案,但有時它會導致奇怪的行為:當 select 某個單元格時,方法-tableView:didSelectRowAtIndexPath:被調用用於具有不同 indexPath 的單元格。

Apple的解決方案到目前為止沒有副作用,看起來更優雅。

還有一個優雅的解決方案:

從 UIScrollView 創建一個子類並覆蓋以下方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesMoved:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesCancelled:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesEnded:touches withEvent:event];
}

將每次觸摸傳遞給滾動視圖的超級視圖,然后將調用 didSelectRowAtIndexPath。

解決了 uitableviewcell 和 uiscrollview 的子類化問題。

它滿足了我的需求。 希望它可以提供幫助。

最大限度


myScrollView.h


#import <UIKit/UIKit.h>
@interface myScrollView : UIScrollView {
}

@end

我的滾動視圖.m


#import "myScrollView.h"
@implementation myScrollView


- (id)initWithFrame:(CGRect)frame {

    return [super initWithFrame:frame];
}

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event 
{   
    NSLog(@"touch scroll");
    // If not dragging, send event to next responder
    if (!self.dragging) 
        [self.nextResponder touchesEnded: touches withEvent:event]; 
    else
        [super touchesEnded: touches withEvent: event];
}

myCell.h


#import <UIKit/UIKit.h>


@interface myCell : UITableViewCell {

}

@end

我的細胞.m



#import "myCell.h"


@implementation myCell


- (id)initWithFrame:(CGRect)frame {

    return [super initWithFrame:frame];
}

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event 
{   
    NSLog(@"touch cell");
    // If not dragging, send event to next responder
    [super touchesEnded: touches withEvent: event];
}

RootViewController.h



#import <UIKit/UIKit.h>

@class myCell;
@class myScrollView;

@interface RootViewController : UITableViewController {

    myCell *cell;
    myScrollView *scrollView;
}

@end

根視圖控制器.m



#pragma mark -
#pragma mark Table view data source

// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 3;
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    // my custom cell
    cell = [[myCell alloc] init];
    if (cell == nil) {
        cell = [[[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }


    // the custom scroll view
    scrollView = [[myScrollView alloc] initWithFrame:cell.frame];
    scrollView.contentSize = CGSizeMake(640, 40);
    [cell.contentView addSubview:scrollView];

    //something to add in scrollView
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 20)];
    label.text = @"some text";
    [scrollView addSubview:label];

    // Configure the cell.

    return cell;
}

選擇的答案是正確的,但我根據我得到的錯誤更新了代碼。

在子類滾動視圖中添加以下代碼。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.dragging) {
        [super touchesMoved:touches withEvent:event];
    } else {
        if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
            [(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
        }

        [self.superview touchesMoved:touches withEvent:event];
    }
}

如果您的self.delegate不是UITableViewCell ,則將該屬性替換為您的單元格的屬性。

單元格需要在移動過程中檢索取消觸摸事件,以防止出現不希望的結果。 它可以很容易地重現如下。

  • 突出顯示單元格(假設滾動視圖在整個單元格上,如果不突出顯示滾動視圖)
  • 當單元格突出顯示時,拖動表格視圖
  • Select 任何其他單元格,現在之前突出顯示的單元格將檢索didSelectCell state

還有一點要提的是順序很重要! 如果self.delegateself.superview之前沒有被調用,那么突出顯示的 state 不會發生。

我找到了滿足我需求的最簡單的解決方案:

子類 UIScrollView touchesEnded 方法並發布通知。

在 UITableview 中,在 viewdidAppear 中添加一個觀察者(在 viewdiddisappear 中將其刪除)以調用調用 tableview didSelectRowForIndexPath 的 function。

像這樣的東西(快速版)

// myScrollView.swift

import UIKit

class myScrollView: UIScrollView {
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
            NSNotificationCenter.defaultCenter().postNotificationName("selectTVRow", object: nil)
    }
}

在您的表格視圖中:

// ItemsList.swift

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "selectFourthRow", name: "selectTVRow", object: nil)
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: "selectfourthrow", object: nil)
    }

    func selectFourthRow() {
        let rowToSelect:NSIndexPath = NSIndexPath(forRow: 4, inSection: 0);
        self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect);
    }

    /*
    .... rest of your tableview Datasource and Delegate methods...
    numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath
    */

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM