CALayers এর ইউআইভিউ'র সীমানা পরিবর্তনে পুনরায় আকার পেল না। কেন?


101

আমার একটি রয়েছে UIViewযার CALayerস্তরে প্রায় 8 টি পৃথক সাবলেয়ার যুক্ত হয়েছে। যদি আমি দর্শনের সীমানা (অ্যানিমেটেড) সংশোধন করি তবে দৃশ্যটি নিজেই সঙ্কুচিত হয়ে যায় (আমি এটি দিয়ে একটি পরীক্ষা করেছি backgroundColor), তবে সাবলেয়ারগুলির আকার অপরিবর্তিত রয়েছে

কীভাবে সমাধান করবেন?


layer.autoresizingMaskসহায়ক হতে পারে।
ডনসং

উত্তর:


153

সলিন যেভাবে ব্যবহার করেছিল আমি একই পদ্ধতি ব্যবহার করেছি, তবে সেই কোডটিতে একটি টাইপো রয়েছে। পদ্ধতিটি হওয়া উচিত:

- (void)layoutSubviews {
  [super layoutSubviews];
  // resize your layers based on the view's new bounds
  mylayer.frame = self.bounds;
}

আমার উদ্দেশ্যগুলির জন্য, আমি সর্বদা চাইতাম সাবলেয়ারটি পিতামাতার দর্শনের পূর্ণ আকার হয়। আপনার ভিউ ক্লাসে সেই পদ্ধতিটি রাখুন।


8
@ ফিশিনার আপনি কি নিশ্চিত? মনে হচ্ছে আপনি ফ্রেমটি বর্ণনা করছেন। সীমাবদ্ধতা, তাত্ত্বিকভাবে সর্বদা 0,0 এর উত্স হিসাবে হওয়া উচিত
griotspeak

4
@ গ্রিগ্রোস্পিক - এটি আসলে ঘটনা নয়। সীমানা বৈশিষ্ট্যের বর্ণনাটি এখানে দেখুন: বিকাশকারী / অ্যাপ্লিকেশন / লাইব্রেরি / আইস /# ডকুমেন্টেশন / ইউইকিট / রেফারেন্স / - - "ডিফল্টরূপে সীমা আয়তক্ষেত্রের উত্স সেট করা আছে (0, 0) তবে আপনি করতে পারেন ভিউয়ের বিভিন্ন অংশ প্রদর্শন করতে এই মানটি পরিবর্তন করুন।
jdc

অনেক ধন্যবাদ, আমি তখন থেকে কয়েকটি কেস (স্ক্রোল ভিউ, একের জন্য) জেনেছি যেখানে এটি সত্য নয় তবে আমি এই মন্তব্যটি ভুলে গেছি।
griotspeak

32
[সুপার লেআউটসুভিউ] কল করতে ভুলবেন না, কারণ এটি বিভিন্ন ইউআইকিট ক্লাসে অপ্রত্যাশিত আচরণের কারণ হতে পারে।
কেএমপুরফি 91

4
এটি একটি স্ব-আকারের UITextView(স্ক্রোলএইনেবলড = কোন) এবং অটো লেআউট নিয়ে আমার পক্ষে খুব ভাল কাজ করে নি । আমি তার তত্ত্বাবধানে একটি পাঠ্য ভিউ পিন করেছি, যার ফলস্বরূপ CALayerনিজের নীচে একটি (সীমান্ত) ছিল এবং যখন আমি পাঠ্য দৃশ্যের উচ্চতা পরিবর্তিত হয়েছিল তখন এটি সীমান্তের অবস্থান আপডেট করতে চাই। কোনও কারণে layoutSubiewsঅনেক দেরিতে পথ বলা হয়েছিল (এবং স্তর অবস্থানটি অ্যানিমেটেড ছিল)।
iosdude

27

যেহেতু আইফোনে ক্যালায়ার লেআউট ম্যানেজারগুলিকে সমর্থন করে না, তাই আমি মনে করি যে আপনাকে আপনার ভিউয়ের মূল স্তরটি একটি কাস্টম ক্যালায়ার সাবক্লাস করতে হবে যাতে আপনি সমস্ত সাবলেয়ারের layoutSublayersফ্রেম সেট করতে ওভাররাইড করে। +layerClassআপনার নতুন CALayer সাবক্লাসের ক্লাসটি ফেরত দেওয়ার জন্য আপনাকে অবশ্যই আপনার দর্শনের পদ্ধতিটি ওভাররাইড করতে হবে ।


