UIView में दो कोनों को गोल करें


83

कुछ समय पहले मैंने एक दृश्य के दो कोनों को गोल करने के बारे में एक प्रश्न पोस्ट किया था , और इसे बहुत अच्छी प्रतिक्रिया मिली, लेकिन इसे लागू करने में समस्याएं आ रही हैं। यहाँ मेरा दोष है: विधि:

- (void)drawRect:(CGRect)rect {
    //[super drawRect:rect]; <------Should I uncomment this?
    int radius = 5;
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath(context);
    CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
    CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
    CGContextClosePath(context);
    CGContextClip(context);
}

विधि को बुलाया जा रहा है, लेकिन दृश्य के परिणाम को प्रभावित नहीं करता है। कोई विचार क्यों?

जवाबों:


104

CACornerMask को iOS 11 में पेश किया गया है, जो व्यू लेयर में नीचे की ओर टॉपलैफ्ट, टॉपलाइट, बॉटलिफ्ट को परिभाषित करने में मदद करता है। नीचे उपयोग करने के लिए उदाहरण है।

यहाँ मैं केवल दो शीर्ष कोने को गोल करने की कोशिश करता हूँ:

myView.clipsToBounds = true
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]

FYI रेफरी:


यह अब ऐसा करने का मुहावरेदार तरीका लगता है। अच्छी पकड़!
जुम्हिन

3
ध्यान दें कि दृश्य की चौड़ाई / ऊंचाई अभी भी कम से कम दो बार कोने के त्रिज्या, या अजीब कलाकृतियों को दिखाने की आवश्यकता है। उदाहरण के लिए केवल नीचे के कोनों को गोल करना, 20 की त्रिज्या और केवल 30 परिणामों की ऊंचाई एक दृश्यमान संकरा सेल (एक पिक्सेल या दो द्वारा) में।
ग्राहम पर्क्स

ध्यान दें कि यह सही तरीका है यदि आपका दृश्य अपना फ्रेम बदलता है (संभव है कि एक विस्तृत UITextView के कारण, जैसा कि मेरे मामले में है - stackoverflow.com/questions/50926215/… )। यदि आप एक UIBezierPath सेट करते हैं, तो फ़्रेम में परिवर्तन होने पर यह स्वचालित रूप से अपडेट नहीं होगा।
thomers

यह केवल iOS 11 और इसके बाद के संस्करण से उपलब्ध हैif #available(iOS 11.0, *) { }
Tri Ngo Minh

2
बहुत बढ़िया जवाब। सेटिंग clipsToBoundsको चालू करना trueआवश्यक नहीं है। आप कोनों मुखौटा और परत को छाया जोड़ने जब सकते clipsToBoundsहै false। मेरे काम आया।
ऐयू रिस

72


जहाँ तक मुझे पता है, अगर आपको भी सबव्यू का मास्क लगाने की आवश्यकता है, तो आप CALayerमास्किंग का उपयोग कर सकते हैं । ऐसा करने के 2 तरीके हैं। पहला एक थोड़ा और अधिक सुंदर है, दूसरा एक वर्कअराउंड :-) है लेकिन यह भी तेज है। दोनों CALayerमास्किंग पर आधारित हैं । मैंने पिछले साल कुछ परियोजनाओं में दोनों विधियों का उपयोग किया है, फिर मुझे आशा है कि आप कुछ उपयोगी पा सकते हैं

समाधान 1

सबसे पहले, मैंने इस फ़ंक्शन को मक्खी के UIImageकोने पर एक छवि मुखौटा ( ) बनाने के लिए बनाया था जिसकी मुझे आवश्यकता है। इस फ़ंक्शन को अनिवार्य रूप से 5 मापदंडों की आवश्यकता होती है: छवि की सीमा और 4 कोने त्रिज्या (शीर्ष-बाएं, शीर्ष-दाएं, नीचे-बाएं और नीचे-दाएं)।


