ইউআইভিউ স্তরের অভ্যন্তরীণ ছায়া প্রভাব?


92

আমার কাছে নিম্নলিখিত ক্যালায়ার রয়েছে:

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(8, 57, 296, 30);
gradient.cornerRadius = 3.0f;
gradient.colors = [NSArray arrayWithObjects:(id)[RGB(130, 0, 140) CGColor], (id)[RGB(108, 0, 120) CGColor], nil];
[self.layer insertSublayer:gradient atIndex:0];

আমি এটিতে একটি অভ্যন্তরীণ ছায়া প্রভাব যুক্ত করতে চাই তবে এটি কীভাবে করবেন তা সম্পর্কে আমি নিশ্চিত নই। আমি মনে করি আমাকে ড্রআরেক্ট আঁকার প্রয়োজন হবে, তবে এটি অন্যান্য ইউআইভিউ অবজেক্টগুলির শীর্ষে স্তরটি যুক্ত করবে, যেহেতু এটি কিছু বোতামের পিছনে একটি বার হওয়ার কথা, তাই আমি কী করব যে ক্ষতিতে পড়েছি?

আমি অন্য স্তরটি যুক্ত করতে পারি, তবে আবার অভ্যন্তরীণ ছায়া প্রভাব কীভাবে অর্জন করতে হবে তা নিশ্চিত নই (এটির মতো:

এখানে চিত্র বর্ণনা লিখুন

সহায়তা প্রশংসা ...

উত্তর:


108

অন্য যে কেউ কাস্টিকের পরামর্শ অনুযায়ী কোর গ্রাফিক্স ব্যবহার করে কীভাবে একটি অভ্যন্তরীণ ছায়া আঁকবেন তা ভাবছেন, তারপরে এটি: (আইওএসে প্রয়োজন অনুসারে সামঞ্জস্য করুন)

আপনার ড্রয়ারেক্টে: পদ্ধতি ...

CGRect bounds = [self bounds];
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat radius = 0.5f * CGRectGetHeight(bounds);


// Create the "visible" path, which will be the shape that gets the inner shadow
// In this case it's just a rounded rect, but could be as complex as your want
CGMutablePathRef visiblePath = CGPathCreateMutable();
CGRect innerRect = CGRectInset(bounds, radius, radius);
CGPathMoveToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x + innerRect.size.width, bounds.origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, bounds.origin.y, bounds.origin.x + bounds.size.width, innerRect.origin.y, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, innerRect.origin.y + innerRect.size.height);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height, innerRect.origin.x + innerRect.size.width, bounds.origin.y + bounds.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y + bounds.size.height);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x, bounds.origin.y + bounds.size.height, bounds.origin.x, innerRect.origin.y + innerRect.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x, innerRect.origin.y);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x, bounds.origin.y, innerRect.origin.x, bounds.origin.y, radius);
CGPathCloseSubpath(visiblePath);

// Fill this path
UIColor *aColor = [UIColor redColor];
[aColor setFill];
CGContextAddPath(context, visiblePath);
CGContextFillPath(context);


// Now create a larger rectangle, which we're going to subtract the visible path from
// and apply a shadow
CGMutablePathRef path = CGPathCreateMutable();
//(when drawing the shadow for a path whichs bounding box is not known pass "CGPathGetPathBoundingBox(visiblePath)" instead of "bounds" in the following line:)
//-42 cuould just be any offset > 0
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));

// Add the visible path (so that it gets subtracted for the shadow)
CGPathAddPath(path, NULL, visiblePath);
CGPathCloseSubpath(path);

// Add the visible paths as the clipping path to the context
CGContextAddPath(context, visiblePath); 
CGContextClip(context);         


// Now setup the shadow properties on the context
aColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 3.0f, [aColor CGColor]);   

// Now fill the rectangle, so the shadow gets drawn
[aColor setFill];   
CGContextSaveGState(context);   
CGContextAddPath(context, path);
CGContextEOFillPath(context);

// Release the paths
CGPathRelease(path);    
CGPathRelease(visiblePath);

সুতরাং, মূলত নিম্নলিখিত পদক্ষেপগুলি রয়েছে:

  1. আপনার পথ তৈরি করুন
  2. আপনার পছন্দ পূরণের রঙটি সেট করুন, প্রসঙ্গটিতে এই পথটি যুক্ত করুন এবং প্রসঙ্গটি পূরণ করুন
  3. এখন একটি বৃহত আয়তক্ষেত্র তৈরি করুন যা দৃশ্যমান পথকে আবদ্ধ করতে পারে। এই পথটি বন্ধ করার আগে দৃশ্যমান পথটি যুক্ত করুন। তারপরে পথটি বন্ধ করুন, যাতে আপনি দৃশ্যমান পথটি এটি থেকে বিয়োগ করে একটি আকার তৈরি করেন। আপনি এই পাথগুলি কীভাবে তৈরি করেছেন তার উপর নির্ভর করে আপনি ভরাট পদ্ধতিগুলি (এমনকি / বিজোড়ের শূন্যহীন ঘুর) তদন্ত করতে চাইতে পারেন। সংক্ষেপে, সাবপ্যাথগুলি "বিয়োগ" করার জন্য যখন আপনি তাদের একসাথে যুক্ত করেন, আপনাকে তাদের আঁকতে হবে (বা বরং এটি নির্মাণ করুন) বিপরীত দিকে, একটি ঘড়ির কাঁটা এবং অন্যটি ঘড়ির কাঁটার দিকের দিকে।
  4. তারপরে আপনার প্রেক্ষাপটে ক্লিপিংয়ের পথ হিসাবে আপনার দৃশ্যমান পথটি সেট করা দরকার, যাতে আপনি এর বাইরে কোনও কিছু স্ক্রিনে আঁকেন না।
  5. তারপরে প্রসঙ্গে ছায়া সেটআপ করুন, এতে অফসেট, অস্পষ্টতা এবং রঙ অন্তর্ভুক্ত রয়েছে।
  6. তারপরে এটির গর্ত দিয়ে বড় আকারটি পূরণ করুন। রঙ কোনও বিষয় নয়, কারণ আপনি যদি সবকিছু ঠিকঠাক করেন তবে আপনি এই রঙটি দেখতে পাবেন না, কেবল ছায়া।

ধন্যবাদ, তবে কি ব্যাসার্ধ সামঞ্জস্য করা সম্ভব? এটি বর্তমানে সীমানার উপর ভিত্তি করে, তবে আমি পরিবর্তে একটি সেট ব্যাসার্ধের উপর ভিত্তি করে করতে চাই (5.0f এর মতো)। উপরের কোডটি সহ, এটি অনেক বেশি গোলাকার।
রানমাদ

4
@ রুনমাদ আচ্ছা, আপনি যে কোনও ধরণের দৃশ্যমান সিজিপিথ তৈরি করতে পারেন যা আপনি চান, এখানে ব্যবহৃত উদাহরণটি কেবল এটিই, ব্রেভিটির জন্য বেছে নেওয়া একটি উদাহরণ। আপনি যদি একটি বৃত্তাকার রেক্ট তৈরি করতে চান, তবে আপনি ঠিক এর মতো কিছু করতে পারেন: সিজিপিথ দৃশ্যমানপথ = [ইউআইবিজেয়ারপ্যাথ বেজিয়ারপাথভিথরউন্ড্রাইড্রেক্ট: রেক্টার কোণার রেডিয়াস: ব্যাসার্ধ] .সিজিপিথ আশা করি এটি সহায়তা করে।
ড্যানিয়েল থর্প

4
@ ড্যানিয়েল থর্প: সুন্দর উত্তরের জন্য +1। আমি বৃত্তাকার রেক্টর পাথ কোডটি নির্ধারণ করেছি (ব্যাসার্ধটি পরিবর্তন করার সময় আপনার ভেঙে গেছে) এবং বাইরের রেক্টরের পাথ কোডটি সরল করে তুলেছি। আশা করি আপত্তি করবেন না।
রেজেক্সিডেন্ট

মাত্র 2 নয়, আমি 4 টি দিক থেকে কীভাবে সঠিকভাবে অভ্যন্তরীণ ছায়া গোছাতে পারি?
প্রোটোকল

@ প্রোটোকল আপনি অফসেটটি {0,0} এ সেট করতে পারেন, তবে একটি ছায়ার ব্যাসার্ধ ব্যবহার করুন, 4.f.
ড্যানিয়েল থর্প

47

আমি জানি আমি এই পার্টিতে দেরি করেছি, তবে এটি আমার ভ্রমণের প্রথম দিকে খুঁজে পেতে সহায়তা করবে ...

ক্রেডিট দেওয়ার ক্ষেত্রে creditণ দেওয়ার জন্য, এটি মূলত কাস্টিকের বৃহত্তর অঞ্চল থেকে ছোট অঞ্চলকে বিয়োগ করার সমাধান সম্পর্কে ড্যানিয়েল থর্পের সম্প্রসারণের একটি পরিবর্তন ification এই সংস্করণটি ওভাররাইডের পরিবর্তে স্তর রচনা ব্যবহার করার জন্য-drawRect:

CAShapeLayerবর্গ একই প্রভাব অর্জন করার জন্য ব্যবহার করা যেতে পারে:

CAShapeLayer* shadowLayer = [CAShapeLayer layer];
[shadowLayer setFrame:[self bounds]];

// Standard shadow stuff
[shadowLayer setShadowColor:[[UIColor colorWithWhite:0 alpha:1] CGColor]];
[shadowLayer setShadowOffset:CGSizeMake(0.0f, 0.0f)];
[shadowLayer setShadowOpacity:1.0f];
[shadowLayer setShadowRadius:5];

// Causes the inner region in this example to NOT be filled.
[shadowLayer setFillRule:kCAFillRuleEvenOdd];

// Create the larger rectangle path.
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));

// Add the inner path so it's subtracted from the outer path.
// someInnerPath could be a simple bounds rect, or maybe
// a rounded one for some extra fanciness.
CGPathAddPath(path, NULL, someInnerPath);
CGPathCloseSubpath(path);

[shadowLayer setPath:path];
CGPathRelease(path);

[[self layer] addSublayer:shadowLayer];

এই মুহুর্তে, যদি আপনার প্যারেন্ট লেয়ারটি তার সীমানায় মাস্কিং না করে তবে আপনি স্তরের প্রান্তগুলির চারপাশে মুখোশ স্তরের অতিরিক্ত অঞ্চল দেখতে পাবেন। আপনি যদি সরাসরি উদাহরণটি অনুলিপি করেন তবে এটি 42 পিক্সেল কালো হবে। এ থেকে মুক্তি পেতে আপনি CAShapeLayerএকই পথের সাহায্যে অন্যকে ব্যবহার করতে পারেন এবং এটিকে ছায়া স্তরটির মুখোশ হিসাবে সেট করতে পারেন:

CAShapeLayer* maskLayer = [CAShapeLayer layer];
[maskLayer setPath:someInnerPath];
[shadowLayer setMask:maskLayer];

আমি নিজেই এটি বেঞ্চমার্ক করিনি, তবে আমার সন্দেহ হয় যে রাস্টেরাইজেশনের সাথে এই পদ্ধতিটি ব্যবহার করা ওভাররাইডের চেয়ে আরও পারফরম্যান্স -drawRect:


4
কিছু ইননারপথ? আপনি কি আরও একটু দয়া করে ব্যাখ্যা করতে পারেন?
মো

4
@ মাই এটি আপনার যে কোনও স্বেচ্ছাসেবী সিজিপিথ হতে পারে। [[UIBezierPath pathWithRect:[shadowLayer bounds]] CGPath]সহজ পছন্দ হচ্ছে।
ম্যাট ওয়াইল্ডিং

এই ম্যাটটির জন্য চিয়ার্স :-)
মো

আমি ছায়া লেয়ার.পাথের জন্য একটি কালো (বাহ্যিক) আয়তক্ষেত্র পেয়ে যা সঠিকভাবে অন্তরের ছায়াকে আঁকবে। আমি কীভাবে এটি থেকে মুক্তি পেতে পারি (কালো বাইরের আয়তক্ষেত্রটি)? দেখে মনে হচ্ছে আপনি কেবল একটি প্রসঙ্গের মধ্যে ফিলকলার সেট করতে পারেন এবং আপনি এটি ব্যবহার করেন না।
অলিভিয়ার

11
এটি খুব সুন্দর কাজ করে! আমি কিছু সংযোজন সহ গিথুবে আপলোড করেছি। একবার চেষ্টা করুন :) github.com/inamiy/YInnerShadowView
inamiy

35

সীমানার বাইরে একটি বড় আয়তক্ষেত্রের পথ তৈরি করে, একটি চৌম্বকীয় আকারের আয়তক্ষেত্র পথটি বিয়োগ করে এবং ফলাফলটিকে "সাধারণ" ছায়া দিয়ে পূরণ করে কোর গ্রাফিক্সের সাথে একটি অভ্যন্তরীণ ছায়া আঁকানো সম্ভব।

তবে, যেহেতু আপনাকে এটিকে গ্রেডিয়েন্ট স্তরটির সাথে একত্রিত করা দরকার তাই আমি মনে করি একটি সহজ সমাধান হ'ল অভ্যন্তরের ছায়ার 9-অংশের স্বচ্ছ পিএনজি চিত্র তৈরি করা এবং এটি সঠিক আকারে প্রসারিত করা। 9-অংশের ছায়া চিত্রটি দেখতে এটির মতো হবে (এর আকার 21x21 পিক্সেল):

বিকল্প পাঠ

CALayer *innerShadowLayer = [CALayer layer];
innerShadowLayer.contents = (id)[UIImage imageNamed: @"innershadow.png"].CGImage;
innerShadowLayer.contentsCenter = CGRectMake(10.0f/21.0f, 10.0f/21.0f, 1.0f/21.0f, 1.0f/21.0f);

তারপরে ইন্টার্নশ্যাডো লাইয়ারের ফ্রেম সেট করুন এবং এটি ছায়াটি সঠিকভাবে প্রসারিত করা উচিত।


হ্যাঁ, আমি মনে করি আপনি ঠিক বলেছেন যতটা সম্ভব স্তরটি সমতল হতে চেয়েছিল। আমি অভ্যন্তরীণ ছায়া এবং গ্রেডিয়েন্ট বর্ণের সাহায্যে ফটোশপে ছবিটি তৈরি করতে পারতাম, ইমেজ ব্যবহার করার সময় আমার কেবল ডিভাইসে 100% এর সাথে মিল থাকা রঙগুলির সাথে সমস্যা রয়েছে।
রানমাড

হ্যাঁ, এটি সমস্ত গ্রেডিয়েন্টস এবং ছায়াগুলির সাথে একটি সমস্যা, আমি চেষ্টা করছি যতটা শক্ত, আমি iOS এ এই ফটোশপ প্রভাবগুলি 1: 1 টি পুনরুত্পাদন করতে পারি না।
কাস্টিক

31

স্লিফ্টে কেবল একটি কালায়ার ব্যবহার করে একটি সরলিকৃত সংস্করণ:

import UIKit

final class FrameView : UIView {
    init() {
        super.init(frame: CGRect.zero)
        backgroundColor = UIColor.white
    }

    @available(*, unavailable)
    required init?(coder decoder: NSCoder) { fatalError("unavailable") }

    override func layoutSubviews() {
        super.layoutSubviews()
        addInnerShadow()
    }

    private func addInnerShadow() {
        let innerShadow = CALayer()
        innerShadow.frame = bounds
        // Shadow path (1pt ring around bounds)
        let path = UIBezierPath(rect: innerShadow.bounds.insetBy(dx: -1, dy: -1))
        let cutout = UIBezierPath(rect: innerShadow.bounds).reversing()
        path.append(cutout)
        innerShadow.shadowPath = path.cgPath
        innerShadow.masksToBounds = true
        // Shadow properties
        innerShadow.shadowColor = UIColor(white: 0, alpha: 1).cgColor // UIColor(red: 0.71, green: 0.77, blue: 0.81, alpha: 1.0).cgColor
        innerShadow.shadowOffset = CGSize.zero
        innerShadow.shadowOpacity = 1
        innerShadow.shadowRadius = 3
        // Add
        layer.addSublayer(innerShadow)
    }
}

নোট করুন যে ইনারশ্যাডো স্তরটির একটি অস্বচ্ছ পটভূমি রঙ হওয়া উচিত নয় কারণ এটি ছায়ার সামনে রেন্ডার হবে।


শেষ লাইনে 'স্তর' রয়েছে। এটা কোথা থেকে আসে?
চার্লি সেলিগম্যান

@ চার্লি সেলিগম্যান এটি মূল স্তর, যা কোনও স্তর হতে পারে। আপনি একটি কাস্টম স্তর বা দৃশ্যের স্তরটি ব্যবহার করতে পারেন (ইউআইভিউ-র একটি স্তরের সম্পত্তি রয়েছে)।
প্যাট্রিক পিজনাপেল

হওয়া উচিত let innerShadow = CALayer(); innerShadow.frame = bounds। যথাযথ সীমা ছাড়াই এটি যথাযথ ছায়া আঁকবে না। যাইহোক ধন্যবাদ
হাইক.আম্পার্ডজিয়ান

@ নীর_এগল সত্য, যদিও আপনি সম্ভবত এটি সেট করতে চান layoutSubviews()এটি সামঞ্জস্য রাখতে
প্যাট্রিক পিজনাপেল

ঠিক! হয় layoutSubviews()বা এর মধ্যেdraw(_ rect)
haik.ampardjian

24

প্রায় চারদিকে যাওয়ার উপায়, তবে এটি চিত্র ব্যবহার করা এড়ানো যায় (পড়ুন: রং পরিবর্তন করা সহজ, ছায়ার ব্যাসার্ধ ইত্যাদি) এবং এটি কোডের কয়েকটি লাইন।

  1. আপনি যে ড্রিফ্যাডো চালু করতে চান তা ইউআইভিউর প্রথম সাবভিউ হিসাবে একটি ইউআইআইমেজভিউ যুক্ত করুন। আমি আইবি ব্যবহার করি, তবে আপনি একই প্রোগ্রামিয়ালি করতে পারেন।

  2. ইউআইআইমেজভিউয়ের রেফারেন্সটি ধরে নেওয়া 'ইন্টার্ন শ্যাডো'

`

[[innerShadow layer] setMasksToBounds:YES];
[[innerShadow layer] setCornerRadius:12.0f];        
[[innerShadow layer] setBorderColor:[UIColorFromRGB(180, 180, 180) CGColor]];
[[innerShadow layer] setBorderWidth:1.0f];
[[innerShadow layer] setShadowColor:[UIColorFromRGB(0, 0, 0) CGColor]];
[[innerShadow layer] setShadowOffset:CGSizeMake(0, 0)];
[[innerShadow layer] setShadowOpacity:1];
[[innerShadow layer] setShadowRadius:2.0];

ক্যাভেট: আপনার একটি সীমানা থাকতে হবে, অন্যথায় ছায়া দেখা যাচ্ছে না। [ইউআইকলার ক্লিয়ার কালার] কাজ করে না। উদাহরণস্বরূপ আমি অন্যরকম রঙ ব্যবহার করি তবে ছায়ার শুরুর মতোই রঙটি পেতে এটির সাথে আপনি গোলযোগ করতে পারেন। :)

UIColorFromRGBম্যাক্রো সম্পর্কে নীচে ব্র্যাব্রেমের মন্তব্য দেখুন ।


আমি এটি ছেড়ে দিয়েছি তবে ধরে নিই আপনি চিত্রের ভিউ যুক্ত করার অংশ হিসাবে এটি করতেন - ফ্রেমটি প্যারেন্ট ইউআইভিউয়ের মতো একই রেক্টে সেট করতে ভুলবেন না। আপনি যদি আইবি ব্যবহার করছেন, আপনি যদি পিতামাতার দৃশ্যের ফ্রেমটি পরিবর্তন করছেন তবে দৃশ্যের সাথে ছায়া আকারের জন্য সঠিক স্ট্রুটস এবং স্প্রিংস সেট করুন। কোডে একটি পুনরায় আকারের মাস্ক থাকা উচিত যা আপনি এটি করতে পারেন বা এএফআইকে।
জিঙ্গলেস্তুলা

এটি এখন সবচেয়ে সহজ উপায়, তবে সচেতন থাকুন যে কালায়ার ছায়া পদ্ধতিগুলি কেবল আইওএস 3.2 এবং তারপরে পাওয়া যায়। আমি ৩.১ সমর্থন করি, তাই আমি যদি এই বৈশিষ্ট্যগুলি সেট করে নেওয়ার আশেপাশে থাকি তবে ([স্তর প্রতিক্রিয়াশীলতা: @ নির্বাচক (সেটশ্যাডো রঙ) :)] {
ডগডাব্লু

এটি আমার পক্ষে কাজ করে না বলে মনে হচ্ছে। কমপক্ষে xcode 4.2 এবং ios সিমুলেটারে 4.3। ছায়াটি হাজির করার জন্য আমাকে একটি পটভূমি রঙ যুক্ত করতে হবে ... যে বিন্দুতে ড্রপস্যাডো কেবল বাইরে দেখা যায়।
Andrea

@ আন্ড্রেয়া - আমি উপরে উল্লিখিত যে সতর্কতার বিষয়টি মনে রাখি। আমি মনে করি একটি পটভূমির রঙ বা একটি সীমানার 'ছায়াকে যুক্ত করতে কিছু দেওয়ার জন্য' এর একই প্রভাব থাকতে পারে। এটি বাইরে উপস্থিত হিসাবে, যদি ইউআইআইমেজভিউ আপনার যে অভ্যন্তরীণ ছায়াটি হতে পারে এটির একটি সংক্ষিপ্তসার না হয় - আপনার কোডটি দেখতে আমার দেখতে হবে।
জিঙ্গলেস্টুলা

কেবল আমার পূর্ববর্তী বিবৃতিটি সংশোধন করতে ... কোডটি আসলে কাজ করে ... আমি কিছু অনুপস্থিত ছিলাম তবে দুর্ভাগ্যক্রমে আমি এখনই এটি মনে করতে পারি না। :) তাই ... এই কোড স্নিপেট ভাগ করে নেওয়ার জন্য ধন্যবাদ।
অ্যান্ড্রিয়ার

17

আগের চেয়ে ভাল দেরী ...

এখানে আরও একটি পদ্ধতির উপায় রয়েছে, সম্ভবত ইতিমধ্যে পোস্ট করা এর চেয়ে ভাল আর কিছু নয়, তবে এটি দুর্দান্ত এবং সাধারণ -

-(void)drawInnerShadowOnView:(UIView *)view
{
    UIImageView *innerShadowView = [[UIImageView alloc] initWithFrame:view.bounds];

    innerShadowView.contentMode = UIViewContentModeScaleToFill;
    innerShadowView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [view addSubview:innerShadowView];

    [innerShadowView.layer setMasksToBounds:YES];

    [innerShadowView.layer setBorderColor:[UIColor lightGrayColor].CGColor];
    [innerShadowView.layer setShadowColor:[UIColor blackColor].CGColor];
    [innerShadowView.layer setBorderWidth:1.0f];

    [innerShadowView.layer setShadowOffset:CGSizeMake(0, 0)];
    [innerShadowView.layer setShadowOpacity:1.0];

    // this is the inner shadow thickness
    [innerShadowView.layer setShadowRadius:1.5];
}

@ সোমামন কি কেবল নির্দিষ্ট দিকের সাথে ছায়া স্থাপন সম্ভব? যেমন কেবল শীর্ষ বা উপরে / নীচে বা উপরে / ডান ইত্যাদিতে ..
মিতেশ ডোবারিয়া

8

ড্রয়ারেক্ট দ্বারা অভ্যন্তরীণ ছায়া আঁকার পরিবর্তে বা ভিউতে ইউআইভিউ যুক্ত করুন। আপনি সরাসরি সীমানায় ক্যালায়ার যুক্ত করতে পারেন, উদাহরণস্বরূপ: আমি যদি ইউআইভিউ ভি এর নীচে অভ্যন্তরীণ ছায়া প্রভাব চাই।

innerShadowOwnerLayer = [[CALayer alloc]init];
innerShadowOwnerLayer.frame = CGRectMake(0, V.frame.size.height+2, V.frame.size.width, 2);
innerShadowOwnerLayer.backgroundColor = [UIColor whiteColor].CGColor;

innerShadowOwnerLayer.shadowColor = [UIColor blackColor].CGColor;
innerShadowOwnerLayer.shadowOffset = CGSizeMake(0, 0);
innerShadowOwnerLayer.shadowRadius = 10.0;
innerShadowOwnerLayer.shadowOpacity = 0.7;

[V.layer addSubLayer:innerShadowOwnerLayer];

এটি লক্ষ্য ইউআইভিউয়ের জন্য নীচের অভ্যন্তরীণ ছায়া যুক্ত করে


6

এখানে সুইফ্ট, পরিবর্তন startPointএবং endPointপ্রতিটি পাশে এটির জন্য একটি সংস্করণ রয়েছে ।

        let layer = CAGradientLayer()
        layer.startPoint    = CGPointMake(0.5, 0.0);
        layer.endPoint      = CGPointMake(0.5, 1.0);
        layer.colors        = [UIColor(white: 0.1, alpha: 1.0).CGColor, UIColor(white: 0.1, alpha: 0.5).CGColor, UIColor.clearColor().CGColor]
        layer.locations     = [0.05, 0.2, 1.0 ]
        layer.frame         = CGRectMake(0, 0, self.view.frame.width, 60)
        self.view.layer.insertSublayer(layer, atIndex: 0)

আমার জন্য কাজ করেছেন !! ধন্যবাদ.
iUser

5

এটি আপনার সমাধান, যা আমি পেইন্টকোড থেকে রফতানি করেছি :

-(void) drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    //// Shadow Declarations
    UIColor* shadow = UIColor.whiteColor;
    CGSize shadowOffset = CGSizeMake(0, 0);
    CGFloat shadowBlurRadius = 10;

    //// Rectangle Drawing
    UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: self.bounds];
    [[UIColor blackColor] setFill];
    [rectanglePath fill];

    ////// Rectangle Inner Shadow
    CGContextSaveGState(context);
    UIRectClip(rectanglePath.bounds);
    CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL);

    CGContextSetAlpha(context, CGColorGetAlpha([shadow CGColor]));
    CGContextBeginTransparencyLayer(context, NULL);
    {
        UIColor* opaqueShadow = [shadow colorWithAlphaComponent: 1];
        CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, [opaqueShadow CGColor]);
        CGContextSetBlendMode(context, kCGBlendModeSourceOut);
        CGContextBeginTransparencyLayer(context, NULL);

        [opaqueShadow setFill];
        [rectanglePath fill];

        CGContextEndTransparencyLayer(context);
    }
    CGContextEndTransparencyLayer(context);
    CGContextRestoreGState(context);
}

3

আমি পার্টিতে খুব দেরি করেছি তবে আমি সম্প্রদায়কে ফিরিয়ে দিতে চাই .. এটি ইউআইটিেক্সটফিল্ড ব্যাকগ্রাউন্ড চিত্রটি সরাতে আমি লিখেছিলাম এমন একটি স্ট্যাটিক লাইব্রেরি এবং কোনও সংস্থান সরবরাহ করার জন্য ... আমি এটি ব্যবহার করেছি চারটি ইউআইটিেক্সটফিল্ড দৃষ্টান্তের একটি পিন এন্ট্রি স্ক্রিন যা একটি অক্ষর কাঁচা বা (বিওএল) [স্ব-ব্যবহারকারীর বুলেটস] বা (বিওওএল) [স্ব-ব্যবহারআস্টারিস্কস] ভিউকন্ট্রোলারে প্রদর্শন করতে পারে। অ্যাপ্লিকেশনটি আইফোন / আইফোন রেটিনা / আইপ্যাড / আইপ্যাড রেটিনার জন্য তাই আমাকে চারটি চিত্র সরবরাহ করতে হবে না ...

#import <QuartzCore/QuartzCore.h>

- (void)setTextFieldInnerGradient:(UITextField *)textField
{

    [textField setSecureTextEntry:self.isUsingBullets];
    [textField setBackgroundColor:[UIColor blackColor]];
    [textField setTextColor:[UIColor blackColor]];
    [textField setBorderStyle:UITextBorderStyleNone];
    [textField setClipsToBounds:YES];

    [textField.layer setBorderColor:[[UIColor blackColor] CGColor]];
    [textField.layer setBorderWidth:1.0f];

    // make a gradient off-white background
    CAGradientLayer *gradient = [CAGradientLayer layer];
    CGRect gradRect = CGRectInset([textField bounds], 3, 3);    // Reduce Width and Height and center layer
    gradRect.size.height += 2;  // minimise Bottom shadow, rely on clipping to remove these 2 pts.

    gradient.frame = gradRect;
    struct CGColor *topColor = [UIColor colorWithWhite:0.6f alpha:1.0f].CGColor;
    struct CGColor *bottomColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor;
    // We need to use this fancy __bridge object in order to get the array we want.
    gradient.colors = [NSArray arrayWithObjects:(__bridge id)topColor, (__bridge id)bottomColor, nil];
    [gradient setCornerRadius:4.0f];
    [gradient setShadowOffset:CGSizeMake(0, 0)];
    [gradient setShadowColor:[[UIColor whiteColor] CGColor]];
    [gradient setShadowOpacity:1.0f];
    [gradient setShadowRadius:3.0f];

    // Now we need to Blur the edges of this layer "so it blends"
    // This rasterizes the view down to 4x4 pixel chunks then scales it back up using bilinear filtering...
    // it's EXTREMELY fast and looks ok if you are just wanting to blur a background view under a modal view.
    // To undo it, just set the rasterization scale back to 1.0 or turn off rasterization.
    [gradient setRasterizationScale:0.25];
    [gradient setShouldRasterize:YES];

    [textField.layer insertSublayer:gradient atIndex:0];

    if (self.usingAsterisks) {
        [textField setFont:[UIFont systemFontOfSize:80.0]];
    } else {
        [textField setFont:[UIFont systemFontOfSize:40.0]];
    }
    [textField setTextAlignment:UITextAlignmentCenter];
    [textField setEnabled:NO];
}

আমি আশা করি এই ফোরামটি যেমন আমাকে সহায়তা করেছে তেমন এটি কাউকে সহায়তা করে।


3

মহান নিবন্ধ চেক কোয়ার্টজ মধ্যে ইনার ছায়া দ্বারা ক্রিস সিরিশ কোনটা ব্যাখ্যা কিভাবে ভেতরের ছায়া দ্বারা টানা হয় PaintCode এবং একটি পরিষ্কার এবং ঝরঝরে কোড স্নিপেট দেয়:

- (void)drawInnerShadowInContext:(CGContextRef)context
                        withPath:(CGPathRef)path
                     shadowColor:(CGColorRef)shadowColor
                          offset:(CGSize)offset
                      blurRadius:(CGFloat)blurRadius 
{
    CGContextSaveGState(context);

    CGContextAddPath(context, path);
    CGContextClip(context);

    CGColorRef opaqueShadowColor = CGColorCreateCopyWithAlpha(shadowColor, 1.0);

    CGContextSetAlpha(context, CGColorGetAlpha(shadowColor));
    CGContextBeginTransparencyLayer(context, NULL);
        CGContextSetShadowWithColor(context, offset, blurRadius, opaqueShadowColor);
        CGContextSetBlendMode(context, kCGBlendModeSourceOut);
        CGContextSetFillColorWithColor(context, opaqueShadowColor);
        CGContextAddPath(context, path);
        CGContextFillPath(context);
    CGContextEndTransparencyLayer(context);

    CGContextRestoreGState(context);

    CGColorRelease(opaqueShadowColor);
}

3

সুইফট ৪.২ এ আমার সমাধান এখানে is আপনি চেষ্টা করতে চান?

final class ACInnerShadowLayer : CAShapeLayer {

  var innerShadowColor: CGColor? = UIColor.black.cgColor {
    didSet { setNeedsDisplay() }
  }

  var innerShadowOffset: CGSize = .zero {
    didSet { setNeedsDisplay() }
  }

  var innerShadowRadius: CGFloat = 8 {
    didSet { setNeedsDisplay() }
  }

  var innerShadowOpacity: Float = 1 {
    didSet { setNeedsDisplay() }
  }

  override init() {
    super.init()

    masksToBounds = true
    contentsScale = UIScreen.main.scale

    setNeedsDisplay()
  }

  override init(layer: Any) {
      if let layer = layer as? InnerShadowLayer {
          innerShadowColor = layer.innerShadowColor
          innerShadowOffset = layer.innerShadowOffset
          innerShadowRadius = layer.innerShadowRadius
          innerShadowOpacity = layer.innerShadowOpacity
      }
      super.init(layer: layer)
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  override func draw(in ctx: CGContext) {
    ctx.setAllowsAntialiasing(true)
    ctx.setShouldAntialias(true)
    ctx.interpolationQuality = .high

    let colorspace = CGColorSpaceCreateDeviceRGB()

    var rect = bounds
    var radius = cornerRadius

    if borderWidth != 0 {
      rect = rect.insetBy(dx: borderWidth, dy: borderWidth)
      radius -= borderWidth
      radius = max(radius, 0)
    }

    let innerShadowPath = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath
    ctx.addPath(innerShadowPath)
    ctx.clip()

    let shadowPath = CGMutablePath()
    let shadowRect = rect.insetBy(dx: -rect.size.width, dy: -rect.size.width)
    shadowPath.addRect(shadowRect)
    shadowPath.addPath(innerShadowPath)
    shadowPath.closeSubpath()

    if let innerShadowColor = innerShadowColor, let oldComponents = innerShadowColor.components {
      var newComponets = Array<CGFloat>(repeating: 0, count: 4) // [0, 0, 0, 0] as [CGFloat]
      let numberOfComponents = innerShadowColor.numberOfComponents

      switch numberOfComponents {
      case 2:
        newComponets[0] = oldComponents[0]
        newComponets[1] = oldComponents[0]
        newComponets[2] = oldComponents[0]
        newComponets[3] = oldComponents[1] * CGFloat(innerShadowOpacity)
      case 4:
        newComponets[0] = oldComponents[0]
        newComponets[1] = oldComponents[1]
        newComponets[2] = oldComponents[2]
        newComponets[3] = oldComponents[3] * CGFloat(innerShadowOpacity)
      default:
        break
      }

      if let innerShadowColorWithMultipliedAlpha = CGColor(colorSpace: colorspace, components: newComponets) {
        ctx.setFillColor(innerShadowColorWithMultipliedAlpha)
        ctx.setShadow(offset: innerShadowOffset, blur: innerShadowRadius, color: innerShadowColorWithMultipliedAlpha)
        ctx.addPath(shadowPath)
        ctx.fillPath(using: .evenOdd)
      }
    } 
  }
}

আমি যদি এটিকে পৃথক শ্রেণি হিসাবে না ব্যবহার করি, তবে আমার কোডটিতে ব্যবহার করার মতো প্রসঙ্গটি (সিটিএক্স) শূন্য হয় তখন:let ctx = UIGraphicsGetCurrentContext
মহসিন খুবাইব আহমেদ

@ মোহসিনখুবাইব আহমেদ UIGraphicsGetCurrentContext যখন কিছু দর্শন তাদের প্রসঙ্গকে স্ট্যাকের দিকে ঠেলে দেয় তখন আপনি পদ্ধতিটি আনতে পদ্ধতিতে পেতে পারেন ।
আরকো

@ আরকোটি যখন আমি ডিভাইসটি ঘোরালাম তখন আমাকে কিছুটা সমস্যা হয়েছিল। আমি 'ওভাররাইড সুবিধাযুক্ত থিম (স্তর: যে কোনও) {সেলফিনাইট () added' যুক্ত করেছি। এখন কোন ত্রুটি প্রদর্শিত হয়!
ইউমা টেকনিক্যাল ইনক।

ক্র্যাশ সংশোধন করতে init (স্তর: যে কোনও) যুক্ত করা হয়েছে
নিক কোভ

2

সুইফটে ক্যালায়ার ব্যবহার করে স্কেলেবল সমাধান

বর্ণিতগুলির সাহায্যে InnerShadowLayerআপনি অন্যকে বাদ দিয়ে কেবল নির্দিষ্ট প্রান্তের জন্য অভ্যন্তরীণ ছায়া সক্রিয় করতে পারবেন। (উদাহরণস্বরূপ, আপনি কেবলমাত্র নিজের দৃষ্টির বাম এবং শীর্ষ প্রান্তে অভ্যন্তরীণ ছায়া গো সক্ষম করতে পারেন)

তারপরে InnerShadowLayerআপনি নিজের ভিউটিতে এটি যুক্ত করে যুক্ত করতে পারেন :

init(...) {

    // ... your initialization code ...

    super.init(frame: .zero)
    layer.addSublayer(shadowLayer)
}

public override func layoutSubviews() {
    super.layoutSubviews()
    shadowLayer.frame = bounds
}

InnerShadowLayer বাস্তবায়ন

/// Shadow is a struct defining the different kinds of shadows
public struct Shadow {
    let x: CGFloat
    let y: CGFloat
    let blur: CGFloat
    let opacity: CGFloat
    let color: UIColor
}

/// A layer that applies an inner shadow to the specified edges of either its path or its bounds
public class InnerShadowLayer: CALayer {
    private let shadow: Shadow
    private let edge: UIRectEdge

    public init(shadow: Shadow, edge: UIRectEdge) {
        self.shadow = shadow
        self.edge = edge
        super.init()
        setupShadow()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    public override func layoutSublayers() {
        updateShadow()
    }

    private func setupShadow() {
        shadowColor = shadow.color.cgColor
        shadowOpacity = Float(shadow.opacity)
        shadowRadius = shadow.blur / 2.0
        masksToBounds = true
    }

    private func updateShadow() {
        shadowOffset = {
            let topWidth: CGFloat = 0
            let leftWidth = edge.contains(.left) ? shadow.y / 2 : 0
            let bottomWidth: CGFloat = 0
            let rightWidth = edge.contains(.right) ? -shadow.y / 2 : 0

            let topHeight = edge.contains(.top) ? shadow.y / 2 : 0
            let leftHeight: CGFloat = 0
            let bottomHeight = edge.contains(.bottom) ? -shadow.y / 2 : 0
            let rightHeight: CGFloat = 0

            return CGSize(width: [topWidth, leftWidth, bottomWidth, rightWidth].reduce(0, +),
                          height: [topHeight, leftHeight, bottomHeight, rightHeight].reduce(0, +))
        }()

        let insets = UIEdgeInsets(top: edge.contains(.top) ? -bounds.height : 0,
                                  left: edge.contains(.left) ? -bounds.width : 0,
                                  bottom: edge.contains(.bottom) ? -bounds.height : 0,
                                  right: edge.contains(.right) ? -bounds.width : 0)
        let path = UIBezierPath(rect: bounds.inset(by: insets))
        let cutout = UIBezierPath(rect: bounds).reversing()
        path.append(cutout)
        shadowPath = path.cgPath
    }
}


1

এই কোডটি আমার পক্ষে কাজ করেছিল

class InnerDropShadowView: UIView {
    override func draw(_ rect: CGRect) {
        //Drawing code
        let context = UIGraphicsGetCurrentContext()
        //// Shadow Declarations
        let shadow: UIColor? = UIColor.init(hexString: "a3a3a3", alpha: 1.0) //UIColor.black.withAlphaComponent(0.6) //UIColor.init(hexString: "d7d7da", alpha: 1.0)
        let shadowOffset = CGSize(width: 0, height: 0)
        let shadowBlurRadius: CGFloat = 7.5
        //// Rectangle Drawing
        let rectanglePath = UIBezierPath(rect: bounds)
        UIColor.groupTableViewBackground.setFill()
        rectanglePath.fill()
        ////// Rectangle Inner Shadow
        context?.saveGState()
        UIRectClip(rectanglePath.bounds)
        context?.setShadow(offset: CGSize.zero, blur: 0, color: nil)
        context?.setAlpha((shadow?.cgColor.alpha)!)
        context?.beginTransparencyLayer(auxiliaryInfo: nil)
        do {
            let opaqueShadow: UIColor? = shadow?.withAlphaComponent(1)
            context?.setShadow(offset: shadowOffset, blur: shadowBlurRadius, color: opaqueShadow?.cgColor)
            context!.setBlendMode(.sourceOut)
            context?.beginTransparencyLayer(auxiliaryInfo: nil)
            opaqueShadow?.setFill()
            rectanglePath.fill()
            context!.endTransparencyLayer()
        }
        context!.endTransparencyLayer()
        context?.restoreGState()
    }
}

0

এখানে কিছু কোড রয়েছে যা আপনার পক্ষে এটি করতে পারে। আপনি যদি নিজের + (Class)layerClassভিউটিতে স্তরটি (ওভাররাইড করে ), জেটিএআইএননারশ্যাডো লাইয়ারে পরিবর্তন করেন তবে আপনি ইনডেন্ট স্তরটিতে অভ্যন্তরীণ ছায়াটি আপনার ডিআই পদ্ধতিতে সেট করতে পারেন এবং এটি আপনার জন্য কাজ করবে। আপনি যদি মূল বিষয়বস্তু আঁকতে চান তবে নিশ্চিত করুন যে আপনি setDrawOriginalImage:yesইনডেন্ট স্তরটিতে কল করেছেন। এই কিভাবে কাজ করে সে সম্পর্কে একটি ব্লগ পোস্টে আছে এখানে


@ মিতেশডোবারিয়া কেবলমাত্র উভয় লিঙ্কই পরীক্ষা করেছে এবং সেগুলি ভাল কাজ করতে দেখা যাচ্ছে (একটি ব্যক্তিগত ট্যাবে অন্তর্ভুক্ত)। কোন লিঙ্কটি আপনাকে সমস্যা তৈরি করছে?
জেমস স্নুক

আপনি দয়া করে অভ্যন্তরীণ ছায়া কোডটির এই প্রয়োগটি দেখুন look এটি কেবল ভিউডিডঅ্যাপার পদ্ধতিতে কাজ করছে। এবং কিছু ঝলকানি দেখায়। drive.google.com/open?id=1VtCt7UFYteq4UteT0RoFRjMfFnbibD0E
মিতেশ ডোবারিয়া

0

গ্রেডিয়েন্ট স্তর ব্যবহার:

UIView * mapCover = [UIView new];
mapCover.frame = map.frame;
[view addSubview:mapCover];

CAGradientLayer * vertical = [CAGradientLayer layer];
vertical.frame = mapCover.bounds;
vertical.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor,
                        (id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
                        (id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
                        (id)[UIColor whiteColor].CGColor, nil];
vertical.locations = @[@0.01,@0.1,@0.9,@0.99];
[mapCover.layer insertSublayer:vertical atIndex:0];

CAGradientLayer * horizontal = [CAGradientLayer layer];
horizontal.frame = mapCover.bounds;
horizontal.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor,
                     (id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
                     (id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
                     (id)[UIColor whiteColor].CGColor, nil];
horizontal.locations = @[@0.01,@0.1,@0.9,@0.99];
horizontal.startPoint = CGPointMake(0.0, 0.5);
horizontal.endPoint = CGPointMake(1.0, 0.5);
[mapCover.layer insertSublayer:horizontal atIndex:0];

0

একটি সহজ সমাধান আছে - কেবলমাত্র সাধারণ ছায়া আঁকুন এবং এ জাতীয় ঘোরান

@objc func shadowView() -> UIView {
        let shadowView = UIView(frame: .zero)
        shadowView.backgroundColor = .white
        shadowView.layer.shadowColor = UIColor.grey.cgColor
        shadowView.layer.shadowOffset = CGSize(width: 0, height: 2)
        shadowView.layer.shadowOpacity = 1.0
        shadowView.layer.shadowRadius = 4
        shadowView.layer.compositingFilter = "multiplyBlendMode"
        return shadowView
    }

func idtm_addBottomShadow() {
        let shadow = shadowView()
        shadow.transform = transform.rotated(by: 180 * CGFloat(Double.pi))
        shadow.transform = transform.rotated(by: -1 * CGFloat(Double.pi))
        shadow.translatesAutoresizingMaskIntoConstraints = false
        addSubview(shadow)
        NSLayoutConstraint.activate([
            shadow.leadingAnchor.constraint(equalTo: leadingAnchor),
            shadow.trailingAnchor.constraint(equalTo: trailingAnchor),
            shadow.bottomAnchor.constraint(equalTo: bottomAnchor),
            shadow.heightAnchor.constraint(equalToConstant: 1),
            ])
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.