Computer >> कंप्यूटर >  >> प्रणाली >> Android

शुरुआती लोगों के लिए जेटपैक कंपोज़ ट्यूटोरियल - कंपोज़ेबल्स और रीकंपोज़िशन को कैसे समझें?

यह ट्यूटोरियल आपको Android पर Jetpack Compose UI लाइब्रेरी से संबंधित कुछ मूलभूत अवधारणाएं और शर्तें सिखाएगा।

हालांकि यह कंपोज़ करने के लिए एक शुरुआती गाइड है, लेकिन यह एंड्रॉइड के लिए एक शुरुआती गाइड नहीं होगा - इसलिए आपको कम से कम एक या दो एप्लिकेशन (हालांकि कंपोज़ में नहीं, जरूरी) का निर्माण करना चाहिए था।

शुरू करने से पहले, मैं शुरू में अधिक वरिष्ठ डेवलपर्स के लिए निर्देशित एक अनुवर्ती लेख लिखने की योजना बना रहा था जब तक कि मैं लेलैंड रिचर्डसन की दो भाग लेख श्रृंखला में नहीं आया। लेलैंड न केवल Jetpack Compose टीम में काम करने वाला एक सॉफ्टवेयर इंजीनियर है, बल्कि मैं देखता हूं कि वह एक महान लेखक भी है।

जबकि मुझे लगता है कि मेरा लेख Jetpack Compose की मूल बातों के परिचय के रूप में अपने आप खड़ा होगा, मैं दृढ़ता से सुझाव देता हूं कंपोज़ के साथ कुछ व्यावहारिक अनुभव प्राप्त करने के बाद आप उनके लेख पढ़ते हैं (या यदि आप उस तरह से सीखना पसंद करते हैं तो तुरंत)।

इस आलेख में वर्णित मुख्य शर्तें/अवधारणाएं:

  • पुराने व्यू सिस्टम और पदानुक्रम की संक्षिप्त समीक्षा
  • संयोजन और दृश्य के संबंध में वे कैसे खड़े होते हैं
  • पुनर्संरचना और इसे बहुत खराब तरीके से करने से कैसे बचें!

एक कंपोज़ेबल क्या है?

इस खंड में, हम Jetpack Compose लाइब्रेरी के सबसे बुनियादी हिस्से पर चर्चा करेंगे। यदि आप एक अनुभवी Android डेवलपर हैं, तो आप "क्या कंपोज़ेबल दृश्य हैं?" शीर्षक वाले उप-अनुभाग पर जा सकते हैं?

यदि आप पहले से ही व्यू सिस्टम से परिचित नहीं हैं, तो आपको अगला भाग पढ़ना चाहिए क्योंकि यह प्रेरित करने और समझने के लिए आवश्यक है कि कंपोज़ेबल क्या है।

पदानुक्रम देखें

एंड्रॉइड एसडीके (इस मंच पर उपयोगकर्ता इंटरफेस बनाने के लिए हम जिन पुस्तकालयों का उपयोग करते हैं) के संदर्भ में, एक दृश्य वह है जिसका उपयोग हम अपने अनुप्रयोगों को संरचना और शैली देने के लिए करते हैं।

यह किसी दिए गए यूजर इंटरफेस (यूआई) का सबसे मौलिक प्रकार का बिल्डिंग ब्लॉक या तत्व है, और इनमें से प्रत्येक बिल्डिंग ब्लॉक में निम्नलिखित प्रकार की जानकारी होगी (अन्य बातों के अलावा):

  • X और Y स्टार्ट और एंड पोजीशन जो कंप्यूटर को बताती है कि डिवाइस स्क्रीन पर व्यू कहां खींचना है
  • रंग और अल्फ़ा (पारदर्शिता) मान
  • फ़ॉन्ट जानकारी, टेक्स्ट, प्रतीक और चित्र
  • उपयोगकर्ता इंटरैक्शन (क्लिक) या एप्लिकेशन के डेटा में परिवर्तन जैसी घटनाओं पर आधारित व्यवहार (उस पर बाद में अधिक)

यह समझना महत्वपूर्ण है कि एक दृश्य एक बटन जैसा कुछ हो सकता है (आमतौर पर "विजेट" के रूप में जाना जाता है), लेकिन यह पूरी स्क्रीन, स्क्रीन के हिस्से या अन्य चाइल्ड व्यू के लिए एक कंटेनर भी हो सकता है

ऐसे कंटेनर संदर्भ के आधार पर आमतौर पर लेआउट या व्यूग्रुप के रूप में जाना जाता है। और, एक ही प्रकार की अधिकांश जानकारी को एक विजेट के रूप में साझा करते समय, उनमें अन्य दृश्यों को व्यवस्थित और प्रदर्शित करने के तरीके के बारे में जानकारी भी होती है जो नेस्टेड हैं उनके भीतर।

इसे ध्यान में रखते हुए, हम दृश्य प्रणाली की इस समीक्षा के महत्वपूर्ण भाग पर पहुंचते हैं:पदानुक्रम देखें . वेब डेवलपर्स के लिए, व्यू पदानुक्रम अनिवार्य रूप से दस्तावेज़ ऑब्जेक्ट मॉडल (DOM) का Android का संस्करण है।

एंड्रॉइड डेवलपर्स के लिए, आप व्यू पदानुक्रम को उन सभी दृश्यों के आभासी प्रतिनिधित्व के रूप में सोच सकते हैं जिन्हें आपने एक्सएमएल फाइलों में या जावा या कोटलिन में प्रोग्रामेटिक रूप से परिभाषित किया है।

इसे स्पष्ट करने के लिए, आइए ऐसी XML फ़ाइल को देखें (इसका बारीकी से अध्ययन करने की कोई आवश्यकता नहीं है, बस नाम नोट करें)। फिर, डिबगर/स्टेपर टूल का उपयोग करके, हम देखेंगे कि यह फ्रैगमेंट के मेमोरी स्पेस में कैसा दिखता है जो इस फ़ाइल को फुलाता है:

fragment_hour_view.xml:

<?xml version=”1.0" encoding=”utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=”https://schemas.android.com/apk/res/android"
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:id=”@+id/root_hour_view_fragment”
xmlns:app=”https://schemas.android.com/apk/res-auto"
>
<androidx.compose.ui.platform.ComposeView
android:id=”@+id/tlb_hour_view”
//...
 />
<com.wiseassblog.samsaradayplanner.ui.managehourview.HourToggleView
android:id=”@+id/vqht_one”
//...
/>
<com.wiseassblog.samsaradayplanner.ui.managehourview.HourToggleView
android:id=”@+id/vqht_two”
//...
/>
<com.wiseassblog.samsaradayplanner.ui.managehourview.HourToggleView
android:id=”@+id/vqht_three”
//...
/>
<com.wiseassblog.samsaradayplanner.ui.managehourview.HourToggleView
android:id=”@+id/vqht_four”
//...
/>
</androidx.constraintlayout.widget.ConstraintLayout>

स्मृति स्थान (Fragment)HourView.kt:

शुरुआती लोगों के लिए जेटपैक कंपोज़ ट्यूटोरियल - कंपोज़ेबल्स और रीकंपोज़िशन को कैसे समझें?
दृश्य पदानुक्रम की छवि

डिबगर और स्टेपर टूल मेरे कुछ पसंदीदा तरीके हैं जो यह जानने के लिए हैं कि कोड के हुड के नीचे क्या चल रहा है जिसका मैं विभिन्न पुस्तकालयों से उपयोग करता हूं। इसे कुछ समय दें!

आपको यह XML फ़ाइल दिखाने का उद्देश्य और यह एक प्रक्रिया . में क्या बदल जाती है (एक प्रक्रिया बस एक प्रोग्राम है जो चल रहा है डिवाइस पर), यह प्रदर्शित करने के लिए है कि किसी XML फ़ाइल में नेस्टेड दृश्य रनटाइम पर नेस्टेड व्यू पदानुक्रम में कैसे परिवर्तित होते हैं।

उम्मीद है, पुराने सिस्टम के काम करने के सरल लेकिन ठोस मॉडल के साथ, हम इसकी तुलना नए सिस्टम से कर सकते हैं।

क्या कंपोज़ेबल व्यू हैं?

जब मैंने कंपोज़ के साथ काम करना शुरू किया, तो यह मेरे द्वारा पूछे गए पहले प्रश्नों में से एक था, और मुझे जो उत्तर मिला है, वह है हां और नहीं

हां , इस अर्थ में कि एक कंपोज़ेबल एक दृश्य के समान वैचारिक भूमिका को पूरा करता है पुरानी व्यवस्था में। एक कंपोज़ेबल एक बटन की तरह एक विजेट हो सकता है, या एक कंटेनर जैसे कि एक ConstraintLayout (यह ध्यान देने योग्य है कि ConstraintLayout का एक Composable कार्यान्वयन उपलब्ध है)।

