Canvas
कंपोज़ेबल के अलावा, Compose में कई काम के ग्राफ़िक मौजूद हैं
Modifiers
, जो कस्टम कॉन्टेंट बनाने में मदद करते हैं. ये मॉडिफ़ायर काम के हैं
क्योंकि इन्हें किसी भी कंपोज़ेबल में लागू किया जा सकता है.
ड्रॉइंग मॉडिफ़ायर
सभी ड्रॉइंग कमांड, Compose में ड्रॉइंग मॉडिफ़ायर की मदद से पूरे किए जाते हैं. यहां हैं Compose में तीन मुख्य ड्रॉइंग मॉडिफ़ायर:
ड्रॉइंग के लिए बुनियादी मॉडिफ़ायर drawWithContent
है. यहां आपके पास अपने Composable के ड्रॉइंग क्रम और मॉडिफ़ायर में दिए गए ड्रॉइंग निर्देशों को तय करने का विकल्प होता है. drawBehind
एक drawWithContent
के चारों ओर एक सुविधाजनक रैपर है, जिसमें
कंपोज़ेबल के कॉन्टेंट के पीछे सेट किया गया ड्रॉइंग ऑर्डर. drawWithCache
उसके अंदर से onDrawBehind
या onDrawWithContent
को कॉल करता है - और
बनाए गए ऑब्जेक्ट को कैश मेमोरी में सेव करने का तरीका.
Modifier.drawWithContent
: ड्रॉइंग का क्रम चुनें
Modifier.drawWithContent
आपको
प्रोजेक्ट के कॉन्टेंट से पहले या बाद में DrawScope
कार्रवाइयां करनी होंगी
कंपोज़ेबल. इसके बाद, इसका असल कॉन्टेंट रेंडर करने के लिए drawContent
को कॉल करना न भूलें
कंपोज़ेबल. इस मॉडिफ़ायर की मदद से, कार्रवाइयों का क्रम तय किया जा सकता है, अगर
आपको अपनी पसंद के मुताबिक बनाई गई ड्रॉइंग से पहले या बाद में कॉन्टेंट बनाना है
कार्रवाइयां.
उदाहरण के लिए, अगर आपको अपने कॉन्टेंट के ऊपर रेडियल ग्रेडिएंट रेंडर करना है, तो फिर, ये काम किए जा सकते हैं:
var pointerOffset by remember { mutableStateOf(Offset(0f, 0f)) } Column( modifier = Modifier .fillMaxSize() .pointerInput("dragging") { detectDragGestures { change, dragAmount -> pointerOffset += dragAmount } } .onSizeChanged { pointerOffset = Offset(it.width / 2f, it.height / 2f) } .drawWithContent { drawContent() // draws a fully black area with a small keyhole at pointerOffset that’ll show part of the UI. drawRect( Brush.radialGradient( listOf(Color.Transparent, Color.Black), center = pointerOffset, radius = 100.dp.toPx(), ) ) } ) { // Your composables here }
Modifier.drawBehind
: किसी कॉम्पोज़ेबल के पीछे ड्रॉ करना
Modifier.drawBehind
की मदद से,
स्क्रीन पर दिखाए गए कंपोज़ेबल कॉन्टेंट के पीछे DrawScope
कार्रवाइयां. Canvas
को लागू करने के तरीके को देखकर, आपको पता चल सकता है कि यह Modifier.drawBehind
के लिए सिर्फ़ एक सुविधाजनक रैपर है.
Text
के पीछे एक गोल आयत बनाने के लिए:
Text( "Hello Compose!", modifier = Modifier .drawBehind { drawRoundRect( Color(0xFFBBAAEE), cornerRadius = CornerRadius(10.dp.toPx()) ) } .padding(4.dp) )
इससे यह नतीजा मिलता है:
Modifier.drawWithCache
: ड्रॉ ऑब्जेक्ट ड्रॉइंग और कैश मेमोरी में सेव करना
Modifier.drawWithCache
ऑब्जेक्ट बनाए रखता है
जो इसके कैश मेमोरी में सेव होते हैं. ऑब्जेक्ट, साइज़ के हिसाब से कैश मेमोरी में सेव किए जाते हैं
समान या कोई भी स्टेट ऑब्जेक्ट जिन्हें पढ़ा गया है वे
बदल दिया गया है. यह मॉडिफ़ायर, कॉल ड्रॉइंग की परफ़ॉर्मेंस को बेहतर बनाने के लिए काम का है
यह ऑब्जेक्ट (जैसे: Brush, Shader, Path
वगैरह) को फिर से आवंटित करने की ज़रूरत से बचाता है.
जो ड्रॉ पर बनाए जाते हैं.
इसके अलावा, remember
का इस्तेमाल करके भी ऑब्जेक्ट को कैश मेमोरी में सेव किया जा सकता है. इसके लिए,
कार्रवाई बदलने वाली कुंजी. हालांकि, ऐसा हमेशा संभव नहीं होता, क्योंकि आपके पास हमेशा ऐक्सेस नहीं होता
संगीत वीडियो से जुड़े हों. drawWithCache
का इस्तेमाल करना ज़्यादा बेहतर हो सकता है, अगर
ऑब्जेक्ट का इस्तेमाल सिर्फ़ ड्रॉइंग के लिए किया जाता है.
उदाहरण के लिए, अगर आपने Text
के पीछे ग्रेडिएंट बनाने के लिए Brush
बनाया है, तो
drawWithCache
, Brush
ऑब्जेक्ट को ड्रॉइंग एरिया के साइज़ तक कैश मेमोरी में सेव करता है
बदलाव:
Text( "Hello Compose!", modifier = Modifier .drawWithCache { val brush = Brush.linearGradient( listOf( Color(0xFF9E82F0), Color(0xFF42A5F5) ) ) onDrawBehind { drawRoundRect( brush, cornerRadius = CornerRadius(10.dp.toPx()) ) } } )
ग्राफ़िक मॉडिफ़ायर
Modifier.graphicsLayer
: कॉम्पोज़ेबल पर ट्रांसफ़ॉर्मेशन लागू करना
Modifier.graphicsLayer
एक मॉडिफ़ायर है, जो कंपोज़ेबल ड्रॉ के कॉन्टेंट को ड्रॉ लेयर में बनाता है. ऐप्लिकेशन
लेयर में कुछ अलग-अलग फ़ंक्शन होते हैं, जैसे कि:
- ड्रॉइंग बनाने के निर्देशों के लिए आइसोलेशन (
RenderNode
से मिलता-जुलता). ड्रॉइंग लेयर के भाग के रूप में कैप्चर किए गए निर्देशों को, ऐप्लिकेशन कोड को फिर से लागू किए बिना रेंडर करने वाले पाइपलाइन को. - इसमें मौजूद सभी ड्रॉइंग के निर्देशों पर लागू होने वाले बदलाव लेयर.
- कंपोज़िशन की क्षमताओं के लिए रास्टराइज़ेशन. जब किसी लेयर को रास्टराइज़ किया जाता है, तो ड्रॉइंग के निर्देशों का पालन किया जाता है और आउटपुट को ऑफ़स्क्रीन में कैप्चर कर दिया जाता है बफ़र. अगले फ़्रेम के लिए इस तरह के बफ़र को कंपोज़िट करना, अलग-अलग निर्देशों को लागू करने से ज़्यादा तेज़ होता है. हालांकि, स्केलिंग या रोटेशन जैसे ट्रांसफ़ॉर्म लागू होने पर, यह बिटमैप की तरह काम करेगा.
ट्रांसफ़ॉर्मेशन
Modifier.graphicsLayer
, ड्रॉइंग के निर्देशों के लिए अलगाव की सुविधा देता है. उदाहरण के लिए, Modifier.graphicsLayer
का इस्तेमाल करके अलग-अलग ट्रांसफ़ॉर्मेशन लागू किए जा सकते हैं.
इनमें ऐनिमेशन जोड़ा जा सकता है या इनमें बदलाव किया जा सकता है. इसके लिए, ड्रॉइंग के लिए इस्तेमाल किए गए लैम्ब्डा फ़ंक्शन को फिर से लागू करने की ज़रूरत नहीं होती.
Modifier.graphicsLayer
, आपके वीडियो के मेज़र किए गए साइज़ या प्लेसमेंट में बदलाव नहीं करता
कंपोज़ेबल, क्योंकि यह सिर्फ़ ड्रॉ के चरण पर असर डालता है. इसका मतलब है कि आपको कंपोज़ेबल
दूसरों को ओवरलैप कर सकता है, अगर वह अपनी लेआउट की सीमाओं से बाहर आ जाता है.
इस मॉडिफ़ायर का इस्तेमाल करके, यहां दिए गए बदलाव लागू किए जा सकते हैं:
स्केल - साइज़ बढ़ाना
scaleX
और scaleY
, हॉरिज़ॉन्टल या वर्टिकल फ़ॉर्मैट में कॉन्टेंट को बड़ा या छोटा करते हैं
दिशा-निर्देश. 1.0f
की वैल्यू से पता चलता है कि स्केल में कोई बदलाव नहीं हुआ है. 0.5f
की वैल्यू का मतलब है कि डाइमेंशन आधा है.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.scaleX = 1.2f this.scaleY = 0.8f } )
अनुवाद
translationX
और translationY
को graphicsLayer
के साथ बदला जा सकता है,
translationX
, कंपोज़ेबल को बाईं या दाईं ओर ले जाता है. translationY
कम या ज़्यादा किया जा सकता है.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.translationX = 100.dp.toPx() this.translationY = 10.dp.toPx() } )
रोटेशन
क्षैतिज रूप से घुमाने के लिए rotationX
, लंबवत रूप से घुमाने के लिए rotationY
और
Z ऐक्सिस (स्टैंडर्ड रोटेशन) पर घुमाने के लिए, rotationZ
दबाएं. यह मान बताया गया है
डिग्री (0-360) में.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
Origin
कोई transformOrigin
तय किया जा सकता है. इसके बाद, उसका इस्तेमाल उस बिंदु के तौर पर किया जाता है जहां से
बदलाव होते रहते हैं. अब तक दिए गए सभी उदाहरणों
TransformOrigin.Center
, जो (0.5f, 0.5f)
पर है. अगर आपने (0f, 0f)
पर ऑरिजिन तय किया है, तो ट्रांसफ़ॉर्मेशन, कॉम्पोज़ेबल के सबसे ऊपर बाएं कोने से शुरू होते हैं.
अगर ऑरिजिन को rotationZ
ट्रांसफ़ॉर्मेशन से बदला जाता है, तो आपको दिखेगा कि
आइटम कंपोज़ेबल के ऊपर बाईं ओर घूमता है:
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.transformOrigin = TransformOrigin(0f, 0f) this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
क्लिप और आकार
आकार से उस आउटलाइन के बारे में पता चलता है जो clip = true
जब कॉन्टेंट क्लिप करता है. तय सीमा में
इस उदाहरण में, हम दो अलग-अलग क्लिप के लिए दो बॉक्स सेट करते हैं -
graphicsLayer
क्लिप वैरिएबल और दूसरा आसान रैपर का इस्तेमाल करके क्लिप
Modifier.clip
.
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .size(200.dp) .graphicsLayer { clip = true shape = CircleShape } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(CircleShape) .background(Color(0xFF4DB6AC)) ) }
पहले बॉक्स के कॉन्टेंट (“नमस्ते लिखें” टेक्स्ट) को वृत्त का आकार:
इसके बाद, अगर सबसे ऊपर दिए गए गुलाबी गोले के ऊपर translationY
लागू किया जाता है, तो आपको पता चलता है कि बाउंड
कंपोज़ेबल में मौजूद चीज़ें पहले जैसी ही हैं, लेकिन नीचे की ओर सर्कल बना है
सर्कल (और इसकी सीमाओं से बाहर) का इस्तेमाल करें.
कंपोज़ेबल को जिस हिस्से में बनाया गया है उस हिस्से में क्लिप बनाने के लिए, दूसरा जोड़ें
मॉडिफ़ायर चेन की शुरुआत में Modifier.clip(RectangleShape)
. कॉन्टेंट
फिर मूल सीमाओं के अंदर ही रहता है.
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .clip(RectangleShape) .size(200.dp) .border(2.dp, Color.Black) .graphicsLayer { clip = true shape = CircleShape translationY = 50.dp.toPx() } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(RoundedCornerShape(500.dp)) .background(Color(0xFF4DB6AC)) ) }
ऐल्फ़ा
Modifier.graphicsLayer
का इस्तेमाल, पूरी लेयर के लिए alpha
(अपारदर्शिता) सेट करने के लिए किया जा सकता है. 1.0f
पूरी तरह से ओपेक नहीं है और 0.0f
दिखाई नहीं दे रहा है.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "clock", modifier = Modifier .graphicsLayer { this.alpha = 0.5f } )
कंपोज़िटिंग स्ट्रेटजी
ऐल्फ़ा और पारदर्शिता के साथ काम करना इतना आसान नहीं है, जितना कि
ऐल्फ़ा वैल्यू. किसी अल्फा को बदलने के अलावा, graphicsLayer
पर CompositingStrategy
सेट करने का विकल्प भी होता है. CompositingStrategy
तय करता है कि
कंपोज़ेबल का कॉन्टेंट एक-दूसरे के साथ कंपोज़िट किया गया (एक साथ रखा गया)
जिसे पहले ही स्क्रीन पर बनाया जा चुका है.
ये अलग-अलग रणनीतियां हैं:
अपने-आप चालू और बंद (डिफ़ॉल्ट)
कंपोज़िटिंग की रणनीति, graphicsLayer
के बाकी सदस्यों से तय होती है
पैरामीटर का इस्तेमाल करें. अगर ऐल्फ़ा का साइज़ इससे कम है, तो यह लेयर को ऑफ़स्क्रीन बफ़र में रेंडर करता है
1.0f या RenderEffect
सेट है. जब अल्फ़ा 1f से कम हो, तो
कंपोज़िटिंग लेयर, कॉन्टेंट को रेंडर करने और फिर ड्रॉ करने के लिए अपने-आप बन जाती है
यह ऑफ़स्क्रीन बफ़र, संबंधित ऐल्फ़ा वाले डेस्टिनेशन के लिए है. सेट किया जा रहा है
RenderEffect
या ओवरस्क्रोल, कॉन्टेंट को हमेशा ऑफ़स्क्रीन में रेंडर करता है
बफ़र, CompositingStrategy
सेट पर ध्यान दिए बिना.
ऑफ़स्क्रीन
कंपोज़ेबल के कॉन्टेंट को हमेशा ऑफ़स्क्रीन में रास्टराइज़ किया जाता है
टेक्स्चर या बिटमैप का इस्तेमाल करें. यह कॉन्टेंट को मास्क करने के लिए, BlendMode
ऑपरेशन लागू करने के लिए और ड्रॉइंग के निर्देशों के जटिल सेट को रेंडर करते समय परफ़ॉर्मेंस के लिए मददगार है.
CompositingStrategy.Offscreen
का इस्तेमाल करने का एक उदाहरण, BlendModes
के साथ है. नीचे दिया गया उदाहरण देखें,
मान लें कि आपको किसी Image
कंपोज़ेबल के हिस्सों को हटाने के लिए, एक ड्रॉ निर्देश जारी करना है
BlendMode.Clear
का इस्तेमाल करता है. अगर आप compositingStrategy
को इस पर सेट नहीं करते हैं
CompositingStrategy.Offscreen
, BlendMode
सभी कॉन्टेंट के साथ इंटरैक्ट करता है
टैप करें.
Image(painter = painterResource(id = R.drawable.dog), contentDescription = "Dog", contentScale = ContentScale.Crop, modifier = Modifier .size(120.dp) .aspectRatio(1f) .background( Brush.linearGradient( listOf( Color(0xFFC5E1A5), Color(0xFF80DEEA) ) ) ) .padding(8.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .drawWithCache { val path = Path() path.addOval( Rect( topLeft = Offset.Zero, bottomRight = Offset(size.width, size.height) ) ) onDrawWithContent { clipPath(path) { // this draws the actual image - if you don't call drawContent, it wont // render anything this@onDrawWithContent.drawContent() } val dotSize = size.width / 8f // Clip a white border for the content drawCircle( Color.Black, radius = dotSize, center = Offset( x = size.width - dotSize, y = size.height - dotSize ), blendMode = BlendMode.Clear ) // draw the red circle indication drawCircle( Color(0xFFEF5350), radius = dotSize * 0.8f, center = Offset( x = size.width - dotSize, y = size.height - dotSize ) ) } } )
CompositingStrategy
को Offscreen
पर सेट करने पर, एक ऑफ़स्क्रीन बन जाती है
टेक्स्चर की मदद से, कमांड को एक्ज़ीक्यूट करें (सिर्फ़ BlendMode
को
कंपोज़ेबल का कॉन्टेंट). इसके बाद, यह उसे पहले से रेंडर किए गए हिस्से के ऊपर रेंडर करता है
जिसका असर पहले से बनाए गए कॉन्टेंट पर नहीं पड़ता.
अगर आपने CompositingStrategy.Offscreen
का इस्तेमाल नहीं किया, तो लागू करने के नतीजे
BlendMode.Clear
, डेस्टिनेशन में मौजूद सभी पिक्सल हटा देता है, भले ही वह कुछ भी हो
पहले से सेट था– यानी विंडो का रेंडरिंग बफ़र (काला) दिखता रहेगा. कई
जिसमें ऐल्फ़ा शामिल है, वह BlendModes
के बिना उम्मीद के मुताबिक काम नहीं करेगा
ऑफ़स्क्रीन बफ़र. लाल वृत्त संकेतक के चारों ओर काले रंग के गोले पर ध्यान दें:
इसे थोड़ा और समझने के लिए: अगर ऐप्लिकेशन में ट्रांसलूसंट विंडो होती है
इस्तेमाल नहीं किया है और आपने CompositingStrategy.Offscreen
का इस्तेमाल नहीं किया है,
BlendMode
पूरे ऐप्लिकेशन से इंटरैक्ट करेगा. इससे दिखाने के लिए सभी पिक्सल हट जाएंगे
के नीचे दिया गया है, जैसा कि इस उदाहरण में बताया गया है:
ध्यान रखें कि CompositingStrategy.Offscreen
का इस्तेमाल करते समय, एक ऑफ़स्क्रीन
टेक्सचर, जो ड्रॉइंग एरिया का साइज़ होता है उसे बनाया जाता है और उस पर वापस रेंडर किया जाता है
स्क्रीन. इस रणनीति का इस्तेमाल करके किए गए ड्रॉइंग निर्देश, डिफ़ॉल्ट रूप से इस क्षेत्र में क्लिप हो जाते हैं. नीचे दिए गए कोड स्निपेट में, ऑफ़स्क्रीन टेक्सचर का इस्तेमाल करने पर होने वाले बदलावों के बारे में बताया गया है:
@Composable fun CompositingStrategyExamples() { Column( modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) { /** Does not clip content even with a graphics layer usage here. By default, graphicsLayer does not allocate + rasterize content into a separate layer but instead is used for isolation. That is draw invalidations made outside of this graphicsLayer will not re-record the drawing instructions in this composable as they have not changed **/ Canvas( modifier = Modifier .graphicsLayer() .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { // ... and drawing a size of 200 dp here outside the bounds drawRect(color = Color.Magenta, size = Size(200.dp.toPx(), 200.dp.toPx())) } Spacer(modifier = Modifier.size(300.dp)) /** Clips content as alpha usage here creates an offscreen buffer to rasterize content into first then draws to the original destination **/ Canvas( modifier = Modifier // force to an offscreen buffer .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { /** ... and drawing a size of 200 dp. However, because of the CompositingStrategy.Offscreen usage above, the content gets clipped **/ drawRect(color = Color.Red, size = Size(200.dp.toPx(), 200.dp.toPx())) } } }
ModulateAlpha
यह कंपोज़िशन रणनीति हर ड्रॉइंग के लिए ऐल्फ़ा को मॉड्यूल करती है
graphicsLayer
में निर्देश रिकॉर्ड किए गए हैं. इससे,
जब तक RenderEffect
सेट नहीं होता, तब तक 1.0f से कम के ऐल्फ़ा के लिए ऑफ़स्क्रीन बफ़र, ताकि यह कर सके
ऐल्फ़ा रेंडरिंग के लिए बेहतर तरीके से काम करेगा. हालांकि, इसके लिए अलग-अलग नतीजे हो सकते हैं
ओवरलैप होने वाले कॉन्टेंट के लिए. ऐसे मामलों में जहां पहले से ही यह जानकारी उपलब्ध हो कि
ओवरलैप नहीं कर रहा है, तो वह इससे बेहतर प्रदर्शन प्रदान कर सकता है
1 से कम अल्फ़ा मान वाले CompositingStrategy.Auto
.
अलग-अलग कंपोज़िशन रणनीतियों का एक और उदाहरण नीचे दिया गया है - अलग-अलग
कंपोज़ेबल के अलग-अलग हिस्सों में ऐल्फ़ा और Modulate
लागू करना
रणनीति:
@Preview @Composable fun CompositingStratgey_ModulateAlpha() { Column( modifier = Modifier .fillMaxSize() .padding(32.dp) ) { // Base drawing, no alpha applied Canvas( modifier = Modifier.size(200.dp) ) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // Alpha 0.5f applied to whole composable Canvas(modifier = Modifier .size(200.dp) .graphicsLayer { alpha = 0.5f }) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // 0.75f alpha applied to each draw call when using ModulateAlpha Canvas(modifier = Modifier .size(200.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.ModulateAlpha alpha = 0.75f }) { drawSquares() } } } private fun DrawScope.drawSquares() { val size = Size(100.dp.toPx(), 100.dp.toPx()) drawRect(color = Red, size = size) drawRect( color = Purple, size = size, topLeft = Offset(size.width / 4f, size.height / 4f) ) drawRect( color = Yellow, size = size, topLeft = Offset(size.width / 4f * 2f, size.height / 4f * 2f) ) } val Purple = Color(0xFF7E57C2) val Yellow = Color(0xFFFFCA28) val Red = Color(0xFFEF5350)
किसी कंपोज़ेबल का कॉन्टेंट बिटमैप में लिखना
सामान्य इस्तेमाल का उदाहरण, किसी कंपोज़ेबल से Bitmap
बनाना है. कॉपी करने के लिए
किसी Bitmap
में आपके कंपोज़ेबल का कॉन्टेंट शामिल है. इसका इस्तेमाल करके GraphicsLayer
बनाएं
rememberGraphicsLayer()
.
drawWithContent()
का इस्तेमाल करके ड्रॉइंग कमांड को नई लेयर पर रीडायरेक्ट करें
graphicsLayer.record{}
. फिर इसका इस्तेमाल करके दिखाई देने वाले कैनवस में लेयर बनाएं
drawLayer
:
val coroutineScope = rememberCoroutineScope() val graphicsLayer = rememberGraphicsLayer() Box( modifier = Modifier .drawWithContent { // call record to capture the content in the graphics layer graphicsLayer.record { // draw the contents of the composable into the graphics layer this@drawWithContent.drawContent() } // draw the graphics layer on the visible canvas drawLayer(graphicsLayer) } .clickable { coroutineScope.launch { val bitmap = graphicsLayer.toImageBitmap() // do something with the newly acquired bitmap } } .background(Color.White) ) { Text("Hello Android", fontSize = 26.sp) }
बिटमैप को डिस्क में सेव करके शेयर किया जा सकता है. ज़्यादा जानकारी के लिए, पूरा उदाहरण के तौर पर दिया गया स्निपेट. डिस्क पर सेव करने की कोशिश करने से पहले, डिवाइस पर अनुमतियां देखना न भूलें.
कस्टम ड्रॉइंग मॉडिफ़ायर
अपना कस्टम मॉडिफ़ायर बनाने के लिए, DrawModifier
इंटरफ़ेस लागू करें. यह
आपको ContentDrawScope
का ऐक्सेस देता है, जो सार्वजनिक किए गए डेटा की तरह ही है
Modifier.drawWithContent()
का इस्तेमाल करते समय. इसके बाद, एक ही ड्रॉइंग को एक्सट्रैक्ट किया जा सकता है
कोड हटाने और उपलब्ध कराने के लिए कस्टम ड्रॉइंग मॉडिफ़ायर में कार्रवाइयों के विकल्प
सुविधाजनक रैपर; उदाहरण के लिए, Modifier.background()
DrawModifier
.
उदाहरण के लिए, अगर आपको ऐसा Modifier
लागू करना था जो वर्टिकल तरीके से फ़्लिप होता हो
सामग्री है, तो आप इस तरह से एक बना सकते हैं:
class FlippedModifier : DrawModifier { override fun ContentDrawScope.draw() { scale(1f, -1f) { this@draw.drawContent() } } } fun Modifier.flipped() = this.then(FlippedModifier())
फिर Text
पर लागू किए गए इस फ़्लिप किए गए मॉडिफ़ायर का इस्तेमाल करें:
Text( "Hello Compose!", modifier = Modifier .flipped() )
अन्य संसाधन
graphicsLayer
और कस्टम ड्रॉइंग का इस्तेमाल करने वाले ज़्यादा उदाहरणों के लिए, यहां देखें
इन संसाधनों की मदद से:
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक टेक्स्ट दिखता है
- Compose में ग्राफ़िक्स
- इमेज को पसंद के मुताबिक बनाना {:#customize-image}
- Jetpack Compose के लिए Kotlin