static inline UIImage* MTDContextCreateRoundedMask( CGRect rect, CGFloat radius_tl, CGFloat radius_tr, CGFloat radius_bl, CGFloat radius_br ) {  

    CGContextRef context;
    CGColorSpaceRef colorSpace;

    colorSpace = CGColorSpaceCreateDeviceRGB();

    // create a bitmap graphics context the size of the image
    context = CGBitmapContextCreate( NULL, rect.size.width, rect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast );

    // free the rgb colorspace
    CGColorSpaceRelease(colorSpace);    

    if ( context == NULL ) {
        return NULL;
    }

    // cerate mask

    CGFloat minx = CGRectGetMinX( rect ), midx = CGRectGetMidX( rect ), maxx = CGRectGetMaxX( rect );
    CGFloat miny = CGRectGetMinY( rect ), midy = CGRectGetMidY( rect ), maxy = CGRectGetMaxY( rect );

    CGContextBeginPath( context );
    CGContextSetGrayFillColor( context, 1.0, 0.0 );
    CGContextAddRect( context, rect );
    CGContextClosePath( context );
    CGContextDrawPath( context, kCGPathFill );

    CGContextSetGrayFillColor( context, 1.0, 1.0 );
    CGContextBeginPath( context );
    CGContextMoveToPoint( context, minx, midy );
    CGContextAddArcToPoint( context, minx, miny, midx, miny, radius_bl );
    CGContextAddArcToPoint( context, maxx, miny, maxx, midy, radius_br );
    CGContextAddArcToPoint( context, maxx, maxy, midx, maxy, radius_tr );
    CGContextAddArcToPoint( context, minx, maxy, minx, midy, radius_tl );
    CGContextClosePath( context );
    CGContextDrawPath( context, kCGPathFill );

    // Create CGImageRef of the main view bitmap content, and then
    // release that bitmap context
    CGImageRef bitmapContext = CGBitmapContextCreateImage( context );
    CGContextRelease( context );

    // convert the finished resized image to a UIImage 
    UIImage *theImage = [UIImage imageWithCGImage:bitmapContext];
    // image is retained by the property setting above, so we can 
    // release the original
    CGImageRelease(bitmapContext);

    // return the image
    return theImage;
}  

अब आपको कोड की कुछ लाइनों की आवश्यकता है। मैं अपने ViewController में सामान डाल viewDidLoadविधि यह तेजी से है, लेकिन आप अपने कस्टम में भी इसका उपयोग कर सकते हैं, क्योंकि UIViewके साथ layoutSubviewsउदाहरण में विधि।



- (void)viewDidLoad {

    // Create the mask image you need calling the previous function
    UIImage *mask = MTDContextCreateRoundedMask( self.view.bounds, 50.0, 50.0, 0.0, 0.0 );
    // Create a new layer that will work as a mask
    CALayer *layerMask = [CALayer layer];
    layerMask.frame = self.view.bounds;       
    // Put the mask image as content of the layer
    layerMask.contents = (id)mask.CGImage;       
    // set the mask layer as mask of the view layer
    self.view.layer.mask = layerMask;              

    // Add a backaground color just to check if it works
    self.view.backgroundColor = [UIColor redColor];
    // Add a test view to verify the correct mask clipping
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView release];

    [super viewDidLoad];
}

समाधान २

यह समाधान थोड़ा और "गंदा" है। अनिवार्य रूप से आप गोल कोने के साथ एक मुखौटा परत बना सकते हैं जिसकी आपको आवश्यकता है (सभी कोनों)। फिर आपको कोने की त्रिज्या के मूल्य से मुखौटा परत की ऊंचाई बढ़ानी चाहिए। इस तरह नीचे के गोल कोने छिपे हुए हैं और आप केवल ऊपरी गोल कोने को देख सकते हैं। मैं बस में कोड डाल viewDidLoadयह तेजी से है, क्योंकि विधि लेकिन आप अपने कस्टम में भी उपयोग कर सकते हैं UIViewके साथ layoutSubviewsउदाहरण में विधि।

  

- (void)viewDidLoad {

    // set the radius
    CGFloat radius = 50.0;
    // set the mask frame, and increase the height by the 
    // corner radius to hide bottom corners
    CGRect maskFrame = self.view.bounds;
    maskFrame.size.height += radius;
    // create the mask layer
    CALayer *maskLayer = [CALayer layer];
    maskLayer.cornerRadius = radius;
    maskLayer.backgroundColor = [UIColor blackColor].CGColor;
    maskLayer.frame = maskFrame;

    // set the mask
    self.view.layer.mask = maskLayer;

    // Add a backaground color just to check if it works
    self.view.backgroundColor = [UIColor redColor];
    // Add a test view to verify the correct mask clipping
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView release];

    [super viewDidLoad];
}