नहीं , इस अर्थ में कि UI अब दृश्य पदानुक्रम (इंटरऑपरेबिलिटी से जुड़ी स्थितियों के अलावा) में वस्तुतः प्रतिनिधित्व नहीं करता है। इसके साथ ही कहा जा रहा है कि, UI का वस्तुतः प्रतिनिधित्व करने और उसका ट्रैक रखने के लिए कंपोज़ जादू का उपयोग नहीं करता है। इसका मतलब यह है कि इसकी अपनी एक चीज होनी चाहिए जो वैचारिक रूप से व्यू पदानुक्रम के समान हो।

आइए इस बात पर एक बहुत ही संक्षिप्त नज़र डालते हैं। यहां, हमारे पास एक गतिविधि है जो setContent {…} . का उपयोग करती है कंपोज़ेबल को स्वयं से बाँधने का कार्य:

ActiveGameActivity.kt:

class ActiveGameActivity : AppCompatActivity(), ActiveGameContainer {
private lateinit var logic: ActiveGameLogic
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val viewModel = ActiveGameViewModel()
    setContent {
        ActiveGameScreen(
            onEventHandler = {
                logic.onEvent(it)
            },
            viewModel
        )
    }
    logic = buildActiveGameLogic(this, viewModel, applicationContext)
}
//…
}

ActiveGameScreen.kt:

@Composable
fun ActiveGameScreen(
    onEventHandler: ((ActiveGameEvent) -> Unit),
    viewModel: ActiveGameViewModel
) {
    //...

    GraphSudokuTheme {
        Column(
            Modifier
                .background(MaterialTheme.colors.primary)
                .fillMaxHeight()
        ) {
            ActiveGameToolbar(
                clickHandler = {
                    onEventHandler.invoke(
                        ActiveGameEvent.OnNewGameClicked
                    )
                }
            )

            Box {
              //content
            }
        }
    }
}

कंपोज़ में, व्यू पदानुक्रम को किसी ऐसी चीज़ से बदल दिया जाता है जिसे हम खोज सकते हैं यदि हम वास्तव में mWindow में गहराई से खुदाई करते हैं। इस गतिविधि का क्षेत्र। उस क्षेत्र के भीतर दृश्य पदानुक्रम का वैचारिक प्रतिस्थापन है: Composer और इसके slotTable .

शुरुआती लोगों के लिए जेटपैक कंपोज़ ट्यूटोरियल - कंपोज़ेबल्स और रीकंपोज़िशन को कैसे समझें?

इस बिंदु पर, यदि आप Composer . का विस्तृत अवलोकन चाहते हैं और इसका slotTable , मुझे फिर से सुझाव देना चाहिए कि आप लेलैंड का लेख पढ़ें (वह भाग 2 में विस्तार से जाता है)। कंपोज़र और उसके स्लॉटटेबल की तुलना में कंपोज़ पदानुक्रम के लिए और भी बहुत कुछ है, लेकिन यह हमें आरंभ करने के लिए पर्याप्त होना चाहिए।

सामान्य शब्दों में, Jetpack Compose उस चीज़ का उपयोग करता है जिसे हम इसके Compose Hierarchy कह सकते हैं (जो कंपोज़र और उसके स्लॉटटेबल जैसी चीज़ों से बना और प्रबंधित होता है)।

फिर से, यह दृश्य पदानुक्रम के समान वैचारिक विचार है, स्मृति स्थान में वस्तुओं का एक समूह जो सामूहिक रूप से UI का प्रतिनिधित्व करता है, लेकिन इसे बहुत अलग तरीके से लागू किया जाता है।

हालाँकि, एक महत्वपूर्ण अंतर है, जिसे तकनीकी रूप से समझना मुश्किल है, लेकिन सिद्धांत रूप में समझना आसान है। यह वह तरीका है जिससे कंपोज़, कंपोज़ पदानुक्रम के अपडेट को हैंडल करता है:पुनर्संरचना

रीकंपोज़िशन:कंपोज़ UI को कैसे अपडेट करें

मेरे ईएसएल दोस्तों के लिए, कंपोज़ शब्द लैटिन componre . से आया है , जिसका मोटे तौर पर अर्थ है "एक साथ रखना।" संगीत लिखने वाले को अक्सर "संगीतकार" कहा जाता है, जिसे एक या एक से अधिक वाद्ययंत्रों से आने वाले नोटों को एक रचना (गीत) में एक साथ रखने के बारे में सोचा जा सकता है।

