कम्पोज़ में ग्राफ़िक्स

कई ऐप्लिकेशन को यह ठीक से कंट्रोल करने की ज़रूरत होती है कि पेज पर क्या जानकारी दिखाई जाए स्क्रीन. यह स्क्रीन पर बॉक्स या गोला रखने जितना छोटा हो सकता है सही जगह पर दिखाई दे सकती है या हो सकता है कि उस पर ग्राफ़िक कई अलग-अलग स्टाइल के एलिमेंट होते हैं.

मॉडिफ़ायर और DrawScope के साथ बेसिक ड्रॉइंग

लिखें में किसी चीज़ को कस्टम बनाने का मुख्य तरीका मॉडिफ़ायर का इस्तेमाल करना है, जैसे कि Modifier.drawWithContent, Modifier.drawBehind, और Modifier.drawWithCache.

उदाहरण के लिए, अपने कंपोज़ेबल के पीछे कुछ ड्रॉ करने के लिए, ड्रॉइंग वाले निर्देशों को एक्ज़ीक्यूट करने के लिए, drawBehind मॉडिफ़ायर:

Spacer(
    modifier = Modifier
        .fillMaxSize()
        .drawBehind {
            // this = DrawScope
        }
)

अगर आपको सिर्फ़ एक कंपोज़ेबल की ज़रूरत है, तो Canvas कंपोज़ेबल. Canvas कंपोज़ेबल Modifier.drawBehind के आस-पास सुविधाजनक रैपर. Canvas को अपने लेआउट में उसी तरह से रखा जाता है जिस तरह Compose के किसी दूसरे यूज़र इंटरफ़ेस (यूआई) एलिमेंट को रखा जाता है. इस Canvas, एलिमेंट को उनकी स्टाइल पर पूरा कंट्रोल करके, एलिमेंट बनाए जा सकते हैं स्थान.

सभी ड्रॉइंग मॉडिफ़ायर, DrawScope को दिखाते हैं. यह स्कोप वाला ड्रॉइंग एनवायरमेंट है, जो अपनी स्थिति बनाए रखता है. इसकी मदद से, ग्राफ़िकल एलिमेंट के ग्रुप के लिए पैरामीटर सेट किए जा सकते हैं. DrawScope कई काम के फ़ील्ड उपलब्ध कराता है. जैसे, size, Size का मौजूदा डाइमेंशन बताने वाला Size ऑब्जेक्ट.

कुछ ड्रॉ करने के लिए, DrawScope पर ड्रॉ करने के कई फ़ंक्शन में से किसी एक का इस्तेमाल किया जा सकता है. उदाहरण के लिए, यह कोड स्क्रीन के सबसे ऊपर बाएं कोने में एक रेक्टैंगल बनाता है:

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasQuadrantSize = size / 2F
    drawRect(
        color = Color.Magenta,
        size = canvasQuadrantSize
    )
}

सफ़ेद बैकग्राउंड पर बना गुलाबी रेक्टैंगल, जो स्क्रीन का एक चौथाई हिस्सा भर लेता है
पहली इमेज. Compose में कैनवस का इस्तेमाल करके बनाया गया रेक्टैंगल.

ड्रॉइंग में बदलाव करने वाले अलग-अलग टूल के बारे में ज़्यादा जानने के लिए, ग्राफ़िक्स में बदलाव करने वाले टूल का दस्तावेज़ देखें.

कोऑर्डिनेट सिस्टम

स्क्रीन पर कुछ बनाने के लिए, आपको ऑफ़सेट (x और y) और आपका आइटम. DrawScope पर ड्रॉ करने के कई तरीकों से, पोज़िशन और साइज़ पैरामीटर की डिफ़ॉल्ट वैल्यू से मिलती हैं. आम तौर पर, डिफ़ॉल्ट पैरामीटर आइटम को कैनवस पर [0, 0] पॉइंट पर रखें और डिफ़ॉल्ट साइज़ सेट करें पूरे ड्रॉइंग एरिया को भरने वाला size है, जैसा कि ऊपर दिए गए उदाहरण में दिखाया गया है - आपको दिखेगा रेक्टैंगल सबसे ऊपर बाईं ओर मौजूद है. अपने आइटम के साइज़ और पोज़िशन में बदलाव करने के लिए, आपको Compose में मौजूद कोऑर्डिनेट सिस्टम को समझना होगा.

