অটোলেআউট সীমাবদ্ধতা ব্যবহার করার সময় আমি কীভাবে একটি দর্শন বর্তমান প্রস্থ এবং উচ্চতা পেতে পারি?


108

আমি ফ্রেমের সম্পত্তি সম্পর্কে কথা বলছি না, কারণ এটি থেকে আপনি কেবল xib এ দর্শনটির আকার পেতে পারেন। আমি যখন সীমাবদ্ধতার কারণে দৃশ্যটি পুনরায় আকার দেওয়া হয় তখন তার বিষয়ে বলছি (সম্ভবত কোনও ঘূর্ণনের পরে, বা কোনও ইভেন্টের প্রতিক্রিয়া হিসাবে)। এর বর্তমান প্রস্থ এবং উচ্চতা পাওয়ার কোনও উপায় আছে কি?

প্রস্থ এবং উচ্চতার সীমাবদ্ধতার সন্ধানে আমি তার সীমাবদ্ধতার মধ্য দিয়ে পুনরাবৃত্তি করার চেষ্টা করেছি, তবে এটি খুব পরিষ্কার নয় এবং অভ্যন্তরীণ সীমাবদ্ধতা থাকলে (যেহেতু আমি উভয়ের মধ্যে পার্থক্য করতে পারি না) ব্যর্থ হয়। এছাড়াও, এটি কেবল তখনই কাজ করে যদি তাদের প্রকৃতপক্ষে প্রস্থ এবং উচ্চতার সীমাবদ্ধতা থাকে, যা তারা পুনরায় আকার দেওয়ার জন্য অন্যান্য বাধাগুলির উপর নির্ভর করে যদি না don't

কেন এটা আমার পক্ষে এত কঠিন? ARG!


আমি ভাবতাম যে কোনও নির্দিষ্ট সময়ে দেখার সীমানা এর বর্তমান প্রস্থ এবং উচ্চতা ধরে রেখেছে। এটি লেআউট প্রক্রিয়া চলাকালীন সামঞ্জস্য হয়।
ফিলিপ মিলস

হুম আমি কখনই সীমানা যাচাই করতে ভাবিনি। আমি এখন এটি করব।
ইউফ

উত্তর:


246

উত্তরটি হ'ল [view layoutIfNeeded]

কারণটা এখানে:

আপনি এখনও পরিদর্শন করে view.bounds.size.widthএবং view.bounds.size.height(বা ফ্রেমটি সমান যা আপনি যদি না খেলেন ততই সমান view.transform) তত্পরতার বর্তমান প্রস্থ এবং উচ্চতা পান ।

আপনি যদি চান যা আপনার বিদ্যমান সীমাবদ্ধতার দ্বারা প্রস্থ এবং উচ্চতা বোঝায় তবে উত্তর হ'ল সীমাবদ্ধতাগুলি ম্যানুয়ালি পর্যবেক্ষণ করা উচিত নয়, কারণ এটির ব্যাখ্যা করার জন্য আপনাকে অটো লেআউট সিস্টেমের সম্পূর্ণ সীমাবদ্ধতা-সমাধানের যুক্তি পুনরায় প্রয়োগ করতে হবে would সীমাবদ্ধতার। পরিবর্তে, আপনাকে যা করা উচিত তা হ'ল অটো লেআউটটিকে সেই লেআউটটি আপডেট করতে বলুন , যাতে এটি সীমাবদ্ধতাগুলি সমাধান করে এবং সঠিক সমাধান সহ ভিউ.বাউন্ডের মান আপডেট করে এবং তারপরে আপনি ভিউবাউন্ডগুলি পরিদর্শন করেন।

আপনি কীভাবে অটো লেআউটটিকে লেআউটটি আপডেট করতে বলবেন? [view setNeedsLayout]আপনি রান লুপের পরবর্তী সময়ে লেআউটটি আপডেট করতে অটো লেআউট চাইলে কল করুন ।

তবে আপনি যদি এটির সাথে সাথে লেআউটটি আপডেট করতে চান তবে আপনি আপনার বর্তমান ফাংশনটির মধ্যে পরে নতুন সীমানা মানটি অবিলম্বে অ্যাক্সেস করতে পারেন , বা রান লুপটি পরিবর্তনের আগে অন্য সময়ে, তারপরে আপনাকে কল করতে হবে [view setNeedsLayout]এবং [view layoutIfNeeded]