एक साथ रखने का तात्पर्य है कि अलग-अलग टुकड़े हैं। यह समझना महत्वपूर्ण है कि लगभग कोई भी अच्छा सॉफ़्टवेयर डेवलपर अपने कोड को सबसे छोटे उचित भागों में विभाजित करने के लिए कम से कम कुछ प्रयास करता है।

मैं उचित . का उल्लेख करता हूं , क्योंकि मुझे लगता है कि डीआरवाई (डोन्ट रिपीट योरसेल्फ) जैसे सिद्धांतों का पालन केवल उस सीमा तक किया जाना चाहिए, जहां वे पैदा होने से ज्यादा समस्याओं का समाधान करते हैं।

इस अवधारणा को लागू करने के कई लाभ हैं, जिसे अक्सर प्रतिरूपकता कहा जाता है, (या जैसा कि मैं पसंद करता हूं, चिंताओं का पृथक्करण, या एसओसी)। मुझे पता है कि इसे पढ़ने वाले आप में से कुछ लोग सोच सकते हैं कि मैं सिर्फ लेलैंड ने अपने लेख में जो कहा है, उसकी नकल कर रहा हूं, लेकिन मैं कई वर्षों से एसओसी को सॉफ्टवेयर आर्किटेक्चर के स्वर्ण सिद्धांत के रूप में बात कर रहा हूं।

जहां यह कंपोज़ में चलता है, वही सिद्धांत है जिसे हम लोकप्रिय Javascript लाइब्रेरी प्रतिक्रिया में देखते हैं . जब ठीक से किया जाता है, तो कंपोज़ केवल कंपोज़ेबल्स (यूआई के भाग/तत्व) को "पुन:तैयार" (फिर से तैयार करना, फिर से प्रस्तुत करना, अपडेट करना, जो कुछ भी) करेगा, जिसे पुन:संयोजित करने की आवश्यकता है।

जब किसी एप्लिकेशन के प्रदर्शन की बात आती है तो यह बेहद महत्वपूर्ण है। ऐसा इसलिए है क्योंकि UI को फिर से बनाना, चाहे वह पुराने व्यू सिस्टम में हो या कंपोज़ में, सिस्टम संसाधनों के लिए महंगा है।

यदि आप जागरूक नहीं थे, तो पुराने RecyclerView का पूरा उद्देश्य (जो कि 2016 में मैंने पहली बार एक ट्यूटोरियल बनाया था!) ​​डेटा की सूची में ViewHolder पैटर्न को नियोजित करना था। इसने प्रत्येक सूची आइटम के लिए लगातार नए दृश्यों को बढ़ाने (बनाने) की आवश्यकता से बचा लिया।

इस लेख में मेरा लक्ष्य ज्यादातर सिद्धांत पर ध्यान केंद्रित करना था, क्योंकि मैं अगले कुछ महीनों में बहुत सारी व्यावहारिक सामग्री लिखूंगा। हालांकि, मैं अपने प्रत्यक्ष अनुभव से एक कहानी के साथ लेख को समाप्त करूंगा, जो आपको यह समझने में मदद करेगा कि पुनर्संरचना कैसे काम करती है, और इसे बहुत खराब तरीके से करने से कैसे बचें!

स्टॉपवॉच का उदाहरण

अपने पहले पूर्ण कंपोज़ एप्लिकेशन के लिए, मैंने सुडोकू बनाने का निर्णय लिया। इसके कई कारण हैं, जिसमें यह तथ्य भी शामिल है कि मैं एक ऐसा प्रोजेक्ट चाहता था जिसमें अत्यधिक जटिल UI न हो। मैं ग्राफ डीएस और एल्गोस में गहराई से गोता लगाने का मौका भी चाहता था, जो सुडोकू पहेली के लिए काफी उपयुक्त हैं।

एक चीज जो मैं चाहता था वह एक स्टॉपवॉच थी जो इस बात पर नज़र रखेगी कि उपयोगकर्ता को पहेली को पूरा करने में कितना समय लगा:

शुरुआती लोगों के लिए जेटपैक कंपोज़ ट्यूटोरियल - कंपोज़ेबल्स और रीकंपोज़िशन को कैसे समझें?
ग्राफ सुडोकू पहेली