निर्देशांक सिस्टम का ऑरिजिन ([0,0]), ड्रॉइंग एरिया में सबसे ऊपर बाईं ओर मौजूद पिक्सल पर होता है. x दाईं ओर बढ़ने पर बढ़ता है और y नीचे की ओर बढ़ने पर बढ़ता है.

कोऑर्डिनेट सिस्टम दिखाने वाला ग्रिड, जिसमें सबसे ऊपर बाईं ओर [0, 0] और सबसे नीचे दाईं ओर [चौड़ाई, ऊंचाई] दिख रहा है
दूसरी इमेज. ड्रॉइंग कोऑर्डिनेट सिस्टम / ड्रॉइंग ग्रिड.

उदाहरण के लिए, अगर आपको कैनवस के सबसे ऊपर दाएं कोने से सबसे नीचे बाएं कोने तक डायगनल लाइन खींचनी है, तो DrawScope.drawLine() फ़ंक्शन का इस्तेमाल करें. साथ ही, उससे जुड़ी x और y पोज़िशन के साथ, शुरू और खत्म होने के ऑफ़सेट की जानकारी दें:

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasWidth = size.width
    val canvasHeight = size.height
    drawLine(
        start = Offset(x = canvasWidth, y = 0f),
        end = Offset(x = 0f, y = canvasHeight),
        color = Color.Blue
    )
}

बुनियादी बदलाव

DrawScope, ड्रॉइंग करने के निर्देश में बदलाव करने की सुविधा देता है. इससे, ड्रॉइंग करने के निर्देशों को बदला जा सकता है एक साथ काम करते हैं.

स्केल

इस्तेमाल की जाने वाली चीज़ें DrawScope.scale() किसी फ़ैक्टर से अपनी ड्रॉइंग कार्रवाइयों का साइज़ बढ़ाया जा सकता है. scale() जैसे ऑपरेशन, उससे जुड़े लैम्ब्डा फ़ंक्शन में मौजूद सभी ड्रॉइंग ऑपरेशन पर लागू होते हैं. उदाहरण के लिए, नीचे दिया गया कोड scaleX को 10 और scaleY को 15 गुना बढ़ाता है:

Canvas(modifier = Modifier.fillMaxSize()) {
    scale(scaleX = 10f, scaleY = 15f) {
        drawCircle(Color.Blue, radius = 20.dp.toPx())
    }
}

एक ऐसा सर्कल जिसे अलग-अलग हिस्सों में अलग-अलग स्केल किया गया है
तीसरी इमेज. कैनवस पर सर्कल पर स्केल वाली कार्रवाई लागू करना.

अनुवाद

ड्रॉइंग के ऑपरेशन को ऊपर, नीचे, बाएं या दाएं ले जाने के लिए, DrawScope.translate() का इस्तेमाल करें. उदाहरण के लिए, निम्न कोड ड्रॉइंग को 100 px दाईं ओर और 300 px ऊपर ले जाता है:

Canvas(modifier = Modifier.fillMaxSize()) {
    translate(left = 100f, top = -300f) {
        drawCircle(Color.Blue, radius = 200.dp.toPx())
    }
}

एक गोला जो केंद्र से दूर चला गया है
चौथी इमेज. कैनवस पर मौजूद सर्कल पर ट्रांसलेट ऑपरेशन लागू करना.

घुमाएं

पिवट पॉइंट के आस-पास ड्रॉइंग ऑपरेशन घुमाने के लिए, DrawScope.rotate() का इस्तेमाल करें. उदाहरण के लिए, यहां दिया गया कोड किसी रेक्टैंगल को 45 डिग्री घुमाता है:

Canvas(modifier = Modifier.fillMaxSize()) {
    rotate(degrees = 45F) {
        drawRect(
            color = Color.Gray,
            topLeft = Offset(x = size.width / 3F, y = size.height / 3F),
            size = size / 3F
        )
    }
}

एक फ़ोन, जिसकी स्क्रीन के बीच में आपको 45 डिग्री घुमाया गया है
पांचवीं इमेज. हम मौजूदा ड्रॉइंग स्कोप पर रोटेशन लागू करने के लिए rotate() का इस्तेमाल करते हैं. यह रेक्टैंगल को 45 डिग्री घुमाता है.

इनसेट

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

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasQuadrantSize = size / 2F
    inset(horizontal = 50f, vertical = 30f) {
        drawRect(color = Color.Green, size = canvasQuadrantSize)
    }
}

यह कोड, ड्रॉइंग के निर्देशों में पैडिंग जोड़ता है:

चारों ओर से पैड किया गया आयत
छठी इमेज. ड्रॉइंग करने के निर्देशों के लिए, इनसेट को लागू किया जा रहा है.

एक से ज़्यादा बदलाव

अपनी ड्रॉइंग में एक से ज़्यादा ट्रांसफ़ॉर्मेशन ऐक्शन लागू करने के लिए, DrawScope.withTransform() फ़ंक्शन, जो टैग बनाता है और कोई एक ट्रांसफ़ॉर्मेशन ऐक्शन लागू करता है, जिसमें आपकी पसंद के सभी बदलाव शामिल होते हैं. इसका इस्तेमाल किया जा रहा है अलग-अलग उपयोगकर्ताओं को नेस्ट किए गए कॉल करने के मुकाबले, withTransform() ज़्यादा बेहतर तरीके से काम करता है ट्रांसफ़ॉर्मेशन ऐक्शन होता है, क्योंकि सभी ट्रांसफ़ॉर्मेशन ऐक्शन एक साथ करने के बजाय, एक बार में इस्तेमाल करने के लिए, कंपोज़ की ज़रूरत के हिसाब से एक के बाद एक होने वाले बदलाव.

उदाहरण के लिए, नीचे दिया गया कोड, रेक्टैंगल पर ट्रांसलेशन और रोटेशन, दोनों को लागू करता है:

Canvas(modifier = Modifier.fillMaxSize()) {
    withTransform({
        translate(left = size.width / 5F)
        rotate(degrees = 45F)
    }) {
        drawRect(
            color = Color.Gray,
            topLeft = Offset(x = size.width / 3F, y = size.height / 3F),
            size = size / 3F
        )
    }
}

एक फ़ोन, जिसमें घुमा हुआ रेक्टैंगल, स्क्रीन की साइड में शिफ़्ट हो गया है
सातवीं इमेज. आयत को घुमाने और बाईं ओर ले जाने के लिए, withTransform का इस्तेमाल करें.

ड्रॉइंग से जुड़ी सामान्य कार्रवाइयां

टेक्स्ट बनाएं

Compose में टेक्स्ट ड्रॉ करने के लिए, आम तौर पर Text composable का इस्तेमाल किया जा सकता है. हालांकि, अगर आप DrawScope में हैं या आपको इसका इस्तेमाल करके, मैन्युअल तरीके से टेक्स्ट बनाना है कस्टमाइज़ करना है, तो आप DrawScope.drawText() तरीका.

टेक्स्ट ड्रॉ करने के लिए, rememberTextMeasurer का इस्तेमाल करके TextMeasurer बनाएं और मेज़रर के साथ drawText को कॉल करें:

val textMeasurer = rememberTextMeasurer()

Canvas(modifier = Modifier.fillMaxSize()) {
    drawText(textMeasurer, "Hello")
}

कैनवस पर 'नमस्ते' लिखा हुआ दिखाया गया है
आठवीं इमेज. कैनवस पर टेक्स्ट ड्रॉ करना.

टेक्स्ट को मेज़र करना

