颜色选择器的困惑

Posted

技术标签:

【中文标题】颜色选择器的困惑【英文标题】:Color picker quandary 【发布时间】:2014-06-12 05:15:11 【问题描述】:

我正在尝试实现一个简单的颜色选择器,该颜色选择器由UIImageView 中的图像组成。当用户在其上拖动手指时,我希望相邻视图使用当前像素颜色不断更新。

我在@rdelmar 对this question on SO 的回答中找到了接近理想解决方案的东西,因此我借用了代码并对其进行了修改,以将pickedColor 发送回AddCategoryViewController 上的方法。但是,此方法 (setColorview) 不会更新 colorView

我的断点和 NSLog 显示颜色信息正在从触摸中收集、发送和接收,但显然没有应用,正如受影响的 UIView colorView 不反映颜色的事实所示。最明显的问题是属性colorView 读取null,我不明白为什么。

作为奖励,我真的希望选择器能够响应滑动手指,而不仅仅是点击。

我已经在下面包含了所有相关代码,重要的行用//************************标记

感谢收看!感谢所有帮助!

代码从这里开始,文件用--------------------------分隔:

//
//  UIView+UIView_ColorOfPoint.m
//  WMDGx
//
//

#import "UIView+UIView_ColorOfPoint.h"
#import <QuartzCore/QuartzCore.h>


@implementation UIView (UIView_ColorOfPoint)

-(UIColor *) colorOfPoint:(CGPoint)point

    unsigned char pixel[4] = 0;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixel,
                                                 1, 1, 8, 4, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast);

    CGContextTranslateCTM(context, -point.x, -point.y);

    [self.layer renderInContext:context];

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    UIColor *color = [UIColor colorWithRed:pixel[0]/255.0
                                     green:pixel[1]/255.0 blue:pixel[2]/255.0
                                     alpha:pixel[3]/255.0];
    return color;


@end




-----------------------------------------


//
//  ColorPickerView.m
//  WMDGx
//
//

#import "ColorPickerView.h"

AddCategoryViewController *addCatVC;

@implementation ColorPickerView


- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        // Initialization code
    
    return self;



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

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint loc = [touch locationInView:self];
    self.pickedColor = [self colorOfPoint:loc];
    NSLog(@"Touches began");

    //******************** For sending color info to setColorView in AddCategoryViewController
    addCatVC = [[AddCategoryViewController alloc]init];
    addCatVC.colorForColorView = self.pickedColor;

    NSLog(@"Picked color is %@",self.pickedColor);

    //******************** Call the method in AddCategoryViewController, which should display the color of the current pixel
    [addCatVC setColorview];



@end



--------------------------------


//
//  AddCategoryViewController.m
//  WMDGx
//
//

#import "AddCategoryViewController.h"

@interface AddCategoryViewController ()

@end

@implementation AddCategoryViewController

NSMutableArray *array;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];

    // Do any additional setup after loading the view.
    self.catTextField.delegate = self;
    [self.pickerImageView setUserInteractionEnabled:YES];

    self.colorView.layer.cornerRadius = 6;

    // ********************I put this NSLog here to check the status of the property self.colorView

    NSLog(@"Color view is %@",self.colorView);//_colorView  UIView * 0x8a63d30 0x08a63d30 (from Variables View)


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


- (BOOL)textFieldShouldReturn:(UITextField *)textField

    [self.catTextField resignFirstResponder];
    return YES;



-(void)setColorview // ********************This is where the backgroundColor of self.colorView should be set

    NSLog(@"colorForColorView is %@",self.colorForColorView);

    NSLog(@"Color view is %@",self.colorView); //_colorView UIView *    nil 0x00000000 (from Variables View)

    [self.colorView setBackgroundColor:self.colorForColorView]; //colorView should display the color, but doesn't

    NSLog(@"Color view is %@",self.colorView); //_colorView UIView *    nil 0x00000000 (from Variables View)

    NSLog(@"Color view color is %@",self.colorView.backgroundColor);