जैसा कि मेरे पेशे में अक्सर होता है, मुझे उम्मीद थी कि यह टाइमर वास्तव में जोड़ने की तुलना में बहुत आसान होगा। मैंने एंड्रॉइड के क्रोनोमीटर क्लास के साथ-साथ जावा टाइमर क्लास के साथ खिलवाड़ किया, और दोनों ने अलग-अलग लेकिन फिर भी एप्लिकेशन-ब्रेकिंग समस्याएं प्रस्तुत कीं।

आखिरकार मैंने एक कदम पीछे हटकर महसूस किया कि मैं कोटलिन में लिख रहा हूं। इसलिए मैंने अपने प्रेजेंटेशन लॉजिक क्लास में एक कोरआउटिन आधारित टाइमर सेट किया (इसे वहां रखने के लिए सबसे अधिक समझ में आया), जो हर सेकेंड में मेरे व्यूमोडेल को अपडेट करेगा:

Class ActiveGameLogic(…):…{
//…
inline fun startCoroutineTimer(
    delayMillis: Long = 0,
    repeatMillis: Long = 1000,
    crossinline action: () -> Unit
) = launch {
    delay(delayMillis)
    if (repeatMillis > 0) {
        while (true) {
            action()
            delay(repeatMillis)
        }
    } else {
        action()
    }
}
private fun onStart() =
launch {
    gameRepo.getCurrentGame(
    { puzzle, isComplete ->
        viewModel.initializeBoardState(
            puzzle,
            isComplete
    )
        if (!isComplete) timerTracker = startCoroutineTimer {
            viewModel.updateTimerState()
        }
    },{
        container?.onNewGameClick()
    })
}
//…
}

व्यूमोडेल (एएसी से नहीं - मैं अपने स्वयं के वीएम लिखता हूं। लेकिन कंपोज में पहले से ही एएसी वीएम के साथ अच्छी इंटरऑपरेबिलिटी है जो मैं देख सकता हूं।) कॉलबैक फ़ंक्शंस के उजागर संदर्भ, जो कि मैं अपने कंपोज़ेबल्स को अपडेट करने के लिए उपयोग करूंगा:

class ActiveGameViewModel {
    //…
    internal var subTimerState: ((Long) -> Unit)? = null
    internal var timerState: Long = 0L
    //…
    internal fun updateTimerState(){
        timerState++
        subTimerState?.invoke(timerState)
    }
//…
}

अब महत्वपूर्ण हिस्सा आता है! हम कंपोज़ की कुछ विशेषताओं, जैसे कि remember का उपयोग करके कंपोज़ पदानुक्रम के पुनर्संरचना को ट्रिगर कर सकते हैं समारोह:

var timerState by remember {
    mutableStateOf(“”)
}

अगर आपको पता होना चाहिए, तो ये सुविधाएं slotTable . में आपको जो कुछ भी याद है उसकी स्थिति को स्टोर करती हैं . संक्षेप में, यहां राज्य शब्द का अर्थ डेटा की वर्तमान "स्थिति" है, जो केवल एक खाली स्ट्रिंग के रूप में शुरू होता है।

यहां पर मैंने चीजों को खराब कर दिया . मैंने अपने साधारण टाइमर को कंपोज़ेबल अपने स्वयं के फ़ंक्शन (लागू एसओसी) में खींच लिया था, और मैं timerState में गुजर रहा था उस कंपोज़ेबल के पैरामीटर के रूप में।

हालांकि, उपरोक्त स्निपेट टाइमर के पैरेंट कंपोज़ेबल में बैठे थे, जो UI के सबसे जटिल हिस्से के लिए एक कंटेनर था (एक 9x9 सुडोकू के लिए बड़ी संख्या में विजेट की आवश्यकता होती है):

@Composable
fun GameContent(
    onEventHandler: (ActiveGameEvent) -> Unit,
    viewModel: ActiveGameViewModel
) {
    Surface(
        Modifier
            .wrapContentHeight()
            .fillMaxWidth()
    ) {
        BoxWithConstraints(Modifier.background(MaterialTheme.colors.primary)) {
            //…
            ConstraintLayout {
                val (board, timer, diff, inputs) = createRefs()
                var isComplete by remember {
                    mutableStateOf(false)
                }
                var timerState by remember {
                    mutableStateOf("")
                }
                viewModel.subTimerState = {
                    timerState = it.toTime()
                }
                viewModel.subIsCompleteState = { isComplete = it }
            //…Sudoku board
            //Timer
                Box(Modifier
                    .wrapContentSize()
                    .constrainAs(timer) {
                        top.linkTo(board.bottom)
                        start.linkTo(parent.start)
                    }
                    .padding(start = 16.dp))
                {
                    TimerText(timerState)
                }
            //…difficulty display
            //…Input buttons
            }
        }
    }
}
@Composable
fun TimerText(timerState: String) {
    Text(
        text = timerState,
        style = activeGameSubtitle.copy(color = MaterialTheme.colors.secondary)
    )
}