टेक्स्ट ड्रॉइंग करने की सुविधा, ड्रॉइंग के अन्य निर्देशों से अलग तरीके से काम करती है. आम तौर पर, आप ड्रॉइंग कमांड को आकार (चौड़ाई और ऊंचाई) के रूप में आकार दें, ताकि वह आकार/इमेज के रूप में ड्रॉ कर सके. टेक्स्ट का इस्तेमाल करने वाले कुछ पैरामीटर, रेंडर किए जाने वाले पेज का साइज़ कंट्रोल करते हैं टेक्स्ट, जैसे कि फ़ॉन्ट का साइज़, फ़ॉन्ट, लिगेचर, और अक्षरों के बीच की दूरी.

आप Compose की सुविधा का इस्तेमाल करके, TextMeasurer का इस्तेमाल कर सकते हैं. टेक्स्ट का साइज़, ऊपर दी गई बातों के आधार पर तय किया जा सकता है. अगर आपको कोई बैकग्राउंड बनाना है, टेक्स्ट के पीछे, मापी गई जानकारी का इस्तेमाल करके आप फ़ाइल का आकार जान सकते हैं. टेक्स्ट के अंदर टेक्स्ट का साइज़:

val textMeasurer = rememberTextMeasurer()

Spacer(
    modifier = Modifier
        .drawWithCache {
            val measuredText =
                textMeasurer.measure(
                    AnnotatedString(longTextSample),
                    constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()),
                    style = TextStyle(fontSize = 18.sp)
                )

            onDrawBehind {
                drawRect(pinkColor, size = measuredText.size.toSize())
                drawText(measuredText)
            }
        }
        .fillMaxSize()
)

यह कोड स्निपेट, टेक्स्ट पर गुलाबी बैकग्राउंड बनाता है:

कई लाइनों वाला टेक्स्ट, जो पूरे हिस्से का 2⁄3 साइज़ ले रहा है. इसमें एक रेक्टैंगल है
नौवीं इमेज. बैकग्राउंड में रेक्टैंगल के साथ, पूरे एरिया का ⅔ हिस्सा लेने वाला कई लाइन वाला टेक्स्ट.

सीमाओं, फ़ॉन्ट साइज़ या मेज़र किए गए साइज़ पर असर डालने वाली किसी भी प्रॉपर्टी में बदलाव करने पर, रिपोर्ट में नया साइज़ दिखता है. width और height, दोनों के लिए एक तय साइज़ सेट किया जा सकता है. इसके बाद, टेक्स्ट TextOverflow के सेट किए गए साइज़ के हिसाब से दिखता है. उदाहरण के लिए, नीचे दिया गया कोड, टेक्स्ट को कॉम्पोज़ेबल एरिया की ⅓ ऊंचाई और ⅓ चौड़ाई में रेंडर करता है. साथ ही, TextOverflow को TextOverflow.Ellipsis पर सेट करता है:

val textMeasurer = rememberTextMeasurer()

Spacer(
    modifier = Modifier
        .drawWithCache {
            val measuredText =
                textMeasurer.measure(
                    AnnotatedString(longTextSample),
                    constraints = Constraints.fixed(
                        width = (size.width / 3f).toInt(),
                        height = (size.height / 3f).toInt()
                    ),
                    overflow = TextOverflow.Ellipsis,
                    style = TextStyle(fontSize = 18.sp)
                )

            onDrawBehind {
                drawRect(pinkColor, size = measuredText.size.toSize())
                drawText(measuredText)
            }
        }
        .fillMaxSize()
)

अब टेक्स्ट, तय की गई सीमाओं में दिखता है और उसके आखिर में एलिप्सिस दिखता है:

गुलाबी बैकग्राउंड पर बनाया गया टेक्स्ट, जिसमें टेक्स्ट को कटा हुआ इलिप्सिस दिखाया गया है.
10वीं इमेज. TextOverflow.Ellipsis, जिसमें टेक्स्ट को मेज़र करने के लिए कंस्ट्रेंट तय होता है.

इमेज ड्रॉ करना