उम्मीद है की यह मदद करेगा। Ciao!


अंत में काम किया! बहुत बहुत धन्यवाद! एक के ऊपर एक फायदा क्या है?
जुम्हिन

वैसे भी CASHPELayer समाधान भी सही है। आप UIBezierPath का उपयोग करके CGPath आकर्षित कर सकते हैं (जिसे 3.2+ की आवश्यकता है) या बस CGPath विधियों (CGPathMoveToPoint, CGPathAddQuadCurveToPoint आदि) के साथ
lff

1
मैं चित्र से परिदृश्य तक रोटेशन के बाद मुखौटा को ऑटोरेस्ज़ कैसे कर सकता हूं?
चौरोबिन

लेयर जोड़ना न भूलें। YksksToBounds = YES
दिमित्री सलनिकोव

यह केवल शीर्ष और निचले दाएं कोनों को गोल करने के लिए कैसे कर सकता है?
हल

69

कुछ जवाब और टिप्पणियों के माध्यम से, मुझे पता चला कि उपयोग करना UIBezierPath bezierPathWithRoundedRectऔर CAShapeLayerसबसे सरल और सबसे सीधा रास्ता। यह बहुत ही जटिल मामलों के लिए उपयुक्त नहीं हो सकता है, लेकिन कभी-कभी कोनों को गोल करने के लिए, यह मेरे लिए तेजी से और आसानी से काम करता है।

मैंने एक सरलीकृत सहायक बनाया था जो मास्क में उपयुक्त कोने को सेट करता है:

-(void) setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
    UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(10.0, 10.0)];

    CAShapeLayer* shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];

    view.layer.mask = shape;
}

इसका उपयोग करने के लिए, बस उपयुक्त UIRectCorner enum के साथ कॉल करें, जैसे:

[self setMaskTo:self.photoView byRoundingCorners:UIRectCornerTopLeft|UIRectCornerBottomLeft];

कृपया ध्यान दें कि मेरे लिए, मैं एक समूहीकृत UITableViewCell में फ़ोटो के गोल कोनों के लिए इसका उपयोग करता हूं, 10.0 त्रिज्या मेरे लिए ठीक काम करता है, अगर उचित मूल्य को बदलने की आवश्यकता है।

संपादित करें: बस एक पहले से ही इस ( लिंक ) के रूप में बहुत ही जवाब दिया नोटिस । यदि आवश्यक हो, तो आप इस उत्तर का उपयोग अतिरिक्त सुविधा फ़ंक्शन के रूप में कर सकते हैं।


EDIT: स्विफ्ट 3 में UIView एक्सटेंशन के समान कोड

extension UIView {
    func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
        let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)

        let shape = CAShapeLayer()
        shape.path = rounded.cgPath

        self.layer.mask = shape
    }
}

इसका उपयोग करने के लिए, maskByRoundingCornerकिसी भी पर सरल कॉल करें UIView:

view.maskByRoundingCorners([.topLeft, .bottomLeft])

क्या यह अभी भी एक सीमा को जोड़ते समय संभव है?
21

2
मुझे DispatchQueue.main.async {} में फंक्शन कॉल
डालनी थी

1
@MaksimKniazev हाँ, इसे मुख्य (UI) थ्रेड से कहा जाना चाहिए। यह नियम यूआई को छूने वाले किसी भी कार्य पर लागू होता है, उन्हें मुख्य धागे से बुलाया जाना चाहिए या कुछ अजीब चीजें हो सकती हैं।
पीएल

1
केवल एक कोना गोल लगता है। @MaksimKniazev समाधान की कोशिश की या तो काम नहीं किया।
Gustavo_fringe

मुझे @Gustavo_fringe जैसी ही समस्या है, जहां शीर्ष दाएं कोने को xib के दृश्य के अंदर (रिसाइज्ड) करने के लिए क्लिप / मास्क नहीं लगाया गया है, सुनिश्चित नहीं है कि इसे अभी कैसे ठीक किया जाए।
साइबरमेव

57

मैं @ lomanf के उत्तर के लिए एक टिप्पणी में यह सब फिट नहीं कर सका। इसलिए मैं इसे एक उत्तर के रूप में जोड़ रहा हूं।