यह कुछ काफी अंतराल और अनुत्तरदायीता पैदा कर रहा था। डीबगर का भारी उपयोग करके, मैं यह पता लगाने में सक्षम था कि क्यों। क्योंकि मेरा timerState वेरिएबल को पैरेंट कंपोज़ेबल के अंदर बनाया और अपडेट किया गया था, यह UI के उस पूरे हिस्से के पुनर्संरचना को ट्रिगर कर रहा था। हर. अकेला। टिक करें।

उपयुक्त कोड को TimerText . में ले जाने के बाद रचना योग्य, चीजें बहुत आसानी से काम करती हैं:

@Composable
fun TimerText(viewModel: ActiveGameViewModel) {
    var timerState by remember {
        mutableStateOf("")
    }

    viewModel.subTimerState = {
        timerState = it.toTime()
    }

    Text(
        text = timerState,
        style = activeGameSubtitle.copy(color = MaterialTheme.colors.secondary)
    )
}

उम्मीद है कि मैंने आपको पुनर्संरचना की एक कामकाजी समझ दी है और इसे गलत तरीके से करने के सबसे बड़े तरीकों में से एक है।

प्रदर्शन के लिए अनावश्यक पुनर्संरचना से बचना अविश्वसनीय रूप से महत्वपूर्ण है। और अब तक ऐसा लगता है कि एसओसी को सख्ती से लागू करना, यहां तक ​​​​कि याद रखने की स्थिति को अलग-अलग कंपोज़ेबल में रखने की बात मानक अभ्यास बन जाना चाहिए।

संसाधन और सहायता

अगर आपको यह लेख पसंद आया है, तो कृपया इसे सोशल मीडिया पर साझा करें और मेरे अन्य लेख फ्रीकोडकैंप पर देखें। मेरा एक YouTube चैनल भी है जिसमें सैकड़ों ट्यूटोरियल हैं, और मैं विभिन्न प्लेटफार्मों पर एक सक्रिय लेखक हूं।

मेरे साथ सोशल मीडिया पर जुड़ें

आप मुझे यहां इंस्टाग्राम पर और यहां ट्विटर पर ढूंढ सकते हैं।

साथ ही, मैं जेटपैक कंपोज़ के साथ शुरू करने के लिए उपयोग किए जाने वाले एकल संसाधन को इंगित करना चाहता हूं:अच्छे डेवलपर्स से कार्य कोड नमूने।


  1. Android पर iPhone इमोजी कैसे देखें

    इस बात से कोई इंकार नहीं है कि iPhone इमोजी अद्भुत हैं, लेकिन क्या होगा यदि आप Android उपकरणों के साथ आने वाली विविधता को पसंद करते हैं? आप अभी भी Android पर iPhone इमोजी देख सकते हैं। यदि आप iPhone से Android पर स्विच कर रहे हैं और अपने पसंदीदा इमोजी का उपयोग करना चाहते हैं तो यह बहुत अच्छी खबर है।

  1. Android दृश्यता श्रोताओं का उपयोग कैसे और क्यों करें

    एंड्रॉइड यूआई दृश्यों से बनाया गया है, और एक नियमित एप्लिकेशन में, आमतौर पर उनमें से कई होते हैं। यह पता लगाने के लिए कि उपयोगकर्ता वर्तमान में किस दृश्य को देख रहा है, आपको दृश्यता श्रोता . स्थापित करने की आवश्यकता है । किसी दृश्य की दृश्यता स्थिति की पहचान करने के लिए आपके पास विभिन्न विकल्पों के

  1. अपने कोटलिन एंड्रॉइड एनिमेशन को कैसे सुलभ बनाएं

    पहली बार Android योगदान के लिए उदाहरणों पर शोध करते समय, कोटलिन में लिखे गए एनिमेशन के लिए कुछ उदाहरण मौजूद थे। देशी एनिमेशन में अभिगम्यता संबंधी विचारों के कुछ कोड उदाहरण भी थे। तो अब हम शुरू करें! आइए कोटलिन में एक देशी विस्तार एनीमेशन लिखने पर ध्यान दें, और बात करें कि टॉकबैक या बढ़े हुए टेक्स्ट