//copilot
// MainActivity.kt
package com.example.contextmenudemo
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material3.Divider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import java.net.URLEncoder
class MainActivity : ComponentActivity() {
private val sampleTexts = listOf(
"Hello, world!",
"Jetpack Compose makes UI simple.",
"Kotlin is concise and expressive.",
"Long-press any item to open the context menu.",
"This demo shows Copy, Copy All, Share, Translate."
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
TextListScreen(items = sampleTexts)
}
}
}
}
}
@Composable
fun TextListScreen(items: List<String>) {
val context = LocalContext.current
var expandedIndex by remember { mutableStateOf<Int?>(null) } // which item's menu is open
var anchorText by remember { mutableStateOf("") } // selected text for actions
Column(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
.padding(12.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start
) {
Text(
text = "Selectable Texts",
style = MaterialTheme.typography.h6.copy(fontWeight = FontWeight.Bold),
modifier = Modifier.padding(bottom = 8.dp)
)
LazyColumn(
contentPadding = PaddingValues(vertical = 4.dp)
) {
itemsIndexed(items) { index, item ->
Box(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 6.dp)
) {
// Each text item listens for long-press to open the context menu
Box(
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colors.surface)
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
anchorText = item
expandedIndex = index
},
onTap = {
// optional: short tap behavior
Toast
.makeText(context, "Tapped: ${item}", Toast.LENGTH_SHORT)
.show()
}
)
}
.padding(14.dp)
) {
Text(text = item, style = MaterialTheme.typography.body1)
}
// Dropdown menu anchored to this Box (appears below the item)
DropdownMenu(
expanded = expandedIndex == index,
onDismissRequest = { expandedIndex = null },
modifier = Modifier
) {
DropdownMenuItem(onClick = {
copyToClipboard(context, anchorText)
Toast.makeText(context, "Copied", Toast.LENGTH_SHORT).show()
expandedIndex = null
}) {
Text("Copy")
}
DropdownMenuItem(onClick = {
val all = items.joinToString(separator = "\n")
copyToClipboard(context, all)
Toast.makeText(context, "All texts copied", Toast.LENGTH_SHORT).show()
expandedIndex = null
}) {
Text("Copy All")
}
DropdownMenuItem(onClick = {
shareText(context, anchorText)
expandedIndex = null
}) {
Text("Share")
}
DropdownMenuItem(onClick = {
openTranslate(context, anchorText)
expandedIndex = null
}) {
Text("Translate")
}
}
}
Divider(modifier = Modifier.padding(top = 6.dp, bottom = 6.dp))
}
}
}
}
/** Helpers **/
private fun copyToClipboard(context: Context, text: String) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("copied_text", text)
clipboard.setPrimaryClip(clip)
}
private fun shareText(context: Context, text: String) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, "Share text")
// If called from non-Activity context, need FLAG_ACTIVITY_NEW_TASK
if (context !is ComponentActivity) {
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(shareIntent)
}
private fun openTranslate(context: Context, text: String) {
try {
val encoded = URLEncoder.encode(text, "UTF-8")
// Open Google Translate web with the text prefilled. This will let user pick target language.
val url = "https://translate.google.com/?sl=auto&tl=&text=$encoded&op=translate"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
// If called from non-Activity context, need FLAG_ACTIVITY_NEW_TASK
if (context !is ComponentActivity) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
} catch (e: Exception) {
Toast.makeText(context, "Unable to open translator", Toast.LENGTH_SHORT).show()
}
}