مقیاس بندی تصاویر در اندروید برای Compose و XML
تو این مطلب میخوام رازهایی از مقیاس بندی تصاویر در اندروید با استفاده از jetpack Compose و xml رو فاش کنم تا دیگه هیچ تصویری نتونه ظاهر برنامتو خراب کنه.
تاحالا واست پیش اومده موقع قرار دادن تصویر توی اپلیکیشنت به جای این که اپلیکیشنت زیبا تر بشه، کیفیتش بیاد پایین و به جذابیت ظاهر برنامت آسیب بزنه؟
مقیاس بندی تصاویر در اندروید با استفاده از XML
اگه پروژه شما بجای استفاده از jetpack compose، از xml استفاده میکنه توی این قسمت از مقاله راهنمای خوب و کاملی واسه مقیاس بندی یا همون image scaling براتون آماده کردم.
مقیاس بندی در اندروید یکی از ویژگیهای خوب Image View ها هست که معمولا باعث سردرگمی شما میشه مخصوصا مواردی که میبینید وقتی Scale Type روعوض میکنید، تغییری توی ظاهر لایتتون اعمال نمیشه.
اگه بلد باشید چطور باهاش رفتار کنید دیگه اینطور مشکلات پیش نمیاد پس حتما در ادامه با من همراه باشید.
خب; بریم سراغ scale type. این ویژگی که به صورت پیشفرض روی ImageView وجود داره تعین میکنهکه تصویرمون چطور باید در محدوده تعیین شده توسط ImageView نمایش داده بشه. و رفتار این اسکیل تایپ، به حالتی بستگی داره که شما بهش میدید.
نمونه کد xml برای مقیاس بندیهای مختلف
<ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="wrap_content" android:src="@drawable/your_image" android:scaleType="centerCrop" android:contentDescription="@string/description"/>
تمام حالتهایی که میتونه به خودش بگیره رو واستون اینجا قرار میدم:
- center: این حالت تصویر را بدون تغییر اندازه در مرکز Image View قرار میده. یعنی اگه تصویر بزرگتر از image view باشه ادامه تصویر که خارج از image view هست نمایش داده نمیشه و اگر هم کوچیک تر از ابعاد ایمیج ویو باشه اصلا تغییری نمیکنه. به مثال زیر توجه کنید:
- centerCrop: تصویر رو طوری تغییر میده که کل ‘ImageVIew’ پوشیده بشه و مرکز تصویر در مرکز Image View قرار بگیره. در این روش ابعاد تصویر طوری تغییر میکنه که ضلع کوچک تصویر (در مثال ما عرض) با بعد متناضر آن در ایمیج ویو برابر بشه. این یه جورایی یه روش بهینه هست واسه این که مقدار بیشتری از تصویر نمایش داده بشه. بعد از این که ابعاد تصویر رو با روشی که گفتم تغییر داد، اضافات تصویر که از ایمیج ویو بیرون زده رو میبره.
مثلا اگه تصویر شما دارای عرض 100 و طول 200 باشه و ایمیج ویو شما هم دارای عرض 200 و طول 500 باشه، میاد و تصویر شما رو (با حفظ مقیاس قبلی) طوری بزرگ میکنه که عرض تصویر شما هم بشه 200. پس از اونجایی که عرض تصویرتون دوبرابر شده و قرار بود مقیاس هم حفظ بشه، طول تصویر شما برابر با 400 میشه یعنی دوبرابر حالت قبلی. یعنی الان شما یک تصویر 200*400 بجای 100*200 دارید. حالا که ابعاد تصویر شما تماماً داخل ایمیج ویو جا میشه دیگه کل تصویر رو میتونید ببینید.
اما اگر حالتی بود که طول تصویر شما، از طول ایمیج ویو بزرگتر میشد، اونوقت دیگه اضافات تصویر که از ایمیج ویو بیرون میزنه، بریده میشه. مثال زیر هم میتونه کمکتون کنه:
- centerInside: این روش مقیاس تصویر رو تغییر میده به طوری که کاملاً درد داخل ایمیج ImageView جا بشه و مرکزش هم همچنان محفوظ بمونه. این یعنی اگر تصویر کوچیک تر از ایمیج ویو باشه دیگه ابعادش تغییر نمیکنه و اگر بزرگتر از ایمیج ویو باشه طوری ابعادش تغییر میکنه که کاملا داخل ایمیج ویو قرار بگیره.
- fitCenter: در این حالت تصویر چه کوچیک تر از ایمیج ویو باشه چه بزرگتر، فرقی نمیکنه. در هر دو حالت ابعاد تصویر رو طوری تغییر میده که کاملا داخل ایمیج ویو قرار بگیره و ایمیج ویو رو پر کنه. یعنی اگه تصویر کوچیک تر از ایمیج ویو بود اون بزرگش میکنه تا اندازه ایمیج ویو بشه و هیچ قسمتیش بیرون نزنه و اگر بزرگتر بود هم اون رو کوچیک میکنه تا دقیقا اندازه ایمیج ویو بشه.
در واقع تو این حالت داره ضلع بزرگتر تصویر رو با ضلع متناظرش در ایمیج ویو هم اندازه میکنه. مثال زیر میتونه بهتر این حالت رو توضیح بده:
- fitStart:دقیقا همون کار fitCenter رو انجام میده فقط اینبار بجای این که وسط ایمیج ویو قرارش بده، بالای ایمیج ویو قرارش میده. مثال زیر رو ببینید:ede
- fitEnd: این هم دقیقا مثل fitStart هست فقط بجای بالا، این بار در پایین ایمیج ویو قرار میگیره.
- fitXY: این حالت هم دیگه کلا هم طول و هم عرض تصویر شمارو دقیقا با طول و عرض ایمیج ویو هم اندازه میکنه. این حالت خوبیش اینه که هم کل ایمیج ویوتون پر میشه هم کل تصویرتون رو بدون برش دارید اما بدیش اینه که تصویرتون دفرمه میشه. تو مثال زیر کاملا این حالت رو نشون دادم:
مقیاس بندی تصاویر در اندروید با استفاده از Jetpack Compose
حالا توی این بخش از مطلب میخوایم در مورد مقیاس بندی تصاویر در اندروید برای پروژه هایی که با Jetpack Compose بالا اومدن صحبت کنیم.
توی جت پک کامپوز ۳ تا کامپوننت مهم داریم که برای نمایش تصویر ازشون استفاده میکنیم:
- Image: کامپوننت اصلی برای نمایش تصاویر در jetpack compose هست. این کامپوننت با استفاده از painter، تصویری که منبعش رو بهش میدیم، نمایش میده.
- Modifier: ابزاری هست برای تغییر خصوصیات و رفتار کامپوننتها مثلا میتونید برای تصاویر از fillMaxHeight, fillMaxWidth, dillMaxSize استفاده کنید تا تصویر تمام فضای مشخص شده رو پوشش بده یا با استفاده از padding, size, clip تصویرتون رو بیشتر شخصی سازی کنید.
- ContentScale: تعیین کننده نحوه قرار گیری و مقیاس بندی توی کامپوننت Image هست و مهم ترین حالتهای اون رو در زیر بهتون معرفی میکنم:
- Crop: تصویر رو طوری اسکیل میکنه که کل فضای مشخص شده رو پوشش بده و ممکنه بخشی از تصویر بریده بشه.
- Fit: این حالت تصویر رو بدون این که بریده بشه، در فضای مشخص شده به طور کامل جا میکنه.
- Inside: تصویر رو داخل فضا قرار میده طوری که هر دو بعد تصویربا همون نسبت قبلی تغییر میکنه تا جا بشه و اگه تصویر کوچیک تر از کانتینرش باشه با همون ابعاد خودش نمایش داده میشه.
منظورم از کانتینر همون فضایی هست که توسط modifier تعریف شده. (در مثال ما کانتینر یک مربع با اضلاع 200dp هست)
برای تست کدهای بالا روی دستگاه خودتون یک پروژه جت پک کامپوز توی اندروید استدیو ایجاد کنید و کدهای زیر رو توی MainActivity.kt قرار بدید:
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.contentscaletutorial.ui.theme.ContentScaleTutorialTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ContentScaleTutorialTheme { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { ImageContentScaleExample() } } } } } @Composable fun ImageContentScaleExample(modifier: Modifier = Modifier) { val image = painterResource(id = R.drawable.my_image2) Column(modifier = modifier.padding(16.dp)) { Text("Example of ContentScale in Compose", style = MaterialTheme.typography.bodyMedium) Image( painter = image, contentDescription = "Demo Image", modifier = Modifier.width(200.dp).height(200.dp), contentScale = ContentScale.Inside // Example of ContentScale ) } } @Preview(showBackground = true) @Composable fun ImageContentScalePreview() { ContentScaleTutorialTheme { ImageContentScaleExample() } }
مقایسه XML و Jetpack Compose در مقیاس بندی تصاویر در اندروید
ترجیح میدم این مقایسه رو داخل یک جدول بهتون نشون بدم :
ویژگی | Jetpack Compose | XML |
مزایا |
|
|
معایب |
|
|
پشتیبانی از انیمیشنها | پشتیبانی بالا با امکان ادغام آسون تر انیمیشنهای پیچیده | امکانات محدودتری برای انیمیشنها داره |
پشتیبانی از مولتیمدیا | خیلی آسون با سایر عناصر مولتی مدیا مثل ویدیو و صدا ادغام میشه | نیاز به کدنویسی بیشتر برای ادغام مدیا داره |
زمان بارگذاری و عملکرد | بهینهسازی بالا و سرعت بارگذاری بهتر UI | ممکنه کندتر باشه به خصوص تو دستگاههای قدیمیتر |
تجربه توسعهدهنده و زمان یادگیری | نیاز به یادگیری نحوه کدنویسی جدید و مدرن | مدیریت بهینهتر و دسترسی آسونتر به ریسورسها |
دسترسی و مدیریت ریسورسها | مدیریت بهینهتر و دسترسی آسونتر به ریسورسها | ممکنه نیاز به تنظیمات دستی بیشتری برای بهینهسازی استفاده از ریسورسها داشته باشه ، مثل تنظیم دستی سایز تصاویر یا مدیریت کش |
نکات پیشرفته
- بهینهسازی تصاویر
بهتره همیشه قبل از این که تصاویر رو توی اپلیکیشن استفاده کنید، اندازهی اونارو به اندازهای که میخواید داخل اپلیکیشن استفاده کنید، نزدیک کنید. اینطوری از مصرف بیش از حد حافظه جلوگیری میکنید. - استفاده از کتابخانههای بارگذاری تصویر مثل Glide یا Picasso
این کتابخونهها حافظه رو بهینه مدیریت میکنند و باعث میشن باگذاری تصاویر، سادهتر و سریعتر انجام بشه. مثلا برای نمایش یک تصویر از یک Url خاص میتونید به شکل زیر از گلاید استفاده کنید:ImageView imageView = findViewById(R.id.my_image_view); Glide.with(this).load("http://www.example.com/image.jpg").into(imageView);
فقط باید قبلش حتما دیپندنسی گلاید رو در فایل build.gradle اضافه کنید. برای راهنمایی بیشتر توی این زمینه مقاله آشنایی با گلاید و کویل رو میتونید بخونید.
- افزودن انیمیشنها به ImageView
انیمیشنها میتونن تجربه کاربری رو جذاب تر کنن. برای این کار میتونید از کلاس ObjectAnimator استفاده کنید. برای مثال میتونید از کد زیر برای چرخوندن دورانی یک تصویر استفاده کنید:ImageView imageView = findViewById(R.id.my_image_view); ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f); animator.setDuration(1000); animator.setRepeatCount(ObjectAnimator.INFINITE); animator.start();
راستی اگه احساس میکنی دوست داری بیشتر با مقیاس بندی تصاویر در اندروید و جت پک کامپوز آشنا بشی میتونی به بوت کمپ جت پک کامپوز در سایت یودمی مراجعه کنی تا بیشتر در موردش بدونی.