Soru UITcrollView içinde UITableViewCell dokunma algılaması


8 özel hücreli bir masa görüşmem var. 8. hücrede, sayfalama 1 ve sayfa 2'yi (veya 3, 4 ... 10) çok yüksek bir hücreye sahip olmadan gösterebilmem için sayfalama etkin bir scrollView ekledim.

Problem scrollView ile yapamıyorum didSelectRowAtIndexPath çünkü hücre scrollView'ın arkasındadır, bu yüzden scrollView tapasını (tokatlamak değil) algılamaya çalışıyorum.

Ben dokunuşları ile oynadıBegan ve dokunurlarEnded ama asla denir (Ben sadece UIView ile çalışmak dokunur biliyorum, ama belki .....)

Herhangi bir yardım çok takdir edilir.

Teşekkürler, maksimum


22
2017-07-09 19:04


Menşei




Cevaplar:


Apple, bu durumda kendi WWDC 2014 oturumu "Gelişmiş kaydırma kayıtları" (Bkz. Demo, 8:10'dan başlayarak):

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

Tüm yapılması gereken bu, geçersiz kılmaya gerek yok touchesBegan:, touchesMoved: ve diğerleri.


Ben geçersiz kılmaya dayalı çözüm kullandım touchesBegan:, touchesMoved:, touchesEnded: ve touchesCancelled: önceden, ama bazen garip bir davranışa neden oldu: belirli bir hücre seçerken, yöntem -tableView:didSelectRowAtIndexPath: farklı indexPath ile hücre için çağrıldı.

Apple'ın çözümünün şu ana kadar hiçbir yan etkisi yok ve daha zarif görünüyor.


73
2018-06-18 11:16



Bu çözümün yalnızca olumsuz tarafı, herhangi bir etkileşimi engellemesiydi. UIButtonkaydırma görünümü içinde. Kullanmaya geri başvurdum touchesBegan: ve touchesEnded: kendim. - petehare
Bu çözüm, normal bir tablo görüntüleme hücresinin aynı seçim karakteristiklerini sağlar, bu nedenle en iyi kaydırma görünümündeki içeriğin kullanıcı etkileşimi etkinleştirilmiş olması gerekmediği sürece en iyisidir. - dwsolberg
Bu kesinlikle daha iyi bir yol gibi geliyor. - Johnny
Bu harika, teşekkürler! - Scott Berrevoets
sen benim günümü kurtardın - HDNZ


Ayrıca zarif bir çözünürlük var:

UIScrollView'dan bir alt sınıf oluşturun ve aşağıdaki yöntemleri geçersiz kılın

- (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];
}

Her dokunuşu kaydırma görünümünün süper görüntüsüne aktardıktan sonra didSelectRowAtIndexPath çağrılır.


13
2018-04-15 05:56



Bu, bu problem için en iyi ve en şık çözümdür. Teşekkür ederim! - Lescai Ionel
Hücrede düğmelerim varsa bu nasıl çalışır? - Lescai Ionel
Sorun, ScrollView'ın dokunuşlarının ana görünümüne geçilmemesidir, böylece çözüm tüm dokunma safhasındaki her dokunuşun ana görünümüne geçmesidir. Düğme hakkında endişelenmenize gerek yok, önce dokunma olayını alır. - x4snowman
Scrollview'in arkasında bir düğme vardı ve dokunuşları almadı ... Çözüm, scrollview'ın içindeki düğmeyi koymaktı. - Lescai Ionel
Düğmeyi kaydırma görünümü içine koymak istemiyorsanız, çözüm daha karmaşık olur, dokunma alanının düğme alanı içinde olup olmadığını algılayabilir, eğer öyleyse, dokunuşları süper görünüm yerine düğmeyi geçirebilirsiniz. - x4snowman


Hem uitableviewcell hem de uiscrollview alt sınıflarını çözdünüz.

İhtiyaçlarım için çalıştı. Umarım yardımcı olabilir.

maksimum


myScrollView.h


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

@end

myScrollView.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

myCell.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

RootViewController.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;
}

5
2017-07-10 14:56



Teşekkürler maske benim için çalışıyor ... Bana gerçekten çok yardımcı oluyor. - The iCoder


Seçilen cevap doğru, ancak kodu aldığım bir hatayı temel alarak güncelledim.

Alt sınıf kaydırma görünümünde aşağıdaki kodu ekleyin.

- (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];
    }
}

Eğer senin self.delegate değil UITableViewCellBu özelliği, bir özelliği hücrenizle değiştirmek yerine.

İstenmeyen sonuçları önlemek için hücre, hareket sırasında iptal dokunma olayını geri almalıdır. Aşağıdaki gibi kolayca tekrarlanabilir.

  • Hücreyi vurgulayın (kaydırma görünümünü vurgulamıyorsanız kaydırma görünümü tüm hücre üzerinde olduğunu varsayarak)
  • Hücre vurgulanırken, tablo görünümünü sürükleyin
  • Başka bir hücre seçin ve şimdi daha önce vurgulanan hücre didSelectCell belirtmek, bildirmek

Bahsetmek için bir başka nokta, sipariş önemlidir! Eğer self.delegate önce denir self.superview sonra vurgulanan durum gerçekleşmeyecek.


4
2018-03-05 06:16



Teşekkürler. Bu hata ile hiç karşılaşmadım çünkü hücrem seçilemedi. Dokundum ve yeni bir görünüm sunacağım, bu yüzden hücre seçiliyken / vurgulandığında tabloyu taşıyamıyorum. Teşekkürler, max - masgar


İhtiyaçlarım için en basit çözümü buldum:

alt sınıf UIScrollView touchesEnded yöntemini ve bildirim gönderir.

UITableview'de viewdidAppear'da bir gözlemci ekleyin (viewdiddisapp içinde kaldırın), didSelectRowForIndexPath tablosunu çağıran bir işlevi çağırmak için.

Böyle bir şey (hızlı versiyon)

// myScrollView.swift

import UIKit

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

Tablonuzda

// 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
    */

0
2017-10-03 12:21