بسم الله الرحمن الرحیم

یه چیزی که فکر کنم با ورود به دنیای ios کمی آزار دهنده باشه، مبحث اسکرول و اسکرول ویو ها توی این سیستم عامل در محیط xcode باشه

تا الان که در حال نوشتن این آموزش هستم xcode 9.4 با سویفت 4.2 در حال استفاده است و این آموزش طبق این نسخه ها نوشته میشه

اسکرول ویو ها توی هر جایی استفاده میشن مثلا توی اندروید کافیه که یه اسکرول ویو رو توی لایوت xml تون درگ کنید و توش ویو های مختلفی رو بکشید تا از حد صفحه بزرگتر بشه اون موقع است که اسکرول ویو شما توی گوشی اسکرول میخوره تا تمام ویو به صورت کامل نشان داده بشه

توی صفحات وب هم که اصلا چیزی تحت عنوان اسکرول ویو نداریم و کافیه شی هایی که روی صفحه با html و css میسازید از صفحه مانیتور بیشتر بشه تا اسکرول بخوره مثلا یه متن طولانی بنویسید یا یه div بزارید که ارتفاعش زیاد باشه و...

برای درک این مطلب توی ios باید چند تا چیز رو بدونید:

  1. ویو های داخل اسکرول ویو حتما باید دارای ارتفاع مشخصی باشند (کامل ترش رو پایین میگم)
  2. اسکرول ویو همزمان هم به طور عمودی و هم افقی اسکرول میخوره (که بهتون میگم چطور میشه فقط از اسکرول افقی استفاده کرد)
  3. یک تیبل ویو در اسکرول ویو به طور عادی برای خودش اسکرول میشه (یعنی اینجوری نیست اسکرولش با اسکرول، اسکرول ویو هماهنگ بشه و وقتی به تهش برسی ویو بعدی رو ببینی بلکه برای خودش سرجای خودش اسکرول میخوره)

 

1. ویو های داخل اسکرول ویو حتما باید دارای ارتفاع مشخصی باشند:

اگه کمی توی ios و محیط xcode کار کرده باشید قطعا با مبحث autoLayout ها آشنایی دارید و میدونید که یه ویو برای اینکه توی گوشی های مختلف درست نمایش داده بشه نیاز به constraint های مختلفی داره که باید ویو رو از همه سمت به ویو های مجاور یا به گوشه صفحه متصل کنه (برای مطالعه بیشتر در مورد autoLayout ها و مفهوم اصلی که خیلی کمکتون میکنه درک درستی داشته باشید و بتونید همه جور صفحه ای رو پیاده کنید این آموزش رو ببینید)

حالا شما اگه بخواید چنین کاری رو توی یه اسکرول ویو انجام بدید و مثلا 1 ویو (UIView) رو توی اسکرول ویو درگ کنید و از همه طرف به اسکرول ویو متصل کنید هیچ وقت اسکرول نمیخوره ولی کافیه که constraint پایینیش رو پاک کنید و در عوض یه ارتفاع مشخص بهش بدید تا اسکرول بخوره یا حتی میتونید توش یه label درگ کنید و line رو روی صفر بزارید و 30 40 خط بنویسید و روی گوشی های مختلف تست کنید، میبینید توی گوشی هایی که برای نمایش تمام متن جا نیست صفحه برنامه اسکرول میخوره

پس سعی کنید این مورد رو رعایت کنید مگرنه اصلا اسکرول ویو شما اسکرول نمیخوره و ابتدای کار ناامید میشید (مثل خودم)

2. اسکرول ویو همزمان به صورت عمودی و افقی اسکرول میخوره:

برای اینکه اسکرول ویو شما فقط عمودی اسکرول بخوره کافیه دقت کنید که ویو های شما عرضی بیشتر از عرض اسکرول ویو نداشته باشند، برای این کار میتونید ویو خودتون رو انتخاب کنید و با نگه داشتن کلید کنترل و درگ کردن ویو به ویوی اصلی (ویوی بالاتر از اسکرول ویو که اسکرول ویو هم عرض اون هست) در منویی که باز میشه گزینه Eqaul Width رو انتخاب کنید یعنی شما الان یه ویو هم عرض ویوی اصلی دارید و این باعث میشه دیگه اسکرول ویو شما به هیچ عنوان به صورت افقی اسکرول نخوره (پس رمز این قسمت این شد که ویو های شما نباید عرضی بیشتر از اسکرول ویو داشته باشند)

 

3.تیبل ویو در اسکرول ویو:

برای برنامه های کمی بزرگتر نیاز میشه گاهی یه تیبل ویو رو توی یه اسکرول ویو قرار بدیم اول میگم چه صفحاتی چنین نیازی دارند تا کاملا به مهم بودن این قسمت پی ببریم بعد آموزش این قسمت رو شروع کنیم:

