ConstraintLayout یک ViewGroup بسیار قدرتمند جهت طراحی صفحات نرم افزارهای اندرویدی است که امکان ایجاد طرحهای منعطف و کارآمد را برای شما فراهم میکند. ViewGroup ویژگیهای بسیار منحصر به فردی دارد که امکان را برای شما فراهم میکند که با سادگی هرچه تمامتر و کمترین حجم کد نویسی لایوتهای پیچیده و بزرگ را با سلسله مراتب کم (اکثرا صفر) پیاده سازی کنید.
در این مقاله قصد داریم چند تا از مهمترین ویژگیهای ConstraintLayout را بررسی کنیم. که در ادامه به آنها میپردازیم
یکی از امکانات منحصر به فرد ConstraintLayout این هست که شما قادرید یک خط راهنما (guideline) به صورت عمودی یا افقی در طرحتان تعریف کنید و سایر المانهای طرح تان را به آن متصل و محدود کنید، دقت کنید که این راهنما برای کاربران برنامه نامرئی خواهد بود و فقط در پیش نمایش اندروید استدیو قابل دیدن هست.
شما میتوانید این راهنما را در داخل طرحتان بر اساس واحدهای dp یا درصد ، نسبت به لبه ConstraintLayout قرار دهید.
جهت فاصله از لبه ی آغازین (بالا در حالت افقی و سمت چپ در حالت عمودی) از کد :
app:layout_constraintGuide_begin="100dp"
و جهت فاصله از لبه ی انتهایی (پایین در حالت افقی و سمت راست در حالت عمودی) از کد:
app:layout_constraintGuide_end="100dp"
و در نهایت جهت تعیین فاصله با استفاده از درصد نسبت به لبه ی آغازین از کد :
app:layout_constraintGuide_percent="0.33"
استفاده کنید. به این نکته دقت کنید که فقط یکی از سه حالت تعریف شده بالا را باید انتخاب کنید و در صورت استفاده از حالت سوم یک عدد اعشاری بین 0 تا 1 را وارد نمایید.
شکل 1- استفاده از خط راهنما (guideline)
در شکل 1 ما قصد داریم طرحی را پیاده سازی کنیم که در آن المان A در تمام حالات به اندازه یک سوم صفحه (33%) از لبه لایوت قرار بگیرد، برای پیاده سازی این طرح ابتدا باید یک راهنمای عمودی در 33 درصد نسبت به لایه اصلی به شکل زیر تعریف کرده و سپس المان A را به صورت زیر به انتهای خط راهنما متصل کنیم :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.33" />
<TextView
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@android:color/darker_gray"
android:text="A"
android:layout_marginStart="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
همانند خطوط راهنما، مانع (Barrier) یک خط نامرئی هست که شما میتوانید المانهای طرحتان را به آن محدود کنید. از موانع زمانی استفاده میشود که شما قصد دارید مشابه شکل 2 یک المان (C) را به یک مجموعه از المانها (A , B) محدود کنید و نه یک المان خاص دیگر.
شکل 2
زمانی که یک مانع تعریف میکنید، مانع مکان دقیق قرارگیری خودش را مشخص نمیکند و محل قرارگیری آن با توجه به المان هایی که با آن نسبت داده اید (A , B) تغییر میکند. در شکل2-الف طول المان A بیشتر از المان B است و Barrier در انتهای المان A قرار میگیرد و در شکل 2-ب طول المان B بیشتر از المان A است و Barrier در انتهای المان B قرار میگیرد و در هر دو حالت المان C در انتهای مانع قرار میگیرد.
برای پیاده سازی یک مانع شما باید المان هایی که میخواهید مانع به آن ارجاع داده شود را با کد "constraint_referenced_ids="A,B و محل قرارگیری مانع نسبت به این مراجع را با کد ""=app:barrierDirection برای مانع مشخص کنید. برای مثال قصد داریم شکل 2 را پیاده سازی کنیم. ابتدا المانهای A ,B ,C و یک Barrier تعریف کرده و سپس A ,B را به مانع ارجاع میدهیم و جهت قرارگیری مانع را مشخص کرده و در آخر المان C را به مانع به صورت زیر متصل میکنیم:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/A"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_margin="16dp"
android:background="@android:color/darker_gray"
android:text="A"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/B"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_margin="16dp"
android:background="@android:color/darker_gray"
android:text="B"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/A"
app:layout_constraintVertical_bias="0.8" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:barrierDirection="end"
app:constraint_referenced_ids="A,B" />
<TextView
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginStart="24dp"
android:background="@android:color/darker_gray"
android:text="C"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
زمانی که شما یک المان را از دو جهت محدود کرده باشید (و اندازه ی المان به صورت عددی ثابت یا "wrap content" تعریف شده باشد.) به صورت پیش فرض المان در وسط دو جهت محدود شده (50%) قرار میگیرد. جهت تغییر نسبت قرارگیری المان میتوانید از کدهای دستوری layout_constraintHorizontal_bias برای حالت افقی و layout_constraintVertical_bias برای حالت عمودی استفاده کنید.
شکل 3- استفاده از bias در ConstraintLayout
در شکل3 ما قصد داریم طرحی را پیاده سازی کنیم که در آن محل قرار گیری ImageView در حالت افقی 20% و در حالت عمودی 80% از لبههای طرح اصلی قرار بگیرد، برای پیاده سازی این طرح کافیست layout_constraintHorizontal_bias و layout_constraintHorizontal_bias را برای ImageView وارد نماییم:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@android:color/darker_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.8" />
</androidx.constraintlayout.widget.ConstraintLayout>
گاهی برای المان هایی مانند تصویر شما نیاز دارید که نسبت طول و ارتفاع المان را فارغ از اندازه تصویر به یک نسبت مشخص برای مثال نسبت 16:9 یا 1:1 انتخاب کنید. برای پیاده سازی این امر باید از بین طول و ارتفاع المان یکی را مشخص کرده و به دیگری مقدار 0dp بدهیم و سپس با کد app:layout_constraintDimensionRatio نسبتی که میخواهیم را به المان بدهیم.
شکل 4 -نحوه ی نسبت دهی به المان
برای مثال در کد زیر ما یک ImageView در طرحمان تعریف کرده و مقدار طول آن را برابر با کل طرح قرار داده ایم و ارتفاع آن را برابر با 0dp قرار داده ایم و سپس نسبت 16:9 را با استفاده از کد app:layout_constraintDimensionRatio="16:9" به تصویر متن داده ایم. در این شرایط فارغ از اندازه صفحه نمایش این تصویر همواره با نسبت 16:9 نمایش داده خواهد شد.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@android:color/darker_gray"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
یکی دیگر از امکانات منحصر به فرد ConstraintLayout این است که به شما اجازه میدهد المان هایتان را همانند حلقههای یک زنجیر به صورت زنجیره تعریف کنید. Chain یا زنجیره، گروهی از المانها است که با محدودیتهای دو طرفه به یکدیگر مرتبط هستند.
برای تشکیل زنجیرهها در صورتی که میخواهید زنجیره ی عمودی تشکیل بدهید باید تمام المانهای زنجیره را به ترتیب از بالا تا پایین به هم وصل کنید و برای تشکیل زنجیرهها در صورتی که میخواهید زنجیره افقی تشکیل بدهید باید تمام المانهای زنجیره را به ترتیب از چپ به راست به هم وصل کنید. (مشابه شکل 5) و سپس در اولین المان مجموعه app:layout_constraintVertical_chainStyle را بیفزایید
شکل5- انواع زنجیره (chain) در ConstraintLayout
المانهای درون یک زنجیره میتواند به صورت عمودی یا افقی با هم یک زنجیره را به یکی از حالات زیر تشکیل دهند.
مطابق با شکل 5-1 این حالت که به صورت پیش فرض برای زنجیرهها فعال هست. المانها با فاصله مساوی از هم در طرح توزیع میشوند.
برای پیاده سازی این حالت باید به صورت زیر عمل کنید:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/A"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="A"
app:layout_constraintBottom_toTopOf="@id/B"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread" />
<TextView
android:id="@+id/B"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="B"
app:layout_constraintBottom_toTopOf="@id/C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/A" />
<TextView
android:id="@+id/C"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@android:color/darker_gray"
android:text="C"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/B" />
</androidx.constraintlayout.widget.ConstraintLayout>
همان طور که در شکل5-1 مشاهده میکنید در این حالت اولین و آخرین المان بر روی لبههای لایوت قرار گرفته و بقیه به طور مساوی در لایوت توزیع میشوند.در مثال پایین ما سه المان A,B,C را دریک به صورت یک زنجیره Spread inside به هم متصل کرده ایم. تنها تفاوت کد نویسی این حالت با حالت قبل در این است که اولین المان مجموعه مقدار layout_constraintVertical_chainStyle را بهspread_inside تغییر میدهیم.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/A"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="A"
app:layout_constraintBottom_toTopOf="@id/B"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside" />
<TextView
android:id="@+id/B"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="B"
app:layout_constraintBottom_toTopOf="@id/C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/A" />
<TextView
android:id="@+id/C"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@android:color/darker_gray"
android:text="C"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/B" />
</androidx.constraintlayout.widget.ConstraintLayout>
تا قبل از معرفی این قابلیت در Constraint Layout برنامه نویسان تنها با استفاده از LinearLayout قادر به وزن دهی المانهای یک طرح بودند اما اکنون همان طور که در شکل 5-3 مشاهده میکنید با تعریف المانها به صورت یک زنجیره Weighted شما قادرید المانها را به هر مقدار که مایلید وزن دهی کنید. برای انجام این کار باید بسته به اینکه میخواهید وزن دهی به صورت افقی یا عمودی باشد طول یا ارتفاع المانهای زنجیره را برابر با 0dp (طول برای حالت افقی و ارتفاع برای حالت عمودی) قرار دهید و به هر یک از المانهای زنجیره ویژگی زیر را بیفزایید.
برای وزن دهی افقی کد:
app:layout_constraintHorizontal_weight="10"
برای وزن دهی عمودی کد:
app:layout_constraintVertical_weight="10"
در مثال پایین ما سه المان A,B,C را دریک به صورت یک زنجیره Weighted به هم متصل کرده ایم و به هر کدام از المانها به ترتیب وزن 10 و 20 و 30 را نسبت داده ایم.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/A"
android:layout_width="100dp"
android:layout_height="0dp"
android:background="@android:color/darker_gray"
android:text="A"
app:layout_constraintBottom_toTopOf="@id/B"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_weight="10" />
<TextView
android:id="@+id/B"
android:layout_width="200dp"
android:layout_height="0dp"
android:background="@android:color/darker_gray"
android:text="B"
app:layout_constraintBottom_toTopOf="@id/C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/A"
app:layout_constraintVertical_weight="20" />
<TextView
android:id="@+id/C"
android:layout_width="100dp"
android:layout_height="0dp"
android:background="@android:color/darker_gray"
android:text="C"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/B"
app:layout_constraintVertical_weight="30" />
</androidx.constraintlayout.widget.ConstraintLayout>
به این نکته توجه فرمایید که در زنجیره Weighted بر خلاف نوع زنجیره دیگر layout_constraintVertical_chainStyle را تعریف نکرده ایم و فقط با مقداردهی 0dp به ارتفاع المانها و تعریف layout_constraintVertical_weight وزن المانها را مشخص کرده ایم.
همانطور که در شکل 5-4 مشاهده میکنید در حالت Packed تمام المانهای زنجیره کاملا به هم میچسپند و در وسط لایوت قرار میگیرند. اگر نیاز داشتید زنجیره را بجای قرار گرفتن در وسط لایوت (50%) در نسبت دیگری قرار بدهید میتوانید از bias که در همین مقاله توضیح داده شد (مورد سوم) استفاده کنید.
در مثال پایین ما سه المان A,B,C را دریک به صورت یک زنجیره Packed به هم متصل کرده ایم و با استفاده از "layout_constraintVertical_bias="0.3 تمام المانهای زنجیره را در نسبت 30% عمودی از کل طرح قرار داده ایم.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
app:layout_constraintVertical_bias="0.3"
app:layout_constraintVertical_chainStyle="packed"
android:id="@+id/A"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="A"
app:layout_constraintBottom_toTopOf="@id/B"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/B"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="B"
app:layout_constraintBottom_toTopOf="@id/C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/A" />
<TextView
android:id="@+id/C"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@android:color/darker_gray"
android:text="C"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/B" />
</androidx.constraintlayout.widget.ConstraintLayout>
شرکت گوگل به عنوان توسعه دهنده سیستم عامل اندروید توجه ویژه ای به ConstraintLayout برای طراحی صفحات اندرویدی دارد و همواره امکانات و ویژگیهای زیادی را در بروز رسانیهای این لایوت اضافه میکند تا برنامه نویسان اندروید به سادگی هرچه تمامتر بتوانند طرح هایی با پیچیدگی بالا را پیاده سازی کنند که در این مقاله به مهمترین آنها پرداختیم .همچنین ConstraintLayout خود به تنهایی قادر به پیاده سازی انیمیشنها نیز هست که در مقالات بعدی به سایر این ویژگیها و نحوه پیاده سازی انیمیشن توسط ConstraintLayout خواهیم پرداخت. با ما همراه باشید. منبع: https://developer.android.com/training/constraint-layout
دوره الفبای برنامه نویسی با هدف انتخاب زبان برنامه نویسی مناسب برای شما و پاسخگویی به سوالات متداول در شروع یادگیری موقتا رایگان شد: