दिलचस्प पोस्ट
कोण 2 में templatURL में डायनामिक टेम्पलेट Jquery mouseover में देरी जोड़ने के लिए कैसे? वसंत MVC 3 नियंत्रक से केवल स्ट्रिंग संदेश लौटें एक रेंज के भीतर एन यादृच्छिक और अद्वितीय संख्या उत्पन्न करें क्या पीडीओएसटीएटमेंट :: बिंदपाम () वैकल्पिक पास पैरामीटर नामों के लिए अग्रणी बृहदान्त्र है? क्या कोई जावास्क्रिप्ट / jQuery DOM परिवर्तन श्रोता है? हाल ही के कार्य / ऐप्स बटन को अक्षम कैसे करें एंड्रॉइड: एप्लिकेशन का नाम प्राप्त करें (पैकेज का नाम नहीं) क्या आलसी लोड हो रहा है? क्यों Matplotlib के साथ इतनी धीमी योजना बना रहा है? पीआईपी स्थापित: कृपया उस निर्देशिका की अनुमतियों और मालिक की जांच करें ग्राहकों से आईफोन क्रैश लॉग कैसे प्राप्त करें? सुनिश्चित करें कि कम से कम एक चेकबॉक्स को चेक किया गया है AdMob विज्ञापन सही ढंग से अक्षम करें जीसीएम पंजीकरण आईडी परिवर्तित

CAGradientLayer, अच्छी तरह से आकार नहीं, रोटेशन पर फाड़

मैं अपने CAGradientLayers प्राप्त करने की कोशिश कर रहा हूं, कि मैं रोटेशन और मोडल व्यू प्रस्तुति पर अच्छा आकार बदलने के लिए अच्छी ढाल पृष्ठभूमि बनाने के लिए उपयोग कर रहा हूं, लेकिन वे गेंद नहीं खेलेंगे।

यहां एक वीडियो है जिसे मैंने अभी अपनी समस्या दिखाया है: रोटेशन पर फाड़ पर ध्यान दें।

यह भी कृपया ध्यान दें कि इस वीडियो को ओएस एक्स पर आईफोन सिमुलेटर के फिल्माने के द्वारा बनाया गया था। मैंने अपनी समस्या को उजागर करने के लिए वीडियो में एनीमेशन को धीमा कर दिया है I

समस्या का वीडियो …

यहाँ एक Xcode प्रोजेक्ट है जिसे मैंने अभी बनाया है (जो कि वीडियो में दिखाए गए ऐप का स्रोत है), मूल रूप से यह दर्शाता है कि समस्या रोटेशन पर होती है और खासकर जब विचारों को मॉडेली रूप से प्रस्तुत किया जाता है:

Xcode प्रोजेक्ट, CAGradientLayer पृष्ठभूमि के साथ मौलिक रूप से प्रस्तुत विचार …

इसके लिए मैं क्या समझता हूं कि इसका उपयोग करना:

[[self view] setBackgroundColor:[UIColor blackColor]]; 

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

किसी भी विचार से मैं इसे सुलझाने के लिए क्या कर सकता हूं?

जॉन

Solutions Collecting From Web of "CAGradientLayer, अच्छी तरह से आकार नहीं, रोटेशन पर फाड़"

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

इसलिए जब आप ढाल परत के फ्रेम को अपडेट करते हैं, तो परत अपने स्वयं के डिफ़ॉल्ट एनीमेशन पैरामीटर के साथ बदलाव को एनिमेट करता है। (इसे "निहित एनीमेशन" कहा जाता है।) ये डिफ़ॉल्ट पैरामीटर इंटरफ़ेस रोटेशन के लिए उपयोग किए गए एनीमेशन पैरामीटर से मेल नहीं खाते हैं, इसलिए आपको एक अजीब परिणाम मिलता है।

मैंने आपकी प्रोजेक्ट को नहीं देखा, लेकिन इस कोड के साथ आपकी समस्या को पुन: उत्पन्न करने के लिए तुलनीय है:

 @interface ViewController () @property (nonatomic, strong) CAGradientLayer *gradientLayer; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.gradientLayer = [CAGradientLayer layer]; self.gradientLayer.colors = @[ (__bridge id)[UIColor blueColor].CGColor, (__bridge id)[UIColor blackColor].CGColor ]; [self.view.layer addSublayer:self.gradientLayer]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.gradientLayer.frame = self.view.bounds; } @end 

