<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مژگان پیوندیان</title>
        <link>https://virgool.io/feed/@mozhepeivand</link>
        <description>https://www.linkedin.com/in/mozhganpeyvand/</description>
        <language>fa</language>
        <pubDate>2026-06-16 12:30:33</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1063604/avatar/jAh6cI.jpeg?height=120&amp;width=120</url>
            <title>مژگان پیوندیان</title>
            <link>https://virgool.io/@mozhepeivand</link>
        </image>

                    <item>
                <title>چگونه Jetpack Compose را به xml بیاوریم؟</title>
                <link>https://virgool.io/@mozhepeivand/%DA%86%DA%AF%D9%88%D9%86%D9%87-compose-%D8%B1%D8%A7-%D8%A8%D9%87-xml-%D8%A8%DB%8C%D8%A7%D9%88%D8%B1%DB%8C%D9%85-jh853mqqbnq7</link>
                <description>اگر پروژه های زیادی دارین که با xml نوشته شدن و دوست دارین توی ان های از تکنولوژی jetpack compose استفاده کنید این مقاله می تونه بهتون کمک کنه تا compose را وارد فایل های xml خود بکنیدو بتوانید از ویژگی های ان استفاده کنیدو کم کم تمام xml های خودرا به سمت compose ببرید.برای اشنایی کامل شما از روال کار یک پروژه معمولی ایجاد کردم تا به روال پروژه های xml تون نزدیکتر باشد.ابتدایک پروژه ی جدید به روش قبل می سازم و Empty Activity را انتخاب میکنم.(همانطور که میدانید برای ساختن یک پروژه با compose بایدEmpty Compose Activity را هنگام ساخت پروژه ی جدید انتخاب کنیم):ساخت پروژه ی جدیدسپس اسم وتنظیمات پیش فرض را تغییر نمی دهم و پروژه را می سازم و ان را ران می کنم:ران شدن mainActivityسپس برای اینکه پروژه ی ما به پروژه هایی که معمولا برنامه نویسان قبلا ان ها را ایجاد کردند نزدیک تر باشدیک فرگمنت ایجاد می کنم:ایجاد فرگمنت جدیدوفرگمنت جدید ساخته می شود:فرگمنت جدیدسپس تکنولوژی binding راوارد xml مربوط به فرگمنت خود می کنیم و تگ مربوط به ان را در gradle ماژول قرار میدهیمپیاده سازه binding در فرگمنتسپس navigation را به پروژه ی خود اضافه می کنیم و فرگمنت ساخته شده را به عنوان home درنظر میگیریم و مبدا اپ خود قرار میدهیم.نمایشی از navigationخب حالا وقتش رسید که به فرگمنت خود که دارای xml است compose را اضافه کنیم.(از اینجا به بعدمی تواند در پروژه های قبلی تون استفاده شود) ابتدا خط زیر رابه build.gradle مربوط به project اضافه می کنیم و ورژن مربوط به compose را مشخص می کنیم .ext{
    compose_version = &#039;1.0.1&#039;
}لازم به ذکر است ورژن کاتلینی که من استفاده میکنم به صورت زیر است:classpath &amp;quotorg.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21&amp;quotسپس خط زیررا به buildFeatrueموجوددر build.gradle درکنار dataBindingمربوط به ماژول اضافه می کنیم.buildFeatures {
    //noinspection DataBindingWithoutKapt
    dataBinding = true
    viewBinding = true
    compose = true
}و همچنین قسمت زیر را اضافه می کنیم:composeOptions {
    kotlinCompilerExtensionVersion compose_version
}حالا می توانیم به ویژگی های compose دسترسی داشته باشیم و از ویژگی های ان استفاده کنیم .سپس Dependency های مربوط به compose را به builde.gradle مربوط به ماژول اضافه می کنیم://compose
implementation(&amp;quotandroidx.compose.runtime:runtime:$compose_version&amp;quot)
implementation &amp;quotandroidx.compose.ui:ui:$compose_version&amp;quot
implementation &amp;quotandroidx.compose.material:material:$compose_version&amp;quot
implementation &amp;quotandroidx.compose.ui:ui-tooling-preview:$compose_version&amp;quotحالا وابستگی های مربوط به compose به پروژه اضافه شدند برای استفاده از compose درون xml به composeView نیاز داریم تا  objectهای مربوط به کامپوز خود را درون ان قرار دهیم پس این view را به xml مربوط به newFragmentاضافه می کنیم:وارد کردن ComposeView به xml مربوط به فرگمنتدرقسمت displayباکس مربوط به compose به صورت خاکستری ظاهر شده که من این view را به TextView به هم chain کردم:نمایشی از xml مربوط به فرگمنتسپس داخل newFragment از طریق binding به composeView دسترسی پیدامی کنیم و به صورت زیر یک textدرون composeView خود قرار می دهیم.دراین view هر لایه ای را می توانیم قرار دهیم برای پیاده سازی constraintLayout دراین قسمت می توانید از مقاله ی مربوط به پیاده سازی constraintLayout در compose استفاده کنید و برای اشنایی بیشتر از منطق پیاده سازی compose و نوشتن کدها مختلف دران می توانید از مقاله ی پیاده سازی state ها و استفاده از remember استفاده کنید .پیاده ساز یcompose داخل فرگمنتدراین قسمت از setViewCompositionStrategyاستفاده کردیم و به compose خودیک استراتژی دادیم وبا استفاده از ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed با destroy یا destroyView شدن فرگمنت compose نیز Destroy می شود و از بین میرودو درواقع به lifecycle فرگمنت وابسته میشود هنگام نابود شدن سپس کد خودرا ران میکنیم:ران شدن xml که دارای compose استهمانطور که میبیند compose درکنار ویجت TextView استفاده شده و هر ویجتی که نیاز داشته باشیم از طریق کد می  توانیم درون composeView قرار دهیم.امیدوارم مطالب گفته شده براتون اموزنده باشه و بتونین طبق مراحل گفته شده پیش برین و از مطلب استفاده کنین پیشنهادمی کنم حتما یکبار طبق روال پیش برین و روی یک پروژه  ان را اعمال کنین تا به طور کلی باساختار کار اشنابشین . اگر به مشکلی خوردین توی قسمت ثبت نظرات می تونین مطرح کنین تاباهم بتونیم راه حل براش پیداکنیم و درکل خوشحال میشم نظرتونو بدونم .موفق و تندرست باشین ?.</description>
                <category>مژگان پیوندیان</category>
                <author>مژگان پیوندیان</author>
                <pubDate>Mon, 20 Dec 2021 13:27:32 +0330</pubDate>
            </item>
                    <item>
                <title>استفاده از Remember و State ها در JetpackCompose</title>
                <link>https://virgool.io/@mozhepeivand/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-remember-%D9%88-state-%D9%87%D8%A7-%D8%AF%D8%B1-jetpackcompose-bvkngslecyfi</link>
                <description>دراین بخش قصد دارم نحوه ی استفاده از state هارا برای شما توضیح بدهم این مبحث فوق العاده کاربردی ومهم هست.ما تازمانی که محتوای static داشته باشیم نیازی به state ها نداریم چون دراین صورت محتوای ما نیازی به تغییر ندارد اما در اپلیکیشن ها معمولا به محتوای داینامیک نیاز است بنابراین ما نیاز داریم که درصورت انجام کاری در اپ تغییری ببینیم بهتر است از ابتدا با مفهوم recompose اشنا شویم :مفهوم Recomposition:بازترکیب یا Re composition فرآیند فراخوانی مجدد توابعی که با @Composable حاشیه نویسی شده اند راانجام میدهد این موضوع زمانی اتفاق می افتد که حالت ها یا state ها  تغییر کنند. وقتی Compose بر اساس حالت های جدید دوباره ساخته می شود را recomposition یابازترکیب می گویند،دراین فرایند فقط توابع یا لامبداهایی که ممکن است تغییر کرده باشند فراخوانی می‌ شوند و بقیه فراخوانی نمی‌شوند.فرض کنید یک اپلیکیشن شمارنده داریم به این صورت که بر روی یک دکمه کلیک می کنیم و مقدار عدد روی دکمه زیاد می شود هربار که روی دکمه میزنیم درواقع UIمربوط به دکمه ی ما دوباره ساخته می شود که به اصطلاح Redraw می شود و عدد جدید روی دکمه نمایش داده می شود به این فرایند Recompose می گویند که همان redrawیا rerun است.حالا به مثال زیر توجه کنید:فرض کنید یک دکمه داریم و میخواهیم بازدن روی این دکمه رنگ ان تغییر کند برای اینکار ابتدایک تابع Composable به اسم Color Box تعریف می کنیم قصد داریم کل پیاده سازی دکمه ی گفته شده دراین تابع باشد:سپس دراین تابع یک Box تعریف میکنیم:تابع clickable{} به این خاطر تعریف می شود که Box مثل یک دکمه عمل کند و بتوان روی ان click کرد.پیاده سازی Stateکامپوز اعلانی است و به این ترتیب تنها راه برای به روز رسانی آن فراخوانی همان تابع composable با آرگومان های جدید است. این آرگومان ها نمایش هایی از وضعیت رابط کاربری هستند. هر زمان که وضعیتی به روز می شود، composeمجدد صورت می گیرد. در نتیجه، چیزهایی مانند TextField به طور خودکار مثل عملکرد XML به روز نمی شوند. به یک composable باید به صراحت وضعیت جدید گفته شود تا مطابق آن بروز شود.حالت یا state شیئی است که به یک یا چند ویجت متصل است، حاوی داده است و مشتاق به روز رسانی ویجت ها از آن داده است. اگر تغییری در داده‌ها اتفاق بیفتد، به همه ویجت‌هایی که به آنها متصل است اطلاع می‌دهد.در jetpack compose مفهوم مدیریت stateهمان Observable pattern است که بیان می‌کند اگر تغییری در شیء تعریف شده رخ دهد، تمام اشیاء وابسته به آن را به طور خودکارتغییر می دهد.برای استفاده ازstate ها از MutableState استفاده می کنیم:interface MutableState&lt;T&gt; : State&lt;T&gt; {
    override var value: T
}خب به مثالمون برمی گردیم همانطور که گفتیم باید باهربار کلیک روی Box رنگ پس زمینه ی ان تغییر کند پس نباید به ان رنگ ثابت دهیم به این ترتیب یک state تعریف می کنیم ومقدار ان را به background میدهیم:در گذشته به جای mutableStateOf، از حاشیه‌نویسی Model @ استفاده می‌کردیم، اما درنسخه ی 0.1.0-dev12 منسوخ شد. سپس state{}  درنسخه ی 0.1.0-dev16 منسوخ شد.سپس در داخل تابع clickable هربار که روی Box کلیک کنیم مقدار این state مربوط به color را اپدیت می کنیم وبه متغیر color می دهیم:همانطور که مشاهده می کنید تابع تعریف شده ی Color سه مقدار قرمز و سبز و ابی دارد که به انها بصورت رندوم مقدارمی دهیم و درنهایت مقدار خروجی را به متغیرcolor می دهیم.هربار که مقدار این color که از نوع mutableState است تغییر می کند تابع Color Box دوباره برروی UIساخته می شود و Redrawیا به عبارتی recompose می شودپس به این ترتیب تمامی متغیر ها وتوابعی که در Color Box فراخوانی شده اند دوباره فراخوانی می شوند به این ترتیب تابع background دوباره مقدار جدید را دریافت میکند و رنگ Box تغییر میکند.مشکل پاراگراف قبل چیست؟همانطور که گفتیم در طی recompose تمامی متغیرها و توابع دوباره فراخوانی می شوند همانطور که در کد مشاهده می کنیددر طی recompose تابع colorBoxدر ابتدای به متغیر color مقدار پیش فرض زرد داده می شود پس دوباره مقدار زرد را به خود می گیرد و مقدار رندومی که قبلا ساخته شده بود از بین می رودو background دوباره بعد از هر بار کلیک به رنگ زرد در می اید !راه حل چیست؟استفاده از rememberتوابع Composable می توانند با استفاده از remember یک شی را در حافظه ذخیره کنند. stateموجود داخل remember بعد ازاینکه در ادامه ی کد مقداری می گیرد ان را درون حافظه ذخیره می کند و در طی recompose همان مقدار ذخیره شده درحافظه برگردانده می شود .در این قسمت remember به کمک ما می اید:همانطور که مشاهده می کنید متغیر color رادرون remember قرار دادیم که همانطور که از اسمش پیداست بعد از هر بار recompose مقدار قبلی متغیر colorرابه خاطر می سپارد ودرحافظه ذخیره می کند و باعث می شود متغیر دوباره مقدار پیش فرض را به خود نگیرد در این صورت مشکل ما حل میشود:به این صورت بعد از هربار کلیک رنگ Box تغییر میکند.کدنوشته شده دربالا به صورت زیراست:class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ColorBox(Modifier.fillMaxSize())
        }
    }
}

@Composable
fun ColorBox(modifier: Modifier = Modifier) {
    val color = remember { mutableStateOf(value = Color.Yellow) }

    Box(modifier = modifier
        .background(color.value)
        .clickable {
            color.value = Color(
                red = Random.nextFloat(),
                green = Random.nextFloat(),
                blue = Random.nextFloat()
            )
        }
    ) {

    }
}امیدوارم مفید بوده باشه موفق باشید.</description>
                <category>مژگان پیوندیان</category>
                <author>مژگان پیوندیان</author>
                <pubDate>Mon, 06 Dec 2021 15:46:29 +0330</pubDate>
            </item>
                    <item>
                <title>استفاده از Constraint Layout در Jetpack Compose</title>
                <link>https://virgool.io/@mozhepeivand/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-constraint-layout-%D8%AF%D8%B1-jetpack-compose-cionwjcpfkux</link>
                <description>اگر از دنیای xml وارد Jetpack Compose شدید پس با layout ها اشنا هستین سه نوع layout وجود داشت که به صورت زیر بود:1. Linear Layout2. Relative Layout3. Constraint Layoutدر این مقاله قصد دارم نحوه ی پیاده سازی Constraint Layout  در Jetpack Compose راتوضیح بدهم برای مطالعه ی این مقاله بهتر است با مفاهیم اولیه JetPack Compose تاحدی اشنا باشید.پیاده سازی Constraint Layout در xml به صورت drag and drop بود به این صورت که کامپوننت ها را درخود xml برمی داشتیم و روی صفحه قرار میدادیم سپس این کامپوننت هارا به هم وصل می کردیم و در همسایگی هم قرار می دادیم اما در jetpack compose به این صورت نیست و تمامی این روال را به صورت کد می توانیم می نویسیم.برای استفاده از constraint Layout در compose مراحل زیر را انجام می دهیم :1- ابتدا dependency زیر را به gradle مربوط به ماژول خود اضافه می کنیم:implementation &amp;quotandroidx.constraintlayout:constraintlayout-compose:1.0.0-rc02&amp;quot2- سپس  بایدمتغیری از نوع ConstraintSet تعریف کنین که به این صورت است:تعریف ConstraintSetدراین تابع میتوانیم constrain های مربوط به عناصر خودرا تعریف کنیم که درادامه خواهید دید.3- برای کامپوننت خود که دراینده نوع ان ( Button , Text View ,..) را مشخص خواهیم کرد ایدی تعریف می  کنید:تعریف اید ها در ConstraintSetدر این قسمت درواقع بااستفاده از تابع createRefFor یک reference درست کردیم که به  ایدی btn_login  اشاره می کند سپس ان را در متغیری به نام button میریزیم بعد ازان محدودیت های مربوط به این reference را بااستفاده از تابعی به نام constrain درادامه مشخص می کنند .4- محدودیت های  مربوط به عنصر خودرا تعیین می کنیم :تعریف ایدی ها و constrain ها در constraintSet این قسمت از کارشبیه به کاربا constraint Layout در xml است همانطور که مشاهده می کنید از تابع constrain استفاده شده و متغیری که برای ان ایدی تعریف کرده بودیم را به این تابع میدهیم سپس محدودیت های ان را مشخص میکنیم و start/end/top/bottom عنصر خود را به عنصر دیگر که برای ان ها ایدی تعریف کردیم و همینطور parent  می توانیم link کنیم.دراین قسمت به این صورت است که top عنصر button ما به top مربوط به parent متصل میشود و به همین ترتیب start ان به start مربوط به parent آن وصل میشود سپس عرض وارتفاع ان را مشخص میکنیم که هم میتوانیم برای ان عدد بگذاریم و هم میتوان از پارامتر های اماده ی دیگری از جمله موارد زیر استفاده کنیم:استفاده ازاپشن های Dimension5- دراین مرحله constraint Set هایی که ساختیم را به Constraint Layout می دهیم و برای ایدی هایی که مشخص کردیم عنصر تعیین می کنیم :تعریف ConstraintLayoutهمانطور که مشاهده میکنیم از layout Id استفاده کرده و ایدی ان را که در ConstraintSetتعریف کردیم به عنصری که نیاز داریم می دهیم.سپس میتوانید برنامه را ران کنید:برنامه ی ران شده کد های ذکر شده در بالاهمانطور که مشاهد میکنید در تصویر یک دکمه به نامcompose که قبلا ان را مشخص کردیم ایجاد شده است.نکته:برای تبدیل xmlبه کامپوز می توانیداز پلاگین استفاده کنید فقط لازم به ذکر است که این پلاگین برای تبدیل ویجت های ساده به کامپوز استفاده میشود وبرای materialوAppCompatکار نمیکند حتما به مثال ان توجه کنید.لازم به ذکر است که در constraint Set هر چندتا متغیر می توانیم تعریف کنیم و سپس constrainهای مربوط به ان را مشخص کنیم و ان هارا به Constraint Layout بدهیم :class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val constraints = ConstraintSet {
                val button = createRefFor(&amp;quotbtn_login&amp;quot)
                val textView = createRefFor(&amp;quottv_name&amp;quot)

                constrain(button) {
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    width = Dimension.value(100.dp)
                    height = Dimension.value(100.dp)
                }
                constrain(textView) {
                    top.linkTo(parent.top)
                    start.linkTo(button.end)
                    width = Dimension.value(100.dp)
                    height = Dimension.value(100.dp)
                }
            }
            ConstraintLayout(constraintSet = constraints, modifier = Modifier.fillMaxSize()) {

                Button( = { /*TODO*/ },
                    modifier = Modifier
                        .layoutId(&amp;quotbtn_login&amp;quot)
                        .background(Color.Green)) {
                   Text(text = &amp;quotCompose&amp;quot)
                }

                Text(
                    text = &amp;quotvirgool&amp;quot,
                    modifier = Modifier
                        .background(Color.Red)
                        .layoutId(&amp;quottv_name&amp;quot)
                )

            }


        }
    }
}
نکته پایانی:همانطور که مشاهده کردین در Jetpack Compose هم می توانیم از Constraint Layout استفاده کنیم ومجموعه ای از عناصر مختلف و حتی Layout های مختلف مربوط به  Jetpack Compose از جمله Box وColumnوRow را در ان قرار دهیم . برای استفاده از ConstraintLayout ابتدا یک ایدی تعریف می کنیم سپس محدودیت های مربوط به عنصری که ایدی ان را تعریف کردیم را مشخص می کنیم و درنهایت نوع عنصر (Button,TextView,TextField,...)را مشخص می کنیم.موفق باشید ?منبع : https://developer.android.com/jetpack/compose/layouts/constraintlayout </description>
                <category>مژگان پیوندیان</category>
                <author>مژگان پیوندیان</author>
                <pubDate>Mon, 06 Dec 2021 13:01:45 +0330</pubDate>
            </item>
            </channel>
</rss>