जैसे @lomanf ने कहा, आपको उपयोक्ताओं को अपने पथ की सीमा के बाहर खींचने से रोकने के लिए एक लेयर मास्क जोड़ने की आवश्यकता है। हालांकि अब ऐसा करना बहुत आसान है। जब तक आप iOS 3.2 या उच्चतर को लक्षित कर रहे हैं, तब तक आपको क्वार्ट्ज के साथ एक छवि बनाने और इसे मास्क के रूप में सेट करने की आवश्यकता नहीं है। आप बस एक के CAShapeLayerसाथ बना सकते हैं UIBezierPathऔर मास्क के रूप में उपयोग कर सकते हैं ।

इसके अलावा, लेयर मास्क का उपयोग करते समय, सुनिश्चित करें कि जिस लेयर को आप मास्क कर रहे हैं, वह मास्क को जोड़ने पर किसी भी लेयर पदानुक्रम का हिस्सा नहीं है। अन्यथा व्यवहार अपरिभाषित है। यदि आपका दृष्टिकोण पहले से ही पदानुक्रम में है, तो आपको इसे उसके पर्यवेक्षण केंद्र से निकालने की आवश्यकता है, इसे मास्क करें, फिर इसे वापस रख दें जहां यह था।

CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *roundedPath = 
  [UIBezierPath bezierPathWithRoundedRect:maskLayer.bounds
                        byRoundingCorners:UIRectCornerTopLeft |
                                          UIRectCornerBottomRight
                              cornerRadii:CGSizeMake(16.f, 16.f)];    
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [roundedPath CGPath];

//Don't add masks to layers already in the hierarchy!
UIView *superview = [self.view superview];
[self.view removeFromSuperview];
self.view.layer.mask = maskLayer;
[superview addSubview:self.view];

कोर एनीमेशन रेंडरिंग के काम करने के तरीके के कारण, मास्किंग अपेक्षाकृत धीमी गति से होने वाला ऑपरेशन है। प्रत्येक मुखौटा को एक अतिरिक्त रेंडरिंग पास की आवश्यकता होती है। इसलिए मास्क का प्रयोग संयम से करें।

इस दृष्टिकोण का एक सबसे अच्छा हिस्सा यह है कि अब आपको एक कस्टम बनाने UIViewऔर ओवरराइड करने की आवश्यकता नहीं है drawRect:। इससे आपका कोड सरल हो जाना चाहिए, और शायद इससे भी तेज।


होनहार लगता है, लेकिन दृश्य दिखाई नहीं देता है। कोई विचार क्यों?
जुमहेन

10
आप UIBezierPath को आकार देने के लिए maskLayer.bounds का उपयोग कर रहे हैं, लेकिन सीमा का मूल्य CGRectZero है। आपको मास्कलेयर.फ्रेम = self.view.bounds जैसे कोड की दूसरी पंक्ति (CASPPELayer प्रारंभ के बाद तुरंत) जोड़ने की आवश्यकता है;
lomanf

1
हाँ तुम सही हो। मैंने उस कोड को दूसरे उदाहरण से निकाला, जहां आकार की परत पहले से मौजूद थी। उसके लिए माफ़ करना।
नाथन एरोर

यह परफेक्ट काम करता है! जैसा कि ऊपर कहा गया है, मुखौटासेलेब्रिटी.फ्रेम = स्व.व्यू.बाउंड जोड़ना काम है। अन्यथा विचार नहीं दिखाते हैं।
डैनियल रिबेरो

+1 यह काफी अच्छा काम करता है। वास्तव में मुझे लगता है कि मैं लोमन के # 2 समाधान के लिए इस पद्धति को पसंद करता हूं। यह विधि आपको आसानी से विपरीत कोनों (जैसे: टॉप राइट + बॉटम लेफ्ट) के लिए आर्क्स जोड़ने की अनुमति देती है, और यह निश्चित रूप से लोमन के पहले समाधान से कम है। महान कोड नाथन!
FreeAsInBeer

30

मैंने नाथन का उदाहरण लिया है और UIViewDRY सिद्धांतों का पालन करने की अनुमति देने के लिए एक श्रेणी बनाई है । बिना और देरी के:

UIView + Roundify.h

#import <UIKit/UIKit.h>

@interface UIView (Roundify)

-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;
-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;

@end

UIView + Roundify.m

#import "UIView+Roundify.h"

@implementation UIView (Roundify)

-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
    CALayer *tMaskLayer = [self maskForRoundedCorners:corners withRadii:radii];
    self.layer.mask = tMaskLayer;
}

-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = self.bounds;

    UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:
        maskLayer.bounds byRoundingCorners:corners cornerRadii:radii];
    maskLayer.fillColor = [[UIColor whiteColor] CGColor];
    maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
    maskLayer.path = [roundedPath CGPath];

    return maskLayer;
}

@end

बुलाना:

[myView addRoundedCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                withRadii:CGSizeMake(20.0f, 20.0f)];

2
आयात करने के लिए मत भूलना <। क्वार्ट्जकोर / QuatzCore.h> .m फ़ाइल में और भी परियोजना में QuartzCore.framework जोड़ें
DEzra

+1 महान सामान, एक सवाल हालांकि, यह देखने का उद्देश्य क्या है / इसे पढ़ने के लिए पर्यवेक्षणीय है?
eladleb

@eladleb: यहां मूल कोड नाथन का था, मैंने बस इसे थोड़ा अनुकूलित किया था। मैंने जो शोध किया है, उससे मैं लेयर मास्क लगाने से पहले दृश्य को हटाने का एक वैध कारण नहीं खोज सकता। इसलिए, मेरा मानना ​​है कि उस कोड को छोड़ना सुरक्षित है।
FreeAsInBeer

@FreeAsInBeer - मैं सहमत हूँ, तो मैं इसे हटाने के लिए मतदान करूँगा, यह वास्तव में दृश्य z- क्रम को बदलता है और अधिक मुद्दे बना सकता है ..
eladleb

समस्या को हल करने के लिए मैं एक गोल दृश्य में गोल कोनों को जोड़ने के साथ आ रहा था: मैंने एक हेडर जोड़ा, गोल कोनों को जोड़ा और गोल नीचे के कोनों के साथ एक पाद जोड़ा। धन्यवाद।
रात में

24

पीएल के उत्तर पर थोड़ा विस्तार करने के लिए मैंने विधि को फिर से लिखा जैसे कि यह कुछ वस्तुओं जैसे कि UIButtonसही ढंग से गोल नहीं कर रहा था

- (void)setMaskTo:(id)sender byRoundingCorners:(UIRectCorner)corners withCornerRadii:(CGSize)radii
{
    // UIButton requires this
    [sender layer].cornerRadius = 0.0;

    UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:[sender bounds]
                                                byRoundingCorners:corners
                                                cornerRadii:radii];

    CAShapeLayer *newCornerLayer = [CAShapeLayer layer];
    newCornerLayer.frame = [sender bounds];
    newCornerLayer.path = shapePath.CGPath;
    [sender layer].mask = newCornerLayer;
}

और इसके द्वारा कॉल करें

[self setMaskTo:self.continueButton byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight withCornerRadii:CGSizeMake(3.0, 3.0)];

12

यदि आप इसे स्विफ्ट में करना चाहते हैं तो आप ए के विस्तार का उपयोग कर सकते हैं UIView। ऐसा करने से, सभी उपवर्ग निम्नलिखित विधि का उपयोग करने में सक्षम होंगे:

import QuartzCore

extension UIView {
    func roundCorner(corners: UIRectCorner, radius: CGFloat) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = maskPath.CGPath
        layer.mask = maskLayer
    }
}    

उदाहरण उपयोग:

self.anImageView.roundCorner(.topRight, radius: 10)

3

स्वीकृत उत्तर को विस्तारित करते हुए, हम इसमें पिछड़ी संगतता जोड़ते हैं। IOS 11 से पहले, view.layer.maskedCorners उपलब्ध नहीं है। तो हम ऐसा कर सकते हैं

if #available(iOS 11.0, *) {
    myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
} else {
    myView.maskByRoundingCorners([.topLeft, .topRight])
}

extension UIView{
    func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
        let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)

        let shape = CAShapeLayer()
        shape.path = rounded.cgPath

        self.layer.mask = shape
    }
}

हमने UIView एक्सटेंशन के रूप में मास्कबाउंडिंग कॉर्नर लिखा है ताकि यह कोड के पुन: उपयोग में सुधार करे।

@SachinVsSachin और @PL :) का श्रेय मैंने इसे बेहतर बनाने के लिए उनके कोड को संयुक्त किया है।