DrawScope की मदद से ImageBitmap लिखने के लिए, ImageBitmap.imageResource() का इस्तेमाल करके इमेज लोड करें. इसके बाद, drawImage को कॉल करें:

val dogImage = ImageBitmap.imageResource(id = R.drawable.dog)

Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
    drawImage(dogImage)
})

कैनवस पर बनाए गए कुत्ते की इमेज
11वीं इमेज. कैनवस पर ImageBitmap बनाना.

बुनियादी आकार बनाना

DrawScope पर आकृति ड्रॉइंग वाले कई फ़ंक्शन हैं. कोई आकार बनाने के लिए, पहले से तय किए गए ड्रॉ फ़ंक्शन में से किसी एक का इस्तेमाल करें, जैसे कि drawCircle:

val purpleColor = Color(0xFFBA68C8)
Canvas(
    modifier = Modifier
        .fillMaxSize()
        .padding(16.dp),
    onDraw = {
        drawCircle(purpleColor)
    }
)

एपीआई

आउटपुट

drawCircle()

वृत्त बनाना

drawRect()

draw rect

drawRoundedRect()

draw rounded rect

drawLine()

रेखा खींचना

drawOval()

ओवल आकार बनाना

drawArc()

आर्क ड्रॉ करना

drawPoints()

पॉइंट बनाना

पाथ बनाएं

पाथ, गणित के निर्देशों की एक सीरीज़ होती है. इसके नतीजे के तौर पर, एक बार ड्रॉइंग बनाई जाती है लागू किया गया. DrawScope, DrawScope.drawPath() तरीके का इस्तेमाल करके पाथ बना सकता है.

उदाहरण के लिए, मान लें कि आपको एक त्रिभुज बनाना है. पाथ जनरेट किया जा सकता है ड्रॉइंग एरिया के साइज़ का इस्तेमाल करके, lineTo() और moveTo() जैसे फ़ंक्शन करते हैं. इसके बाद, त्रिकोण बनाने के लिए, इस नए पाथ के साथ drawPath() को कॉल करें.

Spacer(
    modifier = Modifier
        .drawWithCache {
            val path = Path()
            path.moveTo(0f, 0f)
            path.lineTo(size.width / 2f, size.height / 2f)
            path.lineTo(size.width, 0f)
            path.close()
            onDrawBehind {
                drawPath(path, Color.Magenta, style = Stroke(width = 10f))
            }
        }
        .fillMaxSize()
)

Compose पर बनाया गया, उल्टा बैंगनी रंग का पाथ ट्राइऐंगल
12वीं इमेज. Compose में Path बनाना और ड्रॉइंग करना.

Canvas ऑब्जेक्ट ऐक्सेस किया जा रहा है

DrawScope से, आपके पास Canvas ऑब्जेक्ट का सीधे तौर पर ऐक्सेस नहीं होता है. इस्तेमाल करने के लिए पाने के लिए DrawScope.drawIntoCanvas() Canvas ऑब्जेक्ट का ही ऐक्सेस दें, ताकि आप फ़ंक्शन कॉल कर सकें.

उदाहरण के लिए, अगर आपके पास एक कस्टम Drawable है, जिसे आप तो आप कैनवस ऐक्सेस कर सकते हैं और Drawable#draw() को कॉल कर सकते हैं. Canvas ऑब्जेक्ट:

val drawable = ShapeDrawable(OvalShape())
Spacer(
    modifier = Modifier
        .drawWithContent {
            drawIntoCanvas { canvas ->
                drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt())
                drawable.draw(canvas.nativeCanvas)
            }
        }
        .fillMaxSize()
)

फ़ुल साइज़ में दिखने वाला अंडाकार ब्लैक शेपड्रॉवल
13वीं इमेज. Drawable बनाने के लिए कैनवस ऐक्सेस किया जा रहा है.

ज़्यादा जानें

Compose में ड्रॉ करने के बारे में ज़्यादा जानने के लिए, यहां दिए गए संसाधन देखें: