【问题标题】:Checkbox image toggle in UITableViewCellUITableViewCell 中的复选框图像切换
【发布时间】:2009-07-23 12:42:43
【问题描述】:

我需要一些关于创建UITableViewCell 的指导,该UITableViewCell 左侧有一个可以切换的图像。图像应该是可点击的并充当切换(复选框)。

我正在苦苦挣扎的部分是:

  1. 如何检测图像上的点击并以与didSelectRowAtIndexPath 不同的方式处理这些点击?
  2. 如何在不执行[tableView reloadData] 的情况下更改图像?

【问题讨论】:

  • 您好,您如何为您的问题制作这张图片?有没有可用的软件?
  • 你从哪里得到复选标记图标?
  • 我也可以看看你从哪里得到那个复选标记图标吗?
  • @rein 你是如何创建后退按钮的(左上角)?
  • @London 这不是来自我的应用程序 - 它来自一个名为 Groceries 的应用程序。 sophiestication.com/groceries

标签: iphone cocoa-touch uitableview


【解决方案1】:

其实很简单。

只需创建一个新的 UIControl 子类并将其全部放入其中(不需要单独的控制器。)我们称之为 ToggleImageControl。

@interface ToggleImageControl : UIControl
{
   BOOL selected;
   UIImageView *imageView;
   UIImage *normalImage;
   UIImage *selectedImage;
}

为每个单元格创建一个ToggleImageControl,并将其添加到适当的位置。

ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: <frame>];
toggleControl.tag = indexPath.row;  // for reference in notifications.
[cell.contentView addSubview: toggleControl];

添加一个 UIImageView 来包含图像。为触摸事件添加目标。

- (void) viewDidLoad
{
   normalImage = [UIImage imageNamed: @"normal.png"];
   selectedImage = [UIImage imageNamed: @"selected.png"];
   imageView = [[UIImageView alloc] initWithImage: normalImage];
   // set imageView frame
   [self.view addSubview: imageView];

[self addTarget: self action: @selector(toggleImage) forControlEvents: UIControlEventTouchUpInside];

}

设置UIImageView的image属性来更新图片;这将触发重绘而没有副作用。

- (void) toggleImage
{
   selected = !selected;
   imageView.image = (selected ? selectedImage : normalImage); 

   // Use NSNotification or other method to notify data model about state change.
   // Notification example:
   NSDictionary *dict = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: self.tag forKey: @"CellCheckToggled"];
   [[NSNotificationCenter defaultCenter] postNotificationName: @"CellCheckToggled" object: self userInfo: dict];

}

你显然需要按摩一些东西。您可能希望传入两个图像名称以使其更易于重用,并且我建议您也从对象外部指定通知名称字符串(假设您正在使用通知方法。)

【讨论】:

  • 这太棒了!谢谢。一个问题,当点击 toggleImage 控件时,点击不会冒泡到 UITableViewControl 的 didSelectRowAtIndexPath。对吗?
  • 不,按钮会拦截它并阻止它被单元格看到。
  • 你能不能也让这个控件成为一个空框架并使用现有的 cell.imageView 属性来绘制实际的图像?
  • sehugg:可能。几乎任何事情都可以通过分层控制来完成。
  • 当滚动 tableview 图像消失。它显然没有工作。
【解决方案2】:

这是我正在使用的“override touchesBegan:”方法的一个实现,它很简单,似乎效果很好。

只需将此类包含在您的项目中,然后在您的tableView:cellForRowAtIndexPath: 方法中创建和配置TouchIconTableViewCell 而不是UITableView 单元格。

TouchIconTableViewCell.h:

#import <UIKit/UIKit.h>

@class TouchIconTableViewCell;

@protocol TouchIconTableViewCellDelegate<NSObject>

@required
- (void)tableViewCellIconTouched:(TouchIconTableViewCell *)cell indexPath:(NSIndexPath *)indexPath;

@end

@interface TouchIconTableViewCell : UITableViewCell {
    id<TouchIconTableViewCellDelegate> touchIconDelegate;       // note: not retained
    NSIndexPath *touchIconIndexPath;
}

@property (nonatomic, assign) id<TouchIconTableViewCellDelegate> touchIconDelegate;
@property (nonatomic, retain) NSIndexPath *touchIconIndexPath;

@end

TouchIconTableViewCell.m:

#import "TouchIconTableViewCell.h"