ওভাররাইড + লেয়ারক্লাস ওপেনজিএল লেয়ার ওভাররাইডের মতো? মনে করছি. সাবলেয়ারগুলির ফ্রেম সেট করবেন? কি সেট? আমাকে সুপারলেয়ার ফ্রেমের আকারের উপর নির্ভর করে স্বতন্ত্রভাবে সমস্ত সাবলেয়ারের ফ্রেম / অবস্থান গণনা করতে হবে? কোনও "বাধা-জাতীয়", বা "লিঙ্ক-টু-সুপারলেয়ার" -র মতো সমাধান নেই? ওহ, ,শ্বর, সময়সীমার বাইরে আর একটি দিন। সিজিলেয়ার্স পুনরায় আকার পেয়েছে, তবে খুব অচল ছিল, ক্যালায়ার্স যথেষ্ট দ্রুত, তবে পুনরায় আকার পাননি। এত অবাক। উত্তরের জন্য ধন্যবাদ, যাইহোক।
গেরি বোর্বস

4
ম্যাকের ক্যালায়ার এর জন্য লেআউট ম্যানেজার রয়েছে তবে তারা আইফোনে উপলভ্য নয়। হ্যাঁ, আপনাকে নিজের ফ্রেমের আকারগুলি গণনা করতে হবে। আরেকটি বিকল্প হ'ল সাবলেয়ারগুলির পরিবর্তে সাবউভিউগুলি ব্যবহার করা যেতে পারে। তারপরে আপনি সেই অনুযায়ী সংক্ষিপ্তসারগুলির অটোরিসাইজিং মাস্কগুলি সেট করতে পারেন।
ওলে বেগম্যান

4
হ্যাঁ, ইউআইভিউউগুলি খুব পারফরম্যান্স ব্যয়বহুল ক্লাস, তবে আমি ক্যালায়ার্স ব্যবহার করি।
গেরি বোর্বস

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

শুধু এই মধ্যে bumped। ওলে যেমন বলেছে ক্যালায়ারকে সাবক্লাস করা সর্বোত্তম বিকল্পের মতো মনে হচ্ছে তবে এটি অযথা জটিল মনে হচ্ছে।
দিমিত্রি

16

আমি এটি ইউআইভিউতে ব্যবহার করেছি।

-(void)layoutSublayersOfLayer:(CALayer *)layer
{
    if (layer == self.layer)
    {
        _anySubLayer.frame = layer.bounds;
    }

super.layoutSublayersOfLayer(layer)
}

আমার জন্য কাজ কর.


হ্যাঁ, এটি আইওএস ৮ এ আমার জন্য কাজ করেছিল সম্ভবত সম্ভবত পূর্ববর্তী সংস্করণগুলিতে কাজ করবে। আমার একটি গ্রেডিয়েন্ট ব্যাকগ্রাউন্ড স্তর ছিল এবং যখন ডিভাইসটি ঘোরানো হয় তখন স্তরটির আকার পরিবর্তন করা দরকার।
ইপেজ_এড

আমার জন্য কাজ করেছে, তবে এটিকে
এন্ট্রপির

4
এটাই সেরা উত্তর! হ্যাঁ আমি লেআউটসুভিউগুলি চেষ্টা করেছি তবে এটি কেবলমাত্র আমার ইউআইটিেক্সটফিল্ডের লেআউটটি যেমন বাম ভিউ এবং ডানদর্শন দেখুন অদৃশ্য হয়ে যায় এবং ইউআইটিেক্সটফিল্ডে আরও টেক্সট অদৃশ্য হয়ে যায়। আমি ইউআইভিউর উত্তরাধিকারের পরিবর্তে এক্সটেনশন ব্যবহার করেছি, তবে এটি খুব বগিযুক্ত ছিল। এই মহান কাজ! THX
Michał Ziobro

কাস্টম অঙ্কন ( CALayerDelegateগুলি draw(_:in:)) সহ একটি স্তরের জন্য , আমাকেও কল করতে হয়েছিল _anySubLayer.setNeedsDisplay()। তারপরে এটি আমার পক্ষে কাজ করেছিল।
jedwidz

9