सिम्युलेटर में धीमा गति के साथ जो दिखता है, वह यहां है:

खराब रोटेशन

सौभाग्य से, यह ठीक करने के लिए एक आसान समस्या है आपको अपने ढाल परत को एक दृश्य द्वारा प्रबंधित करने की आवश्यकता है। आप ऐसा करते हैं कि एक UIView subclass जो एक CAGradientLayer का उपयोग इसके परत के रूप में करता है। कोड छोटा है:

 // GradientView.h @interface GradientView : UIView @property (nonatomic, strong, readonly) CAGradientLayer *layer; @end // GradientView.m @implementation GradientView @dynamic layer; + (Class)layerClass { return [CAGradientLayer class]; } @end 

फिर आपको CAGradientLayer बजाय GradientView का उपयोग करने के लिए अपना कोड बदलने की आवश्यकता है चूंकि आप एक परत के बजाय अब एक दृश्य का उपयोग कर रहे हैं, आप ढाल के आकार को अपने पर्यवेक्षण में रखने के लिए ऑटोोरिसिज़िंग मुखौटा सेट कर सकते हैं, इसलिए रोटेशन को संभाल करने के लिए आपको बाद में कुछ भी करने की आवश्यकता नहीं है:

 @interface ViewController () @property (nonatomic, strong) GradientView *gradientView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.gradientView = [[GradientView alloc] initWithFrame:self.view.bounds]; self.gradientView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.gradientView.layer.colors = @[ (__bridge id)[UIColor blueColor].CGColor, (__bridge id)[UIColor blackColor].CGColor ]; [self.view addSubview:self.gradientView]; } @end 

यहां परिणाम है:

अच्छा रोटेशन

@ रोब के जवाब के बारे में सबसे अच्छा हिस्सा यह है कि दृश्य आपके लिए परत को नियंत्रित करता है। यहां स्विफ्ट कोड है जो परत वर्ग को ओवरराइड करता है और ढाल सेट करता है।

 import UIKit class GradientView: UIView { override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupView() } private func setupView() { autoresizingMask = [.FlexibleWidth, .FlexibleHeight] guard let theLayer = self.layer as? CAGradientLayer else { return; } theLayer.colors = [UIColor.whiteColor().CGColor, UIColor.lightGrayColor().CGColor] theLayer.locations = [0.0, 1.0] theLayer.frame = self.bounds } override class func layerClass() -> AnyClass { return CAGradientLayer.self } } 

फिर आप जहां भी चाहें वहां दो पंक्तियों में दृश्य जोड़ सकते हैं

 override func viewDidLoad() { super.viewDidLoad() let gradientView = GradientView(frame: self.view.bounds) self.view.insertSubview(gradientView, atIndex: 0) } 

मेरा तेज संस्करण:

 import UIKit class GradientView: UIView { override class func layerClass() -> AnyClass { return CAGradientLayer.self } func gradientWithColors(firstColor : UIColor, _ secondColor : UIColor) { let deviceScale = UIScreen.mainScreen().scale let gradientLayer = CAGradientLayer() gradientLayer.frame = CGRectMake(0.0, 0.0, self.frame.size.width * deviceScale, self.frame.size.height * deviceScale) gradientLayer.colors = [ firstColor.CGColor, secondColor.CGColor ] self.layer.insertSublayer(gradientLayer, atIndex: 0) } } 

ध्यान दें कि ओरिएंटेशन परिवर्तनों के दौरान स्वत: आकार बदलने के लिए (ऑटो-लेआउट के साथ) मुझे फ्रेम आकार की गणना करने के लिए डिवाइस स्केल का भी उपयोग करना था।

  1. इंटरफ़ेस बिल्डर में, मैंने एक UIView को जोड़ा और अपनी कक्षा को ग्रेडियेंटव्यू (ऊपर दिखाए गए वर्ग) में बदल दिया।
  2. मैंने इसके लिए एक आउटलेट (MyGradientView) बनाया था
  3. अंत में, दृश्य नियंत्रक में मैंने कहा:

     override func viewDidLayoutSubviews() { self.myGradientView.gradientWithColors(UIColor.whiteColor(), UIColor.blueColor()) } 

ध्यान दें कि ढाल दृश्य "layoutSubviews" विधि में बनाया गया है, क्योंकि हमें ढाल परत बनाने के लिए एक अंतिम रूप फ्रेम की आवश्यकता है।

जब आप कोड के इस टुकड़े को सम्मिलित करते हैं और willAnimateRotationToInterfaceOrientation:duration: दूर करते हैं तो यह बेहतर दिखेगा। willAnimateRotationToInterfaceOrientation:duration: कार्यान्वयन

 - (void)viewWillLayoutSubviews { [[[self.view.layer sublayers] objectAtIndex:0] setFrame:self.view.bounds]; } 

यह हालांकि बहुत सुंदर नहीं है वास्तविक अनुप्रयोग में आपको UIView को एक ढाल दृश्य बनाने के लिए उप-वर्ग बनाना चाहिए। इस कस्टम दृश्य में आप layerClass को ओवरराइड कर सकते हैं ताकि यह एक ग्रेडिएंट परत द्वारा समर्थित हो:

 + (Class)layerClass { return [CAGradientLayer class]; } 

साथ ही layoutSubviews भी कार्यान्वित करें जब दृश्य की सीमा बदलती है तो इसे संभालने के लिए।

जब इस पृष्ठभूमि दृश्य का निर्माण होता है तो ऑटोर्सिस्किंग मास्क का उपयोग करें ताकि सीमाएं स्वचालित रूप से इंटरफ़ेस रोटेशन पर समायोजित कर सकें।

पूरी स्विफ्ट संस्करण viewFrame से viewFrame सेट करें जो कि इस दृश्य को देखने के viewFrame

 import UIKit class MainView: UIView { let topColor = UIColor(red: 146.0/255.0, green: 141.0/255.0, blue: 171.0/255.0, alpha: 1.0).CGColor let bottomColor = UIColor(red: 31.0/255.0, green: 28.0/255.0, blue: 44.0/255.0, alpha: 1.0).CGColor required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupGradient() } override class func layerClass() -> AnyClass { return CAGradientLayer.self } var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer } var viewFrame: CGRect! { didSet { self.bounds = viewFrame } } private func setupGradient() { gradientLayer.colors = [topColor, bottomColor] } } 

निजी रूप से, मैं सब कुछ को देखने के उपनगरीय इलाके में आत्मनिर्भर रखता हूं।

यहां मेरा स्विफ्ट कार्यान्वयन है:

  import UIKit @IBDesignable class GradientBackdropView: UIView { @IBInspectable var startColor: UIColor=UIColor.whiteColor() @IBInspectable var endColor: UIColor=UIColor.whiteColor() @IBInspectable var intermediateColor: UIColor=UIColor.whiteColor() var gradientLayer: CAGradientLayer? // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func drawRect(rect: CGRect) { // Drawing code super.drawRect(rect) if gradientLayer == nil { self.addGradientLayer(rect: rect) } else { gradientLayer?.removeFromSuperlayer() gradientLayer=nil self.addGradientLayer(rect: rect) } } override func layoutSubviews() { super.layoutSubviews() if gradientLayer == nil { self.addGradientLayer(rect: self.bounds) } else { gradientLayer?.removeFromSuperlayer() gradientLayer=nil self.addGradientLayer(rect: self.bounds) } } func addGradientLayer(rect rect:CGRect) { gradientLayer=CAGradientLayer() gradientLayer?.frame=self.bounds gradientLayer?.colors=[startColor.CGColor,intermediateColor.CGColor,endColor.CGColor] gradientLayer?.startPoint=CGPointMake(0.0, 1.0) gradientLayer?.endPoint=CGPointMake(0.0, 0.0) gradientLayer?.locations=[NSNumber(float: 0.1),NSNumber(float: 0.5),NSNumber(float: 1.0)] self.layer.insertSublayer(gradientLayer!, atIndex: 0) gradientLayer?.transform=self.layer.transform } } 

एक और तेज संस्करण – जो drawRect का उपयोग नहीं कर रहा है

 class UIGradientView: UIView { override class func layerClass() -> AnyClass { return CAGradientLayer.self } var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer } func setGradientBackground(colors: [UIColor], startPoint: CGPoint = CGPoint(x: 0.5, y: 0), endPoint: CGPoint = CGPoint(x: 0.5, y: 1)) { gradientLayer.startPoint = startPoint gradientLayer.endPoint = endPoint gradientLayer.colors = colors.map({ (color) -> CGColor in return color.CGColor }) } } 

नियंत्रक में मैं बस कॉल करता हूँ:

 gradientView.setGradientBackground([UIColor.grayColor(), UIColor.whiteColor()]) 

जानकारी

  • एक पंक्ति समाधान के रूप में उपयोग करें
  • जब आप इसे फिर से देखने के लिए जोड़ने के लिए ढाल बदलने (पुन: उपयोग में उपयोग करने के लिए)
  • स्वचालित रूप से स्थानांतरण
  • स्वचालित रूप से हटा रहा है

विवरण

स्विफ्ट 3.1, एक्सकोड 8.3.3

उपाय

 import UIKit extension UIView { func addGradient(colors: [UIColor], locations: [NSNumber]) { addSubview(ViewWithGradient(addTo: self, colors: colors, locations: locations)) } } class ViewWithGradient: UIView { private var gradient = CAGradientLayer() init(addTo parentView: UIView, colors: [UIColor], locations: [NSNumber]){ super.init(frame: CGRect(x: 0, y: 0, width: 1, height: 2)) restorationIdentifier = "__ViewWithGradient" for subView in parentView.subviews { if let subView = subView as? ViewWithGradient { if subView.restorationIdentifier == restorationIdentifier { subView.removeFromSuperview() break } } } let cgColors = colors.map { (color) -> CGColor in return color.cgColor } gradient.frame = parentView.frame gradient.colors = cgColors gradient.locations = locations backgroundColor = .clear parentView.addSubview(self) parentView.layer.insertSublayer(gradient, at: 0) parentView.backgroundColor = .clear autoresizingMask = [.flexibleWidth, .flexibleHeight] clipsToBounds = true parentView.layer.masksToBounds = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() if let parentView = superview { gradient.frame = parentView.bounds } } override func removeFromSuperview() { super.removeFromSuperview() gradient.removeFromSuperlayer() } } 

प्रयोग

 viewWithGradient.addGradient(colors: [.blue, .green, .orange], locations: [0.1, 0.3, 1.0]) 

स्टोरीबोर्ड का उपयोग करना

ViewController

 import UIKit class ViewController: UIViewController { @IBOutlet weak var viewWithGradient: UIView! override func viewDidLoad() { super.viewDidLoad() viewWithGradient.addGradient(colors: [.blue, .green, .orange], locations: [0.1, 0.3, 1.0]) } } 

स्टोरीबोर्ड

 <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> <capability name="Constraints to layout margins" minToolsVersion="6.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_17555986" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uii-31-sl9"> <rect key="frame" x="66" y="70" width="243" height="547"/> <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/> </view> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="uii-31-sl9" secondAttribute="bottom" constant="50" id="a7J-Hq-IIq"/> <constraint firstAttribute="trailingMargin" secondItem="uii-31-sl9" secondAttribute="trailing" constant="50" id="i9v-hq-4tD"/> <constraint firstItem="uii-31-sl9" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="50" id="wlO-83-8FY"/> <constraint firstItem="uii-31-sl9" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" constant="50" id="zb6-EH-j6p"/> </constraints> </view> <connections> <outlet property="viewWithGradient" destination="uii-31-sl9" id="FWB-7A-MaH"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> </scene> </scenes> </document> 

प्रोग्राम के रूप में

 import UIKit class ViewController2: UIViewController { @IBOutlet weak var viewWithGradient: UIView! override func viewDidLoad() { super.viewDidLoad() let viewWithGradient = UIView(frame: CGRect(x: 10, y: 20, width: 30, height: 40)) view.addSubview(viewWithGradient) viewWithGradient.translatesAutoresizingMaskIntoConstraints = false let constant:CGFloat = 50.0 NSLayoutConstraint(item: viewWithGradient, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leadingMargin, multiplier: 1.0, constant: constant).isActive = true NSLayoutConstraint(item: viewWithGradient, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailingMargin , multiplier: 1.0, constant: -1*constant).isActive = true NSLayoutConstraint(item: viewWithGradient, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottomMargin , multiplier: 1.0, constant: -1*constant).isActive = true NSLayoutConstraint(item: viewWithGradient, attribute: .top, relatedBy: .equal, toItem: view, attribute: .topMargin , multiplier: 1.0, constant: constant).isActive = true viewWithGradient.addGradient(colors: [.blue, .green, .orange], locations: [0.1, 0.3, 1.0]) } }