@implementation TouchIconTableViewCell

@synthesize touchIconDelegate;
@synthesize touchIconIndexPath;

- (void)dealloc {
    [touchIconIndexPath release];
    [super dealloc];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    CGPoint location = [((UITouch *)[touches anyObject]) locationInView:self];
    if (CGRectContainsPoint(self.imageView.frame, location)) {
        [self.touchIconDelegate tableViewCellIconTouched:self indexPath:self.touchIconIndexPath];
        return;
    }
    [super touchesBegan:touches withEvent:event];
}

@end

每次创建或重复使用单元格时,设置touchIconDelegatetouchIconIndexPath 属性。触摸您的图标时,将调用委托。然后您可以更新图标或其他任何内容。

【讨论】:

  • 抱歉,“设置 touchIconDelegate 和 touchIconIndexPath 属性”到底是什么意思?
  • 例如:// 创建单元格 TouchIconTableViewCell *cell = (TouchIconTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ident]; if (cell == nil) cell = [[[TouchIconTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ident] autorelease]; cell.touchIconDelegate = 自我; cell.touchIconIndexPath = indexPath;
  • 我喜欢。似乎比创建另一个控件来放入我的自定义表格单元格要简单一些。
【解决方案3】:

所以“..显然需要按摩一些东西..”注释的意思是“...此代码不起作用...”。

所以

- (void) viewDidLoad

应该是

- (id)initWithFrame:(CGRect)frame 
{
 if ( self = [super initWithFrame: frame] ){
  normalImage = [UIImage imageNamed: @"toggleImageNormal.png"];
  selectedImage = [UIImage imageNamed: @"toggleImageSelected.png"];
  imageView = [[UIImageView alloc] initWithImage: normalImage];

 // set imageView frame
  [self addSubview: imageView];

  [self addTarget: self action: @selector(toggleImage) forControlEvents: UIControlEventTouchDown];
 }

 return self;
}

因为- (void) viewDidLoad 永远不会被调用。

【讨论】:

    【解决方案4】:

    Apple 似乎从 2011 年 10 月 12 日起在 iOS 开发者计划中上传了“TableMultiSelect”作为示例代码。

    此代码可以启用编辑模式下的多选。

    self.tableView.allowsMultipleSelectionDuringEditing = YES;
    

    http://developer.apple.com/library/ios/#samplecode/TableMultiSelect/Introduction/Intro.html

    虽然只能从 iOS5 使用。

    几个小时后,我在 Stack Overflow 中找不到此示例代码,因此我将此信息添加到此帖子中。

    【讨论】:

    • 这是一些非常好的示例代码。感谢您提请我们注意。
    【解决方案5】:

    如果您覆盖 touchesBegan,还有一种更简单的方法可以做到这一点:您需要执行一个 if 语句来确定它是否在复选标记附近,如果它不调用 [super touchesBegan:touches withEvent:event] 并且它将表现得好像它被选中了.

    【讨论】:

      【解决方案6】:

      我会做类似的事情(由喜爱的人主演),但我认为你对 iPhone 用户的拇指要求很高,因为单元格将人们引导到另一个视图。首先,我会查看单元格上的详细信息披露选项。其中一个选项是您可以附加到的预制箭头按钮。您的来电。

      如果触摸在您的复选框上,您可能能够捕获 didSelectRowAtIndexPath 事件然后执行一些其他逻辑而不是重定向,尽管我不知道您将如何获得该位置。这意味着您可能需要找到一种方法来在它调用 didSelectRowAtIndex 路径之前获取触摸事件,我不太确定该怎么做。您是否处理过 touchesBegan 之类的问题?

      【讨论】:

      • 我链接的屏幕截图来自 Sophiestication (sophiestication.com/groceries) 的杂货应用程序。我知道这是可能的,因为该应用程序可以做到并且效果很好。我一直在避免创建自己的 UITableViewCell 类 - 到目前为止,我还没有将视图放在 contentView 中。为了正确实现 touchesBegan,我想我别无选择,只能创建自己的 UITableViewCell 类。您是如何编写代码将您的行加注为收藏夹的?
      猜你喜欢
      • 1970-01-01
      • 2012-10-08
      • 2013-02-26
      • 2015-08-29
      • 2012-06-06
      • 2017-01-03
      • 2013-12-31
      • 2012-12-06
      • 1970-01-01
      相关资源
      最近更新 更多