UITableview: Bazı Satırlar İçin Seçimi Devre Dışı Bırakma


298

tableviewXML'den ayrıştırılmış bir grup içeriğinde görüntüleniyorum . Tıklama olayını devre dışı bırakmak istiyorum (hiç tıklayamamam gerekiyor) Tablo iki grup içeriyor. Yalnızca ilk grup için seçimi devre dışı bırakmak istiyorum ancak ikinci grup için seçimi devre dışı bırakmak istiyorum. İkinci grubun ilk sırasını tüpüme navigatestıklıyorum player view.

Yalnızca belirli grupları veya satırları nasıl seçilebilir hale getirebilirim?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if(indexPath.section!=0)
    if(indexPath.row==0)    

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:tubeUrl]];   
}

Teşekkürler.

Yanıtlar:


499

Sadece bu kodu cellForRowAtIndexPath

Hücrenin seçim özelliğini devre dışı bırakmak için: (hücreye dokunurken)

cell.selectionStyle = UITableViewCellSelectionStyleNone;

Hücreyi seçmeyi (dokunmayı) etkinleştirmek için: (hücreye dokunarak)

// Default style
cell.selectionStyle = UITableViewCellSelectionStyleBlue;

// Gray style
cell.selectionStyle = UITableViewCellSelectionStyleGray;

İle bir hücrenin kullanıcı tarafından dokunduğunda yine de kullanıcı selectionStyle = UITableViewCellSelectionStyleNone;arayüzünün çağrılmasına neden olacağını unutmayın didSelectRowAtIndexPath. Bundan kaçınmak için aşağıda önerildiği gibi yapın ve ayarlayın.

cell.userInteractionEnabled = NO;

yerine. Ayrıca cell.textLabel.enabled = NO;öğeyi grileştirmek istediğinizi de unutmayın .


1
Silmek için hızlıca kaydırmaya çalışırsanız bu yöntem hata üretir.
Vive

116
Bu hack! Bunu yapın, aşağıdaki cevabı kullanın - sıfır döndüren willSelectRowAtIndexPath kullanarak!
Peter Stajger

4
UserInteractionEnabled öğesi doğru değil, insanlar not olarak bunun yerine hookSelectRowAtIndexPath öğesini kancalayın.
Jonny

23
İOS 6.0 ve sonraki sürümlerde, iletilen öğenin vurgulanıp vurgulanmamasına bağlı olarak dönen tableView:shouldHighlightRowAtIndexPath:yeni bir UITableViewDelegateyöntemdir . 6.0 ve sonraki sürümler için oluşturuyorsanız, bu yeni API'yi kesinlikle öneririm. BOOLindexPath
cbowns

3
bunu Swift'te yapıyorsanız ve sorun yaşıyorsanız ancak burada sona cell!.selectionStyle = .Noneermişseniz, hangi kuvvetin hücreyi açacağını ayarlamanız ve özelliklerine erişmenize izin vermeniz gerekir.
Marcos

371

Bir satırı (veya satırların alt kümesini) seçilemez hale getirmek istiyorsanız , UITableViewDelegateyöntemi uygulayın -tableView:willSelectRowAtIndexPath:(TechZen tarafından da belirtilir). Eğer seçilebilirindexPath olmaması gerekiyorsa , geri dönün , aksi takdirde . Varsayılan seçim davranışını elde etmek için, iletilen yöntemi yönteminize döndürürsünüz , ancak farklı bir döndürerek satır seçimini de değiştirebilirsiniz .nilindexPathindexPathdelegateindexPath

misal:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // rows in section 0 should not be selectable
    if ( indexPath.section == 0 ) return nil;

    // first 3 rows in any section should not be selectable
    if ( indexPath.row <= 2 ) return nil;

    // By default, allow row to be selected
    return indexPath;
}

2
Küçük detay: <2 değin, değil = <2. :)
Jonas Byström

23
Ben de bu doğru cevap olduğunu eklemek istiyorum, ama aynı zamanda cellForRowAtIndexPath içinde UITableViewCellSelectionStyleNone için selectionStyle ayarlamanız gerekir. Neden? çünkü bu seçim stili olmadan hücre seçilemez, ancak dokunduğunda hala "seçili" olarak görüntülenecektir (bu nedenle diğer hücreler için bir tane varsa seçilen renge
dönüşür

4
bu, kabul edilen yanıttan daha fazla oy almalıdır
user1244109

2
Bunun kabul edilen cevap olmamasının ana sebebinin kabul edilen cevabın daha kolay olmasıdır. Bunu yapmanın 'en iyi yolu' olmasa da, tablonuz hala setSelected öğesini çağırır: hücrelerinizde, görsel olarak hala çalışır. Bu yanıt burada daha fazla çalışma gerektiriyor, ancak setSelected: hücrelerinizde çağıran tablonun öngörülemeyen sonuçlarından kaçınmak için bunu yapmanın uygun yolu (@TooManyEduardos önerisini de birleştirmeniz gerekir).
Brian Sachetta

Bu yanıtı beğendim, ancak cellForRowAtIndexPath ve willSelectRowAtIndexPath içindeki mantığınızı çoğaltmak istemiyorsanız, sadece cell.selectionStyle == none in willSelectRowAtIndexPath içinde nil döndürüp döndürmediğini kontrol edin (aşağıdaki cevabım bakın)
Eric D'Souza

61

İOS 6'dan başlayarak şunları kullanabilirsiniz:

-tableView:shouldHighlightRowAtIndexPath:

Geri dönerseniz NO, hem seçili vurgulamayı hem de o hücreye bağlı film şeridi tarafından tetiklenen sekmeleri devre dışı bırakır.

Üst üste bir dokunuş geldiğinde yöntem çağrılır. NOBu mesaja geri dönmek seçim işlemini durdurur ve dokunulmuş durumdayken seçili olan satırın seçili görünümünü kaybetmesine neden olmaz.

UITableViewDelegate Protokol Başvurusu


3
Kabul. İOS 7 ve üstü için bu tercih edilen yöntem olmalıdır (aslında iOS 8'de diğer yöntemler benim için çalışmadı.)
race_carr

Bu en iyi cevap olmalı.
Cameron E

16

Yukarıdaki cevaplardan hiçbiri sorunu gerçekten doğru bir şekilde ele almıyor. Bunun nedeni, hücre seçimini devre dışı bırakmak istiyoruz, ancak mutlaka hücre içindeki alt görüntülemeleri değil.

Benim durumumda, satırın ortasında bir UISwitch sunuyordum ve satırın geri kalanı için (boş olan) seçimi devre dışı bırakmak istedim ama anahtar için değil! Bunu yapmanın uygun yolu bu nedenle yöntemde

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

formun bir ifadesi

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

belirli bir hücrenin seçimini devre dışı bırakır, aynı zamanda kullanıcının anahtarı değiştirmesine ve böylece uygun seçiciyi kullanmasına izin verir. Birisi kullanıcı etkileşimi yoluyla kullanıcı etkileşimini devre dışı bırakırsa bu doğru değildir.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

sadece hücreyi hazırlayan ve UISwitch ile etkileşime izin vermeyen bir yöntemdir.

Ayrıca, yöntemi kullanarak

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

formun ifadesiyle hücrenin seçimini kaldırmak için

[tableView deselectRowAtIndexPath:indexPath animated:NO];

kullanıcı hücrenin orijinal içeriğine basarken seçilen satırı gösterir.

Sadece iki sentim. Birçok kişinin bunu yararlı bulacağından eminim.


Katılıyorum. willSelectRowAtIndexPathNil'e geri dönmek de aynı soruna sahip, alt görünümler seçilemez.
jeffjv

Ayrıca, statik bir tablonuz varsa, seçimin görünmesini istemediğiniz hücreler için Arabirim Oluşturucu'da Seçimi Yok olarak ayarlayabileceğinizi unutmayın.
jeffjv

11

Seçimleri bu veri kaynağı yöntemleriyle yakalarsınız.

 tableView:willSelectRowAtIndexPath: 
 tableView:didSelectRowAtIndexPath: 
 tableView:willDeselectRowAtIndexPath: 
 tableView:didDeselectRowAtIndexPath:

Bu yöntemlerde, seçilen satırın seçilebilir olmasını istediğiniz satır olup olmadığını kontrol edersiniz. Eğer öyleyse, harekete geçin, eğer değilse, hiçbir şey yapmayın.

Maalesef, yalnızca bir bölüm için seçimi kapatamazsınız. Tüm masa ya da hiçbir şey.

Ancak tablo hücreleri selectionStyleözelliğini olarak ayarlayabilirsiniz UITableViewCellSelectionStyleNone. Bunun seçimi görünmez kılacağına inanıyorum. Hücreleri, kullanıcının bakış açısından tamamen etkisiz hale getirmesi gereken yukarıdaki yöntemlerle birlikte.

Edit01:

İçinde yalnızca bazı satırların seçilebilir olduğu bir tablonuz varsa, seçilebilir satırların hücrelerinin seçilemez satırlardan görsel olarak farklı olması önemlidir. Chevron aksesuar düğmesi bunu yapmanın varsayılan yoludur.

Ancak bunu yaparsanız, kullanıcılarınızın satır seçmeye çalışmasını ve satırın hiçbir şey yapmadığı için uygulamanın hatalı olduğunu düşünmesini istemezsiniz.


lütfen bu yöntemleri nasıl kullanacağınızı veya örnek program linklerini nasıl vereceğinizi
Warrior

2
@ Savaşçı: SDK'yı yüklediyseniz, Xcode'u açabilir, adresine gidip Help -> Developer documentationnasıl çalıştığını görmek için bu yöntem adlarını arama alanına kopyalayabilirsiniz. Geliştirici belgeleri ayrıca örnek kod da içerir.
kennytm

10

İçin Swift 4.0 örneğin:

cell.isUserInteractionEnabled = false
cell.contentView.alpha = 0.5

9

cellForRowAtIndexPathYöntem içinde hücre seçimini devre dışı bırakmak için aşağıdakine benzer bir şey yapmanız gerekir :

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell setUserInteractionEnabled:NO];

Hücrenin gri olduğunu göstermek için, tableView:WillDisplayCell:forRowAtIndexPathyöntemin içine aşağıdakileri koyun :

[cell setAlpha:0.5];

Bir yöntem etkileşimi kontrol etmenizi sağlar, diğeri UI görünümünü kontrol etmenizi sağlar.


5

Yalnızca bazı hücrelerin seçilmesini durdurmak için şunu kullanın:

cell.userInteractionEnabled = NO;

Seçimi engellemenin yanı sıra, bu ayarlanmış hücreler için tableView: didSelectRowAtIndexPath: çağrılmasını da durdurur.


1
Her zaman garip bir şey olur: userInteractionEnabledBir hücrede NO (Açık) olarak ayarladığımda (daha açık bir şekilde, bir indexPath), bazı DİĞER hücrelerin kullanıcı etkileşimi devre dışı bırakılır. userInteractionEnabledTablo görünümü hücrelerinde her kullandığımda bunun neden olduğuna dair hiçbir fikrim yok . Bilinen bir hata mı yoksa yanlış bir şey mi yaptım?
Philip007

3
@ Philip007 "HAYIR" hücreler tekrar kullanılıyor mu? Öyleyse, bir hücreyi ayıkladığınız zaman "EVET" olarak ayarladığınızdan emin olmanız gerekebilir.
JosephH

1
Neden "EVET" olarak ayarladınız? Tipik bir örnek, ilk satırda (kullanıcı etkileşiminden olmasıdır .. bu bilginin (izin verilmez kullanıcı etkileşimi) olmak isteyen if [indexPath row] == 0için) NOolarak tableView:cellForRowAtIndexPath:hücre dequeueing sonra. Genellikle ilk başta Tamam çalışır. Sonra birkaç çağrıdan sonra reloadData, aniden beşinci sıraya etkileşime izin verilmiyor, sonra dördüncü sıra .. Ne zaman olacağını anlayamıyorum. Her şey rastgele görünüyor.
Philip007

6
Eğer hücreler yeniden Eğer Philip007 @, size hücreler için "EVET" sıfırlamak gerekir DO interaktif olmak istiyorum. Aksi takdirde, "NO" hücresi etkileşimli olmasını istediğiniz bir satırda yeniden kullanılırsa, devre dışı bırakılır. ie:if [indexPath row] == 0) { set to NO } else { set to YES }
JosephH

5

tableView:willDisplayCellBir tableViewCell için her türlü özelleştirme yapmak için yöntemi kullanabilirsiniz .

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
     [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
     [cell setUserInteractionEnabled:NO];

     if (indexPath.section == 1 && indexPath.row == 0)
     {
         [cell setSelectionStyle:UITableViewCellSelectionStyleGray];
         [cell setUserInteractionEnabled:YES];
     }
} 

Yukarıdaki kodda, kullanıcı yalnızca TableView öğesinin ikinci bölümünde ilk satırı seçebilir. Geri kalan tüm satırlar seçilemez. Teşekkürler! ~


5

Hızlı için:

cell.selectionStyle = .None
cell.userInteractionEnabled = false

5

Veri modeline dayalı çözümüm:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let rowDetails = viewModel.rowDetails(forIndexPath: indexPath)
    return rowDetails.enabled ? indexPath : nil
}

func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
    let rowDetails = viewModel.rowDetails(forIndexPath: indexPath)
    return rowDetails.enabled
}

5

Hızlı 4.0 için Bu işe yarayacak. DidSelectRowAtIndexPath yönteminde Hücreyi devre dışı bırakır, ancak alt görünümleri tıklanabilir tutar.

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
         if (indexPath.row == clickableIndex ) { 
            return indexPath
         }else{
            return nil
        }
    }

Veya kısaca:, return indexPath.row == clickableIndex ? indexPath : nilkodunuzu biraz daha temiz tutar ;-)
Mark

1

Hücrenin devre dışı ve seçilemez gibi görünmesini sağlamak için bunu kullanın :

cell.selectionStyle = UITableViewCellSelectionStyleNone;

Önemli: Bunun yalnızca bir stil özelliği olduğunu ve aslında hücreyi devre dışı bırakmadığını unutmayın. Bunu yapmak için selectionStyle, didSelectRowAtIndexPath:temsilci uygulamanızda kontrol etmeniz gerekir :

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if(cell.selectionStyle == UITableViewCellSelectionStyleNone) {
        return;
    }

    // do your cell selection handling here
}

1

Brian Chapados'un yukarıdaki cevabı seviyorum. Ancak bu, hem cellForRowAtIndexPath'te hem de daha sonra eşitlemeden kolayca çıkabilen willSelectRowAtIndexPath'te mantığınızın çoğaltılabileceği anlamına gelir. Mantığı çoğaltmak yerine selectionStyle'ı kontrol etmeniz yeterlidir:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (cell.selectionStyle == UITableViewCellSelectionStyleNone)
        return nil;

    else
        return indexPath;
}

1

Hem statik hem de dinamik tablolarla çalıştığı için bunu kullanışlı buldum. Yalnızca gösterime izin vermek istediğim hücrelerde açıklama göstergesini ayarladım.

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (cell.accessoryType != UITableViewCellAccessoryDisclosureIndicator) {
        return nil;
    }
    return indexPath;
}

1

kodlama yapmadan Xcode 7'de şunları yapabilirsiniz:

Anahat görünümünde Tablo Görünümü Hücresi'ni seçin. (Hücre, Tablo Görünümü Denetleyici Sahne> Tablo Görünümü Denetleyici> Tablo Görünümü altında yuvalanmıştır. Tablo görüntüleme hücresini görmek için bu nesneleri açıklamanız gerekebilir)

Özellikler denetçisinde Seçim etiketli alanı bulun ve Yok'u seçin. öznitelik denetçisi Bu seçenekle, kullanıcı dokunduğunda hücre görsel bir vurgu elde etmez.


0

BASİT

Gezinebiliyorsa cell.userInteractionEnabled = YES;hücreyi kullanın , cell.userInteractionEnabled = NO;aksi takdirde


1
Bu aynı zamanda hücre içindeki herhangi bir aksesuar görünüm ile etkileşimi önler, bu da istenen davranış olmayabilir.
Greg Brown

0

tableView:willSelectRowAtIndexPath: Yalnızca tablonuz için veri kaynağındaki yöntemi uygulayın . Yoldaki satırın vurgulanmasını istiyorsanız, belirtilen indexPath öğesini döndürün. Bunu yapmazsanız, sıfır döndürün.

Uygulamamdan bir örnek:

- (NSIndexPath *)tableView:(UITableView *)tableView
    willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    MySelectableObj* obj = [self objectAtPath:indexPath];
    if(obj==nil) return nil;
    return indexPath;
}

Bununla ilgili güzel bir şey shouldPerformSegueWithIdentifier:sender:, yukarıdaki yöntemi nil döndürürse çağrılmayacak, ancak yukarıdaki testi sadece bütünlük için tekrar ediyorum.



0

Bryan'ın cevabına katılıyorum

Eğer yaparsam

cell.isUserInteractionEnabled = false 

hücre içindeki alt görünümler kullanıcıyla etkileşime girmez.

Diğer sitede,

cell.selectionStyle = .none

seçim rengini güncellememesine rağmen didSelect yöntemini tetikler.

WillSelectRowAt kullanarak sorunumu çözdüm. Misal:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {

    if indexPath.section == 0{

        if indexPath.row == 0{
            return nil
        }

    }
    else if indexPath.section == 1{

        if indexPath.row == 0{
            return nil
        }

    }

    return indexPath

}

0

appart'ı tableView.allowsMultipleSelection = trueseçerken, bölümün geri kalan hücrelerinin seçimini kaldırmanız gerekecektir:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section does not support multiple selection {
        // deselect the rest of cells
        tableView
            .indexPathsForSelectedRows?.compactMap { $0 }
            .filter { $0.section == indexPath.section && $0.row != indexPath.row }
            .forEach { tableView.deselectRow(at: $0, animated: true) }
    }
}

-1

hızlı 3.0 için, UITableView hücresiyle kullanıcı etkileşimini devre dışı bırakmak üzere aşağıdaki kodu kullanabilirsiniz

 cell.isUserInteractionEnabled = false
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.