صفحه ای از یک فروشگاه رو در نظر بگیرید که در صفحه یک محصول، پس از معرفی محصول 20 نظر از نظرات کاربران را قرار داده و در زیر آنها محصولات مشابه فروشگاه خود را قرار داده است (نظرات ممکن است دارای 1 خط یا بیشتر از 1 خط باشند)

قطعا میدونیم برای پیاده کردن قسمت نظرات باید از تیبل ویو کمک بگیریم پس اول یه اسکرول ویو میزاریم و توش به ترتیب ویو ها رو میچینیم ویو هایی که میتونن ارتفاع ثابت بگیرن رو باید ارتفاع ثابت بدیم ولی اگر متن داشته باشیم میتونیم با تنظیم line ویو (UILabel) روی صفر یه متنی بنویسیم که هرچند خط میتونه داشته باشه و لازم به ارتفاع ثابت نداره

حالا میرسیم به TableView، پس از درگ این ویو توی اسکرول ویوی خودمون و تنظیم Constraint های اون یه ارتفاع ثابت بهش میدیم (مهم نیس چقدر باشه مثلا 100pt)  و از منوی سمت راست قابلیت اسکرول خوردن رو از تیبل ویو میگیریم (Scrollable رو غیرفعال میکنیم) حالا ادامه ویو ها رو هم میچینیم (برای لیست محصولات مشابه میتونیم از UICollectionView استفاده کنیم که آیتم هاشو کنار هم میچینه و میتونید تنظیم کنید که فقط افقی اسکرول بخوره)

خب تا اینجا یه تیبل ویو داریم که با ارتفاعی که بهش دادیم شاید از 20 نظر بتونه 5 تا از اونا رو نشون بده (فرایند گرفتن دیتا از api  و پارس کردن جیسون ها و توابع tableView با خودتون) و اسکرول هم نمیخوره چون اسکرول خوردنشو غیرفعال کردیم پس عملا نمیتونه کار ما رو راه بندازه اینجاست که یه چیزی به ذهنمون میرسه اینکه بعد از صدا کردن reloadData (این تابع رو بعد از اینکه لیست نظرات از api گرفته شد و همه چیز آماده شد صدا میکنیم تا tableView خودشو از اول با داده های جدید بچینه) ارتفاع رو یه جوری تنظیم کنیم که همه چیز درست بشه یعنی همه 20 نظر جای کافی داشته باشن (توجه کنید قسمت طراحی cell به خودتون واگذار شده ولی یه راهنمای کوچیکی که میتونم بکنم اینه که شما وقتی دارید UILabel رو توی cell میزارید بهش ارتفاع ندید بلکه line رو روی صفر بزارید و مهم تر از اون اینکه حتما حتما از 4 طرف به گوشه های cell وصلش کنید یادتون نره که از پایین هم وصل کنید این خییییلی مهمه)

خب قبل از اینکه بخوایم ارتفاع رو بعد از گرفتن دیتا تغییر بدیم لازمه توی viewDidLoad خط زیر رو اضافه کنیم

tableView.rowHeight = UITableViewAutomaticDimension

کار خط بالا اینه که میشه ارتفاع هر سطر رو به صورت اتوماتیک اندازه گیری کنه (چون ممکنه ارتفاع یه نظر 100 پوینت و ارتفاع نظر دیگه ای 200 پوینت باشه)

حالا یه مواقعی هست که فرصت اندازه گیری دقیق نیست (که فکر کنم براتون پیش بیاد بعدا) یعنی اینکه تیبل ویو نمیتونه از هرکدومو حساب کنه میاد از estimatedRowHieght ی که شما بهش میدید استفاده میکنه و همه رو به همون اندازه میگیره پس کد خط زیر رو هم زیر همون بالایی اضافه کنید

tableView.estimatedRowHeight = 140

حالا میریم به storyboard مون و از اونجا روی ارتفاعی که به تیبل ویو دادیم کلیک میکنیم و با کنترل درگ اونو میاریم توی کلاسمون و اسم outlet ش رو میزارم heightTableViewConstraint ، دیگه کار زیادی نمونده کافیه که بعد از tableView.reloadData() کد زیر رو بزاریم تا ارتفاع به اندازه لازم بشه

heightTableViewConstraint.const = tableView.contentSize.height

اگه درست کار نکرد یه tableView.layoutIfNeeded() هم قبلش بزارید احتمالا درست میشه :\

خب تقریبا کارمون تمومه

سوالی بود در خدمتم

به امید ایرانی با پیشرفت علمی بیشتر

یاعلی مدد