Skip to content

Commit 6c9df97

Browse files
feat: adds new snippet region tag for Desktop Windowing (#834)
* feat: adds new snippet region tag for DesktopWindowing * Apply Spotless * feat: adds drag and drop snippets for DesktopWindowing * Adds `DragAndDropSource` snippet region * Adds `DragAndDropTarget` snippet region * Apply Spotless * feat: adds transparent caption bar snippet for DesktopWindowing * Adds `TransparentActionBar` snippet region to demonstrate configuring transparent caption bar backgrounds via `WindowInsetsController`. * refactor: update desktop windowing snippets * Wrap transparent action bar logic in `TransparentActionBarActivity` * Convert drag-and-drop source and target extension functions to standard functions --------- Co-authored-by: prateekbatra-g <237188927+prateekbatra-g@users.noreply.github.com>
1 parent 0e26519 commit 6c9df97

1 file changed

Lines changed: 163 additions & 0 deletions

File tree

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright 2026 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.snippets.adaptivelayouts
18+
19+
import android.app.Activity
20+
import android.app.PendingIntent
21+
import android.content.ClipData
22+
import android.content.ClipDescription
23+
import android.content.Intent
24+
import android.os.Bundle
25+
import android.view.View
26+
import android.view.WindowInsetsController
27+
import androidx.compose.foundation.background
28+
import androidx.compose.foundation.draganddrop.dragAndDropSource
29+
import androidx.compose.foundation.draganddrop.dragAndDropTarget
30+
import androidx.compose.foundation.isSystemInDarkTheme
31+
import androidx.compose.foundation.layout.Arrangement
32+
import androidx.compose.foundation.layout.ExperimentalLayoutApi
33+
import androidx.compose.foundation.layout.Row
34+
import androidx.compose.foundation.layout.WindowInsets
35+
import androidx.compose.foundation.layout.captionBar
36+
import androidx.compose.foundation.layout.fillMaxWidth
37+
import androidx.compose.foundation.layout.isCaptionBarVisible
38+
import androidx.compose.foundation.layout.padding
39+
import androidx.compose.foundation.layout.windowInsetsTopHeight
40+
import androidx.compose.material3.MaterialTheme
41+
import androidx.compose.material3.Text
42+
import androidx.compose.runtime.Composable
43+
import androidx.compose.ui.Alignment
44+
import androidx.compose.ui.Modifier
45+
import androidx.compose.ui.draganddrop.DragAndDropEvent
46+
import androidx.compose.ui.draganddrop.DragAndDropTarget
47+
import androidx.compose.ui.draganddrop.DragAndDropTransferData
48+
import androidx.compose.ui.draganddrop.toAndroidDragEvent
49+
import androidx.compose.ui.graphics.Color
50+
import androidx.compose.ui.unit.dp
51+
import androidx.core.app.ActivityCompat.requestDragAndDropPermissions
52+
53+
/**
54+
* A custom Title Bar that respects the system caption bar insets.
55+
*/
56+
// [START android_compose_desktop_window_insets_title]
57+
@OptIn(ExperimentalLayoutApi::class)
58+
@Composable
59+
fun CaptionBar() {
60+
if (WindowInsets.isCaptionBarVisible) {
61+
Row(
62+
modifier = Modifier
63+
.windowInsetsTopHeight(WindowInsets.captionBar)
64+
.fillMaxWidth()
65+
.background(if (isSystemInDarkTheme()) Color.White else Color.Black),
66+
horizontalArrangement = Arrangement.Center,
67+
verticalAlignment = Alignment.CenterVertically
68+
) {
69+
Text(
70+
text = "Caption Bar Title",
71+
style = MaterialTheme.typography.titleMedium,
72+
modifier = Modifier.padding(4.dp)
73+
)
74+
}
75+
}
76+
}
77+
// [END android_compose_desktop_window_insets_title]
78+
79+
/**
80+
* Transparent System Caption Bar
81+
*/
82+
class TransparentActionBarActivity : Activity() {
83+
override fun onCreate(savedInstanceState: Bundle?) {
84+
super.onCreate(savedInstanceState)
85+
// [START android_compose_desktop_window_transparent_caption]
86+
window.insetsController?.setSystemBarsAppearance(
87+
WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND,
88+
WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND
89+
)
90+
// [END android_compose_desktop_window_transparent_caption]
91+
}
92+
}
93+
94+
95+
/**
96+
* Simple drag source for plain text data.
97+
*/
98+
fun dragAndDropSourceModifier() {
99+
// [START android_compose_desktop_drag_drop_source]
100+
Modifier.dragAndDropSource { _ ->
101+
DragAndDropTransferData(
102+
clipData = ClipData.newPlainText("label", "Your data"),
103+
flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION
104+
)
105+
}
106+
// [END android_compose_desktop_drag_drop_source]
107+
}
108+
109+
/**
110+
* Custom drag source that launches a new Activity instance when dropped.
111+
*/
112+
fun customDragAndDropSource(activity: Activity, itemId: String) {
113+
// [START android_compose_desktop_drag_drop_source_unhandled_flag]
114+
Modifier.dragAndDropSource { _ ->
115+
val intent = Intent.makeMainActivity(activity.componentName).apply {
116+
putExtra("EXTRA_ITEM_ID", itemId)
117+
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
118+
Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
119+
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
120+
}
121+
122+
val pendingIntent = PendingIntent.getActivity(
123+
activity, 0, intent, PendingIntent.FLAG_IMMUTABLE
124+
)
125+
126+
val data = ClipData(
127+
"Item $itemId",
128+
arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT),
129+
ClipData.Item.Builder().setIntentSender(pendingIntent.intentSender).build()
130+
)
131+
132+
DragAndDropTransferData(
133+
clipData = data,
134+
flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION or
135+
View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
136+
)
137+
}
138+
// [END android_compose_desktop_drag_drop_source_unhandled_flag]
139+
}
140+
141+
/**
142+
* A target modifier configured to receive plain text drag events.
143+
*/
144+
fun dragAndDropTargetModifier(activity: Activity) {
145+
// [START android_compose_desktop_drag_drop_target]
146+
Modifier.dragAndDropTarget(
147+
shouldStartDragAndDrop = { event ->
148+
event.toAndroidDragEvent().clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)
149+
},
150+
target = object : DragAndDropTarget {
151+
override fun onDrop(event: DragAndDropEvent): Boolean {
152+
requestDragAndDropPermissions(activity, event.toAndroidDragEvent())
153+
val clipData = event.toAndroidDragEvent().clipData
154+
val item = clipData?.getItemAt(0)?.text
155+
if (item != null) {
156+
// Process the dropped text item here
157+
}
158+
return item != null
159+
}
160+
}
161+
)
162+
// [END android_compose_desktop_drag_drop_target]
163+
}

0 commit comments

Comments
 (0)