2
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(5, 5, self.bounds.size.width-10, self.bounds.size.height-10)
                                               byRoundingCorners:UIRectCornerAllCorners
                                                     cornerRadii:CGSizeMake(12.0, 12.0)];

अपनी आवश्यकता के अनुसार "AllCorners" बदलें ।


तो क्या आपको UIView में ऐसा करना है या UIViewController में ऐसा किया जा सकता है? एक बार इसे बनाने के बाद आप UIBezierPath के साथ क्या करते हैं? धन्यवाद।
स्टोनब्रीकर

2

प्रदान किए गए सभी समाधान लक्ष्य को प्राप्त करते हैं। लेकिन, UIConstraintsकभी-कभी इसे उड़ा सकते हैं।

उदाहरण के लिए, नीचे के कोनों को गोल करने की आवश्यकता है। यदि ऊंचाई या नीचे की जगह की बाधा UIView के लिए सेट की जाती है जिसे गोल करने की आवश्यकता होती है, तो कोड स्निपेट जो कोनों को गोल करते हैं उन्हें viewDidLayoutSubviewsविधि में स्थानांतरित करने की आवश्यकता होती है ।

पर प्रकाश डाला:

UIBezierPath *maskPath = [UIBezierPath
    bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:
    (UIRectCornerTopRight | UIRectCornerBottomRight) cornerRadii:CGSizeMake(16.0, 16.0)];

ऊपर कोड स्निपेट केवल शीर्ष दाएं कोने को गोल करेगा यदि यह कोड सेट किया गया है viewDidLoad। क्योंकि roundedView.boundsबाधाओं को अद्यतन करने के बाद परिवर्तन होने जा रहा है UIView


1

एक मुखौटा बनाएं और इसे दृश्य की परत पर सेट करें


मुझे यह कैसे करना है? जहां तक ​​निचले स्तर का दृश्य प्रबंधन जाता है मैं अस्थिर हूं।
जुम्हिन

1
stackoverflow.com/questions/2264083/… आपकी मदद कर सकता है
स्टीव रिगिन्स

1
ख़ुशी की बात है कि मेरा जवाब अभी भी लोगों की मदद कर रहा है!
नवन राजा

1

अपने कोड से शुरू करते हुए, आप नीचे दिए गए स्निपेट जैसी किसी चीज़ के साथ जा सकते हैं।

मुझे यकीन नहीं है कि अगर आप के बाद परिणाम की तरह है। वर्थ नोटिंग, यह भी कि, जब / जब सिस्टम ड्रॉक्टेक को कॉल करता है: फिर से, रीलेक्ट होने के लिए केवल रीरेक्ट के हिस्से के लिए पूछ रहा है, यह बहुत ही अजीब व्यवहार करने वाला है। नेवन का दृष्टिकोण , ऊपर उल्लेख किया गया है, जाने के लिए एक बेहतर तरीका हो सकता है।

 // make sure the view's background is set to [UIColor clearColor]
- (void)drawRect:(CGRect)rect
{
    CGFloat radius = 10.0;
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(context, rect.size.width/2, rect.size.height/2);
    CGContextRotateCTM(context, M_PI); // rotate so image appears right way up
    CGContextTranslateCTM(context, -rect.size.width/2, -rect.size.height/2);

    CGContextBeginPath(context);

    CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
    CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
    CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
    CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
    CGContextClip(context); 

    // now do your drawing, e.g. draw an image
    CGImageRef anImage = [[UIImage imageNamed:@"image.jpg"] CGImage];
    CGContextDrawImage(context, rect, anImage);    
}

मैंने गोल कोनों के साथ एक दृश्य पर काम किया, लेकिन मैं इसे इसके किसी भी साक्षात्कार को क्लिप नहीं कर सकता। यदि मैं अपने दृश्य के किनारे पर चौकोर कोनों के साथ एक दृश्य रखता हूं, तो यह अभी भी इसके पर्यवेक्षण के गोल कोनों को कवर करता है। कुछ पता है कि ऐसा क्यों हो रहा है?
जुम्हिन

क्योंकि क्लिपिंग -drawRect:केवल उस दृश्य को प्रभावित करती है जो आप खींच रहे हैं। आपके ड्राइंग के पूरा होने के बाद इसका सबव्यू स्वतंत्र रूप से आकर्षित करता है।
जोनाथन ग्रिप्सन