আমারও একই সমস্যা ছিল। একটি কাস্টম ভিউয়ের স্তরে আমি আরও দুটি সাবলেয়ার যুক্ত করেছি। সাবলেয়ারগুলিকে পুনরায় আকার দেওয়ার জন্য (প্রতিটি সময় কাস্টম ভিউয়ের সীমানা পরিবর্তন হয়), আমি layoutSubviewsআমার কাস্টম ভিউয়ের পদ্ধতিটি প্রয়োগ করেছি; এই পদ্ধতির অভ্যন্তরে আমি আমার সাবভিউ স্তরের বর্তমান সীমানা মেলে প্রতিটি সাবলেয়ার ফ্রেম আপডেট করেছি update

এটার মতো কিছু:

-(void)layoutSubviews{
   //keep the same origin, just update the width and height
   if(sublayer1!=nil){
      sublayer1.frame = self.layer.bounds;
   }
}

16
এফওয়াইআই, আপনার যদি (সাবলেয়ার 1! = শূন্য) প্রয়োজন হয় না, যেহেতু ওবজেসি বার্তা শূন্য করার জন্য সংজ্ঞায়িত করেছে (এই ক্ষেত্রে, -setFrame :) একটি অপ-প্রত্যাবর্তন 0 হিসাবে।
অ্যান্ড্রু পোলিয়ট

9

2017:

এই প্রশ্নের আক্ষরিক উত্তর:

"ক্যালায়ার্স তার ইউআইভিউ'র সীমানা পরিবর্তনের ক্ষেত্রে পুনরায় আকার দিতে পারেনি Why কেন?"

এটি কি ভাল বা খারাপের জন্য:

needsDisplayOnBoundsChange

মিথ্যা (!!) এর মধ্যে ডিফল্ট CALayer

সমাধান,

class CircularGradientViewLayer: CALayer {
    
    override init() {
        
        super.init()
        needsDisplayOnBoundsChange = true
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override open func draw(in ctx: CGContext) {
        go crazy drawing in .bounds
    }
}

প্রকৃতপক্ষে, আমি আপনাকে এই কিউতে পরিচালনা করি

https://stackoverflow.com/a/47760444/294884

যা ব্যাখ্যা করে, সমালোচক কী contentsScaleকরে। আপনি যখন সেট করেন তখন সাধারণত সেট করা দরকার needsDisplayOnBoundsChange


5

সুইফট 3 সংস্করণ

কাস্টম ঘরে, নিম্নলিখিত লাইনগুলি যুক্ত করুন

প্রথমে ঘোষণা করুন

let gradientLayer: CAGradientLayer = CAGradientLayer()

তারপরে নিম্নলিখিত লাইনগুলি যুক্ত করুন

override func layoutSubviews() {
    gradientLayer.frame = self.YourCustomView.bounds
}

0

[ওলে] যেমন লিখেছেন ক্যালায়ার আইওএস-এ স্বয়ংক্রিয়করণ সমর্থন করে না। সুতরাং আপনার নিজের হাতে লেআউট সামঞ্জস্য করা উচিত। আমার বিকল্পটি হ'ল স্তরের ফ্রেমটি সামঞ্জস্য করা (আইওএস 7 এবং এর আগের)

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

বা (আইওএস 8 হিসাবে)

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinato

0

আপনার কাস্টম ভিউতে আপনার কাস্টম লেয়ারের জন্য আপনার ভেরিয়েবল ডিক্লেয়ার করতে হবে, স্কোপ থ্রিতে ভেরিয়েবল ঘোষণা করবেন না। এবং একবার একবার এটি আরম্ভ করুন, নাল মান সেট এবং পুনরায় সেট করার চেষ্টা করবেন না

    শ্রেণি কাস্টমভিউ: ইউআইভিউ {
        var কাস্টমলায়ার: ক্যালায়ার = ক্যালায়ার ()

        ওভাররাইড ফানক লেআউটসুভিউ () {
            super.layoutSubviews ()
    // গার্ডকে _ ফিল কালার দিন = স্ব ._ফিল কালার অন্য {ফিরতি}
            লেআউট ()
        }
        বেসরকারী ফানক লেলআউট () { 
            কাস্টমলায়ার.রেমফ্রেমসুপারভিউ ()
            কাস্টমলায়ার.ফ্রেমে = স্তর.বাউন্ডস
                   
            স্তর.insertSubview (এ: 0)
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.