Iphone UI设计-处理许多UI按钮的最佳方式

Iphone UI设计-处理许多UI按钮的最佳方式,iphone,performance,uibutton,Iphone,Performance,Uibutton,我在处理界面中的大量UIButton时遇到了问题。我想知道是否有人有这方面的第一手经验,以及他们是如何做到的 在处理30-80个按钮时,最简单的是几个复杂的按钮,您是使用UIButton还是执行不同的操作,如drawRect,响应触摸事件并获取触摸事件的坐标 最好的例子是一个日历,类似于苹果日历应用程序。您会使用drawRect绘制大部分时间,然后在单击按钮时将其替换为图像还是只使用UIButtons?与其说是内存占用或按钮的创建,不如说是因为它们有时会发生奇怪的事情(前面的问题),并且会出现性

我在处理界面中的大量UIButton时遇到了问题。我想知道是否有人有这方面的第一手经验,以及他们是如何做到的

在处理30-80个按钮时,最简单的是几个复杂的按钮,您是使用UIButton还是执行不同的操作,如drawRect,响应触摸事件并获取触摸事件的坐标

最好的例子是一个日历,类似于苹果日历应用程序。您会使用drawRect绘制大部分时间,然后在单击按钮时将其替换为图像还是只使用UIButtons?与其说是内存占用或按钮的创建,不如说是因为它们有时会发生奇怪的事情(前面的问题),并且会出现性能问题


感谢您的帮助。

我更喜欢使用图像(如果可能,单个图像或尽可能小的数字)并比较触摸位置,而不是使用30-80个UI按钮


如果我必须创建按钮,那么显然不会为它们创建30-80个变量。我将设置并获取视图标记,以确定点击了哪一个。

如果这些都是您正在制作的动画,那么您可以创建一组Calayer,并将其内容设置为CGImage。您必须比较触摸位置以识别图层。CALayers有一个有用的style属性,它是一个可以存储元数据的NSDictionary。

除非出现特定的性能问题,否则我只使用UIButtons。但是,如果它们具有类似的功能,例如键盘,我会将它们全部映射到一个iAction,并根据发送者区分行为

您遇到了哪些具体的性能和动画问题?

如果按钮出现“奇怪的事情”,您需要弄清原因。仅仅为了避免一个您不理解(并且可能再次出现)的问题而切换架构听起来不是一个好主意

-drawRect:
通过绘制到位图支持的上下文来工作。当在-setNeedsDisplay之后调用-displayIfNeeded(或者执行隐式设置needsDisplay标志的其他操作,如使用contentMode=UIContentModeRedraw调整视图大小)时,会发生这种情况。然后将位图背景合成到屏幕上

按钮的工作原理是将不同的组件(背景图像、前景图像、文本)放在不同的层中。文本在更改并合成到屏幕时绘制;图像直接合成到屏幕上

做事情的“最佳”方式通常是两者的结合。例如,您可以在-drawRect:中绘制文本和背景图像,因此在渲染时不需要合成不同的层(如果视图是“不透明的”,则可以获得额外的加速)。您可能希望通过drawRect避免全屏动画:(而且它不会与CoreAnimation很好地集成),因为绘图往往比合成更昂贵


但首先,我要找出UIButton出了什么问题。在你真正发现慢的部分是什么之前,担心如何让事情变得更快是没有什么意义的。编写代码以便易于维护。UIButton没有那么贵,-drawRect:也没那么糟糕(如果你用
-setNeedsDisplayInRect:
来计算一个小的rect,可能会更好,但是你需要计算rect…),但是如果你想要一个按钮,就用UIButton。

我最近在为iPhone开发游戏时遇到了这个问题。我用UIButtons来固定游戏的分幅,然后用透明的图像、背景色和文本将其样式化

对于少量的瓷砖来说,这一切都很好。然而,当我们到达50岁左右时,性能显著下降。搜索谷歌后,我发现其他人也遇到过同样的问题。看起来iPhone在屏幕上同时有很多透明的按钮。不确定这是UIButton代码中的错误还是设备上图形硬件的限制,但不管怎样,这都超出了程序员的控制范围

我的解决方案是使用核心图形手工绘制电路板。起初,这似乎让人望而生畏,但实际上却相当容易。我只是在Interface Builder中的ViewController上放置了一个大UIImageView,将其制作成一个IBOutlet,这样我就可以从Objective-C中修改它,然后用核心图形构建图像

由于UIImageView不处理点击,我使用UIViewController的touchesBegind方法,然后将触摸的x/y坐标三角化到游戏板上的精确磁贴上

现在,棋盘在不到十分之一秒的时间内渲染。宾果

如果您需要示例代码,请告诉我

更新:这里是我正在使用的代码的简化版本。应该足够你理解要点了

//  CoreGraphicsTestViewController.h
//  CoreGraphicsTest

#import <UIKit/UIKit.h>

@interface CoreGraphicsTestViewController : UIViewController {
    UIImageView *testImageView;

}

@property (retain, nonatomic) IBOutlet UIImageView *testImageView;


-(void) drawTile: (CGContextRef) ctx row: (int) rowNum col: (int) colNum isPressed: (BOOL) tilePressed;

@end
//CoreGraphicsTestViewController.h
//岩芯岩
#进口
@接口CoreGraphicsTestViewController:UIViewController{
UIImageView*testImageView;
}
@属性(保留,非原子)IBUIImageView*testImageView;
-(void)drawTile:(CGContextRef)ctx行:(int)rowNum列:(int)colNum显示:(BOOL)tile显示;
@结束
。。。还有.m文件

//  CoreGraphicsTestViewController.m
//  CoreGraphicsTest

#import "CoreGraphicsTestViewController.h"
#import <QuartzCore/QuartzCore.h>
#import <CoreGraphics/CoreGraphics.h>

@implementation CoreGraphicsTestViewController

@synthesize testImageView;

int iTileSize;
int iBoardSize;

- (void)viewDidLoad {
    int iRow;
    int iCol;

    iTileSize = 75;
    iBoardSize = 3;

    [testImageView setBounds: CGRectMake(0, 0, iBoardSize * iTileSize, iBoardSize * iTileSize)];


    CGRect rect = CGRectMake(0.0f, 0.0f, testImageView.bounds.size.width, testImageView.bounds.size.height);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    for (iRow = 0; iRow < iBoardSize; iRow++) {
        for (iCol = 0; iCol < iBoardSize; iCol++) {
            [self drawTile: context row: iRow col: iCol color: isPressed: NO];
        }
    }

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    [testImageView setImage: image];

    UIGraphicsEndImageContext();

    [super viewDidLoad];
}


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

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView: testImageView];

    if ((location.x >= 0) && (location.y >= 0) && (location.x <= testImageView.bounds.size.width) && (location.y <= testImageView.bounds.size.height)) {

        UIImage *theIMG = testImageView.image;

        CGRect rect = CGRectMake(0.0f, 0.0f, testImageView.bounds.size.width, testImageView.bounds.size.height);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();

        [theIMG drawInRect: rect];

        iRow = location.y / iTileSize;
        iCol = location.x / iTileSize;

        [self drawTile: context row: iRow col: iCol color: isPressed: YES];


        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

        [testImageView setImage: image];

        UIGraphicsEndImageContext();
    }
}


-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UIImage *theIMG = testImageView.image;

    CGRect rect = CGRectMake(0.0f, 0.0f, testImageView.bounds.size.width, testImageView.bounds.size.height);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    [theIMG drawInRect: rect];

    [self drawTile: context row: iRow col: iCol isPressed: NO];


    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    [testImageView setImage: image];

    UIGraphicsEndImageContext();
}

-(void) drawTile: (CGContextRef) ctx row: (int) rowNum col: (int) colNum isPressed: (BOOL) tilePressed {

    CGRect rrect = CGRectMake((colNum * iTileSize), (rowNum * iTileSize), iTileSize, iTileSize); 
    CGContextClearRect(ctx, rrect);

    if (tilePressed) {
        CGContextSetFillColorWithColor(ctx, [[UIColor redColor] CGColor]);
    } else {
        CGContextSetFillColorWithColor(ctx, [[UIColor greenColor] CGColor]);
    }

UIImage *theImage = [UIImage imageNamed:@"tile.png"];
[theImage drawInRect: rrect];
}
//CoreGraphicsTestViewController.m
//岩芯岩
#导入“CoreGraphicsTestViewController.h”
#进口
#进口
@CoreGraphicsTestViewController的实现
@综合评价;
智能化;
intiboardsize;
-(无效)viewDidLoad{
INTIROW;
国际古迹遗址理事会;
iTileSize=75;
iBoardSize=3;
[testImageView设置边界:CGRectMake(0,0,iBoardSize*iTileSize,iBoardSize*iTileSize)];
CGRect rect=CGRectMake(0.0f,0.0f,testImageView.bounds.size.width,testImageView.bounds.size.height);
UIGraphicsBeginImageContext(矩形大小);
CGContextRef context=UIGraphicsGetCurrentContext();
对于(iRow=0;iRow