1

इस तरह से थोड़ा हैकी, लेकिन अपेक्षाकृत सरल (कोई उपवर्ग, मास्किंग, आदि) दो UIViews के लिए नहीं है। दोनों के साथ clipToBounds = YES। बच्चे के दृश्य पर गोल कोनों को सेट करें, फिर इसे माता-पिता के दृश्य के भीतर रखें ताकि आप जिस कोने को सीधे चाहते हैं वह फसली हो।

UIView* parent = [[UIView alloc] initWithFrame:CGRectMake(10,10,100,100)];
parent.clipsToBounds = YES;

UIView* child = [[UIView alloc] new];
child.clipsToBounds = YES;
child.layer.cornerRadius = 3.0f;
child.backgroundColor = [UIColor redColor];
child.frame = CGRectOffset(parent.bounds, +4, -4);


[parent addSubView:child];

उस मामले का समर्थन नहीं करता जहाँ आप दो तिरछे विपरीत कोने गोल चाहते हैं।


1

बेज़ियर पथ एक एवर है, अगर आपको अतिरिक्त कोड की आवश्यकता है तो यह मेरे लिए काम करता है: https://stackoverflow.com/a/13163693/936957

UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:_backgroundImageView.bounds 
                                 byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                                       cornerRadii:CGSizeMake(3.0, 3.0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
_backgroundImageView.layer.mask = maskLayer;
[maskLayer release];

1

UIBezierPath समाधान।

- (void) drawRect:(CGRect)rect {

    [super drawRect:rect];

    //Create shape which we will draw. 
    CGRect rectangle = CGRectMake(2, 
                                  2, 
                                  rect.size.width - 4,
                                  rect.size.height - 4);

    //Create BezierPath with round corners
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rectangle 
                                                   byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight 
                                                         cornerRadii:CGSizeMake(10.0, 10.0)];

    //Set path width
    [maskPath setLineWidth:2];

    //Set color
    [[UIColor redColor] setStroke];

    //Draw BezierPath to see it
    [maskPath stroke];
}

0

यह केवल तभी काम कर सकता है जब कुछ चीजें सही तरीके से सेट की गई हों:

  1. ClipToBounds YES पर सेट होना चाहिए
  2. अपारदर्शी को NO होना चाहिए
  3. बैकग्राउंडरोलर "क्लियरकोलर" होना चाहिए (मुझे इस पर पूरा यकीन नहीं है)
  4. contentMode को "UIContentModeRedraw" होना चाहिए क्योंकि ड्राअर को अक्सर नहीं कहा जाता है यदि यह नहीं है
  5. [सुपर drawRect: rect] को CGContextClip के बाद बुलाया जाना है
  6. आपके विचार में मनमाने ढंग से साक्षात्कार नहीं हो सकते हैं (इस पर निश्चित नहीं)
  7. कम से कम एक बार अपने ड्रॉअर को ट्रिगर करने के लिए "needDisplay:" सेट करना सुनिश्चित करें

0

मुझे पता है कि आप UITableView के शीर्ष दो कोनों को गोल करने की कोशिश कर रहे हैं, लेकिन किसी कारण से मैंने पाया है कि इसका उपयोग करने के लिए सबसे अच्छा समाधान है:

self.tableView.layer.cornerRadius = 10;

प्रोग्रामिक रूप से इसे सभी चार कोनों को गोल करना चाहिए, लेकिन किसी कारण से यह केवल शीर्ष दो को गोल करता है। ** ऊपर लिखे कोड का प्रभाव देखने के लिए कृपया नीचे स्क्रीनशॉट देखें।

आशा है कि ये आपकी मदद करेगा!

यहां छवि विवरण दर्ज करें


1
यदि यह UITableViewतत्कालीन सभी कोनों UITableViewको गोल नहीं कर रहा है तो कहीं और कोड होना चाहिए जो कि नीचे की ओर गोल कोने न बना रहा हो, या हो सकता है कि UIViewया UILabelनीचे के हिस्से को कवर कर रहा हो UITableView
जोश वल्दिविसो

-1

आपको संभवतः सीमा पर क्लिप करना होगा। लाइन जोड़ें

self.clipsToBounds = YES

उस संपत्ति को सेट करने के लिए कोड में कहीं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.