- (IBAction)saveButton:(UIBarButtonItem *)sender

    if (self.catTextField.text.length < 1)
    
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No category created"
                                                        message:@"Please create a new category"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    

    else if (!self.colorView.backgroundColor)
    
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No color selected"
                                                        message:@"Please select a color for your new category"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    
    else
    
        NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
        self.thisCategory = [WMDGCategory MR_createInContext:localContext];
        self.thisCategory.name = [self.catTextField.text uppercaseString];
        self.thisCategory.color = self.colorView.backgroundColor;
        [localContext MR_saveToPersistentStoreAndWait];
        [self.thisCell setUserInteractionEnabled:NO];
        [self.delegate addCatControllerDidSave];
    


- (IBAction)cancelButton:(UIBarButtonItem *)sender

    [self.delegate addCatControllerDidCancel:self.thisCategory];



@end

【问题讨论】:

【参考方案1】:

这是我用于此目的的代码。除了开始触摸之外,我还有相同的触摸移动代码,并且允许您也想要的滑动效果。我的相邻视图有一个标签 200,我根据所选颜色查找并设置它。看起来你的链接代码比我的要干净一些,但也许看到这个会很有用。

首先,当我接触到时:

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

    NSSet *allTouches = [event allTouches];

    if ([allTouches count] != 1)
        return;

    UIView *picker = [self.view viewWithTag:100];

    UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
    CGPoint p = [touch locationInView:self.view];
    if (CGRectContainsPoint(picker.frame, p))
    
        printf("Hit gradient!\n");
        p = [touch locationInView:picker];
        UIColor *c = [self getPixelColor:[UIImage imageNamed:@"gradient.png"]
                                xLoc:p.x
                                yLoc:p.y];

        UIView *display = [self.view viewWithTag:200]; // representative color
        [display setBackgroundColor:c];
    

获取颜色的代码(我相信这段代码是改编自 SO 上的其他代码):

- (UIColor*)getPixelColor:(UIImage *)image xLoc:(int)x yLoc:(int)y

    CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    const UInt8* data = CFDataGetBytePtr(pixelData);
    if (x < 0 || x >= image.size.width || y < 0 || y >= image.size.height)
    
        CFRelease(pixelData);
        return [UIColor whiteColor];
    
    int pixelInfo = ((image.size.width  * y) + x ) * 4;

    UInt8 red = data[pixelInfo];
    UInt8 green = data[(pixelInfo + 1)];
    UInt8 blue = data[pixelInfo + 2];
    UInt8 alpha = data[pixelInfo + 3];
    CFRelease(pixelData);

    UIColor* color = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];

    return color;

【讨论】:

酷!两个问题:1)你把这两块代码放在哪里? 2)这是否消除了对我包含在我的 UIView 类别的需求? 我有一个 ColorPicker UIViewController,这段代码在 ColorPicker 类中。这确实消除了对类别的需求,因为我直接查询我正在使用的图像,而不是渲染视图然后查询该像素。 (再看代码有点搞笑,因为我没有从UIImageView中抓取图片,我直接从文件中查询。理论上你可以直接在UIImageView(picker)中查询图片,但是我没有'没有测试这个。) 谢谢!我会在早上试一试,让你知道会发生什么。我仍然对那个空视图感到困惑。使用标签时结果相同。 完美运行,@Nathan!我很感激。一个挥之不去的问题是,由于您查询的是图像而不是视图,并且由于我使用的是 2x 图像,因此事情完全不相关。目前,我切换到图像的 1x 版本,一切都很好。但是,对于最终版本,我需要协调这件事,可能是通过弄清楚如何查询视图。我很高兴给你一张绿色支票和赞成票,但我很高兴听到这方面的任何指导。谢谢,朋友! 我还没有得到我正在使用的应用程序,我正在使用 2x 图像,所以我没有经过测试的答案。但是,您可以查看 UIImage 的 scale 属性以查看图像是否为 2x。然后您应该能够将触摸的偏移量缩放 2 倍。

以上是关于颜色选择器的困惑的主要内容,如果未能解决你的问题,请参考以下文章

更改时间选择器的文本颜色 [android]

更改日期选择器的文本颜色

更改 Material-UI 日期选择器的标题颜色

Element ColorPicker 颜色选择器绑定值value / v-model差异问题

如何使用本机库自定义项目选择器的背景颜色

一步步教你实现跨游览器的颜色选择器