আপনি একটি দ্বিতীয় প্রশ্ন জিজ্ঞাসা করেছিলেন: "যদি আমার কাছে সরাসরি উল্লেখ না হয় তবে আমি কীভাবে উচ্চতা / প্রস্থের সীমাবদ্ধতা পরিবর্তন করতে পারি?"।

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


16
একটি দুর্দান্ত উত্তর এবং ভাল ব্যাখ্যাও। আমার চুলগুলি টেনে আনার এক-দুই ঘন্টা পরে আমাকে বাঁচিয়েছে।
বেন ক্রিগার 11'13

2
layoutIfNeededদুর্দান্ত, এবং অবিলম্বে ফ্রেমটি উপলব্ধ করা হবে। যাইহোক, এটি দৃশ্যের উপ-গাছগুলিতে যে দৃষ্টিভঙ্গিটির উপর ডাকা হয় তার সমস্ত দৃশ্যের উপর প্রতিবন্ধকতা রেন্ডার করতে বাধ্য করবে। যদি আপনি প্রোগ্রামগতভাবে দর্শন যোগ করেন, উদাহরণস্বরূপ, এবং কল করুনlayoutIfNeeded করে থাকেন এবং আপনার পুনরাবৃত্ত রুটিনে তাদের সকলকে করেন, আপনি দেখতে পাবেন যে আপনার ভিউ হায়ারার্কি খুব ধীরে ধীরে রেন্ডার হয়। (আমি এটি কঠিন উপায়ে শিখেছি) যেমন উত্তরের উত্তরে বলা হয়েছে, 'সেটনিডস লেআউট` আরও দক্ষ এবং এটি ফ্রেমটি পরবর্তী লেআউট পাসে উপলব্ধ করবে যা আদর্শভাবে এক সেকেন্ডের 1/60 তম মধ্যে ঘটে।
shmim

1
আমি জানি এটি পুরানো, তবে আপনি কোথায় এই পদ্ধতিটি ডাকবেন? ইন initWithCoder?
মেনিটবি

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

1
হ্যাঁ, রান লুপটি পরিবর্তনের আগে আপনাকে অটো লেআউট-গণিত মানের অ্যাক্সেসের প্রয়োজন হলে কেবলমাত্র লেআউটটিকে জোর করাতে হবে - উদাহরণস্বরূপ, বর্তমান ফাংশন কলের সীমার মধ্যে।
অ্যালগাল

8

আমার একটি অনুরূপ সমস্যা ছিল যেখানে আমাকে একটি শীর্ষ এবং নীচের সীমানা যুক্ত করতে হবে UITableViewযা এর মধ্যে থাকা সীমাবদ্ধতার উপর ভিত্তি করে আকার পরিবর্তন করে UIStoryboard। আমি এর সাথে আপডেট হওয়া সীমাবদ্ধতাগুলি অ্যাক্সেস করতে সক্ষম হয়েছি - (void)viewDidLayoutSubviews। এটি দরকারী যাতে আপনার কোনও ভিউ সাবক্লাস করার প্রয়োজন হয় না এবং এর বিন্যাসের পদ্ধতিটি ওভাররাইড করে।

/*** SET TOP AND BOTTOM BORDERS ON TABLE VIEW ***/
- (void)addBorders
{
    CALayer *topBorder           = [CALayer layer];
    topBorder.frame              = CGRectMake(0.0f, self.tableView.frame.origin.y, 320.0f, 0.5f);
    topBorder.backgroundColor    = [UIColor redColor].CGColor;

    CALayer *bottomBorder        = [CALayer layer];
    bottomBorder.frame           = CGRectMake(0.0f, (self.tableView.frame.origin.y + self.tableView.frame.size.height), 320.0f, 0.5f);
    bottomBorder.backgroundColor = [UIColor redColor].CGColor;

    [self.view.layer addSublayer:topBorder];
    [self.view.layer addSublayer:bottomBorder];
}

/*** GET AUTORESIZED FRAME DIMENSIONS ***/
- (void)viewDidLayoutSubviews{
    [self addBorders];
}

পদ্ধতি থেকে কল না করে viewDidLayoutSubview , কেবল নীচের সীমানাটি অফস্ক্রিন হওয়ায় কেবল উপরের সীমানাটি সঠিকভাবে আঁকা।


3
ভিউডিডলআউটসুভিউগুলি কয়েকবার বলা হচ্ছে, আপনি প্রচুর স্তর তৈরি করছেন ... অন্য স্তর যুক্ত করার আগে আপনাকে কিছু অস্তিত্বের পরীক্ষা যোগ করতে হবে
কালজেম

কিছু বছর দেরিতে মন্তব্য করুন ... অন্য কোনও কিছুর আগে ওভাররাইড করার সময় আপনারও এই পদ্ধতিটি সুপারক্লাসে কল করা উচিত:[super viewDidLayoutSubviews];
আলেজান্দ্রো ইভান

5

যারা এখনও এই জাতীয় সমস্যার মুখোমুখি হতে পারেন, বিশেষত টেবিলভিউসেল দিয়ে।

কেবল পদ্ধতিটি ওভাররাইড করুন:

-(void)layoutSubviews
{
//your code here like drawing a shadow
}

ইউআইটিএবলভিউসেল বা ইউআইসিএল্লেশনভিউসেল ক্ষেত্রে কোষের একটি সাবক্লাস তৈরি করুন এবং একই পদ্ধতিটি ওভাররাইড করুন:

-(void)layoutSubviews
{
//your code here like drawing a shadow
}

এটিই একমাত্র উপায় যে আমি আমার দৃশ্যের আসল চূড়ান্ত আকারটি পেতে পারি
বেনোইট জাদিনন

আমার একমাত্র বাধা দর্শনের জন্য আমি চূড়ান্ত আকারটি অর্জন করতে সক্ষম হলাম কারণ আমি জাগ্রত থেকে নেওয়ার চেষ্টা করছিলাম তার আগে যা প্রথমে পুনরায় আকার দেওয়ার জন্য সংক্ষিপ্তসারগুলিকে সময় দেয়নি। ধন্যবাদ!
আজিন মেহরনুশ

3

ব্যবহার -(void)viewWillAppear:(BOOL)animatedএবং কল করুন [self.view layoutIfNeeded];- এটি চেষ্টা করে যা কাজ করে।

কারণ আপনি যদি -(void)viewDidLayoutSubviewsএটি ব্যবহার করেন তবে তা অবশ্যই কাজ করবে তবে আপনার ইউআইআই যখনই আপডেট / পরিবর্তন দাবি করে ততবার এই পদ্ধতিটি বলা হয়। যা পরিচালনা করতে কষ্ট পাবে। সফ্ট কীটি হ'ল কলগুলির এই লুপ এড়াতে আপনি একটি বুল ভেরিয়েবল ব্যবহার করেন। ভাল ব্যবহার viewWillAppearviewWillAppearভিউটি আবারো লোড করা হলে পুনরায় কল করা হবে না (পুনর্বিবেচনা ছাড়াই) Remember


2

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


1
আমি অন্যথায় দেখতে পাচ্ছি। ফ্রেম মান পরিবর্তন করতে পারি না, (তাদের ধ্রুবক পরিবর্তন করে আমি xib তাদের একটি IBOutlet রয়েছে।) সরাসরি প্রস্থ / উচ্চতা সীমাবদ্ধতার পরিবর্তন পরেও
yuf

আমার সমস্যাটি অনন্য কারণ আমি সীমাবদ্ধতা পরিবর্তন করেছি, তারপরে একই ফাংশনে ফ্রেম ব্যবহার করা দরকার। সেটনিডস লেআউটকে কল করা তাৎক্ষণিকভাবে আপডেট হয় না। আমার ধারণা আমি প্রথমে ফ্রেমটি ব্যবহার করে বিন্যাসটির জন্য অপেক্ষা করতে হবে। আমার দ্বিতীয় প্রশ্নটি হ'ল, যদি আমার সরাসরি রেফারেন্স না থাকে তবে আমি কীভাবে উচ্চতা / প্রস্থের সীমাবদ্ধতা পরিবর্তন করতে পারি?
ইউফ

1
তারপরে আপনার প্রেরণ_চলাচল করা উচিত এবং এটি আপনাকে পরবর্তী ফ্রেম পর্যন্ত আপনার কোডটি বিলম্ব করতে দেয়। দ্বিতীয় অংশ হিসাবে ... আমি জানি না ... আপনাকে সমস্ত বাধা পুনরাবৃত্তি করতে হবে এবং কোনটি প্রযোজ্য তা সন্ধান করতে হবে ... আইবিউটলেটগুলি আরও সহজ।
borrrden

আইবিউটলেটগুলির জন্য সত্য, তবে আমি কোনও ইউআইভিউয়ের জন্য একটি বিভাগে একটি ফাংশন লিখতে চাই যাতে আমার সাথে কাজ করার জন্য আইবি থাকবে না।
ইউফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.