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>
تا قبل از معرفی این قابلیت در ConstraintLayout برنامهنویسان تنها با استفاده از 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
دوره الفبای برنامه نویسی با هدف انتخاب زبان برنامه نویسی مناسب برای شما و پاسخگویی به سوالات متداول در شروع یادگیری موقتا رایگان شد: