03 deepseek

 //deepseek

Here is a complete, single-file Android app built with Jetpack Compose. It displays a list of texts, and when you tap any text, a context menu pops up with options to copy, copy all, share, or translate the selected text.


```kotlin

package com.example.textcontextmenu


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 androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.compose.foundation.background

import androidx.compose.foundation.clickable

import androidx.compose.foundation.layout.*

import androidx.compose.foundation.lazy.LazyColumn

import androidx.compose.foundation.lazy.items

import androidx.compose.foundation.shape.RoundedCornerShape

import androidx.compose.material.icons.Icons

import androidx.compose.material.icons.filled.Close

import androidx.compose.material3.*

import androidx.compose.runtime.*

import androidx.compose.ui.Alignment

import androidx.compose.ui.Modifier

import androidx.compose.ui.draw.shadow

import androidx.compose.ui.geometry.Offset

import androidx.compose.ui.layout.onGloballyPositioned

import androidx.compose.ui.layout.positionInRoot

import androidx.compose.ui.platform.LocalClipboardManager

import androidx.compose.ui.platform.LocalContext

import androidx.compose.ui.unit.IntOffset

import androidx.compose.ui.unit.dp

import androidx.compose.ui.window.Popup

import androidx.compose.ui.window.PopupProperties

import java.net.URLEncoder


class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContent {

            MaterialTheme {

                TextContextMenuScreen()

            }

        }

    }

}


@OptIn(ExperimentalMaterial3Api::class)

@Composable

fun TextContextMenuScreen() {

    // Sample list of texts to display

    val sampleTexts = remember {

        listOf(

            TextItem(id = 1, content = "The only limit is your mind."),

            TextItem(id = 2, content = "Jetpack Compose makes UI development a joy."),

            TextItem(id = 3, content = "Kotlin is expressive and concise."),

            TextItem(id = 4, content = "Context menus provide quick actions."),

            TextItem(id = 5, content = "Copy, share, translate – all at your fingertips."),

            TextItem(id = 6, content = "Always keep learning new things.")

        )

    }


    // State to hold the currently selected text item and its anchor position

    var contextMenuState by remember { mutableStateOf<ContextMenuState?>(null) }


    // Map to store the screen coordinates of each text item (by id)

    val itemCoordinates = remember { mutableStateMapOf<Int, Offset>() }


    val clipboardManager = LocalClipboardManager.current

    val context = LocalContext.current


    // Helper function to copy a single text

    fun copyText(text: String) {

        clipboardManager.setText(AnnotatedString(text))

        android.widget.Toast.makeText(context, "Copied: $text", android.widget.Toast.LENGTH_SHORT).show()

    }


    // Helper function to copy all texts

    fun copyAllTexts() {

        val allText = sampleTexts.joinToString("\n") { it.content }

        clipboardManager.setText(AnnotatedString(allText))

        android.widget.Toast.makeText(context, "Copied all texts", android.widget.Toast.LENGTH_SHORT).show()

    }


    // Helper function to share a single text

    fun shareText(text: String) {

        val shareIntent = Intent(Intent.ACTION_SEND).apply {

            type = "text/plain"

            putExtra(Intent.EXTRA_TEXT, text)

        }

        context.startActivity(Intent.createChooser(shareIntent, "Share via"))

    }


    // Helper function to translate text using Google Translate (opens browser)

    fun translateText(text: String) {

        val encodedText = URLEncoder.encode(text, "UTF-8")

        val translateUrl = "https://translate.google.com/?text=$encodedText&sl=auto&tl=en"

        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(translateUrl))

        context.startActivity(intent)

    }


    Scaffold(

        topBar = {

            TopAppBar(

                title = { Text("Text Context Menu Demo") },

                colors = TopAppBarDefaults.mediumTopAppBarColors()

            )

        }

    ) { paddingValues ->

        Box(

            modifier = Modifier

                .fillMaxSize()

                .padding(paddingValues)

        ) {

            LazyColumn(

                modifier = Modifier.fillMaxSize(),

                contentPadding = PaddingValues(16.dp),

                verticalArrangement = Arrangement.spacedBy(12.dp)

            ) {

                items(sampleTexts, key = { it.id }) { item ->

                    // Each text item row

                    var itemPosition by remember { mutableStateOf(Offset.Zero) }


                    Card(

                        modifier = Modifier

                            .fillMaxWidth()

                            .onGloballyPositioned { coordinates ->

                                itemPosition = coordinates.positionInRoot()

                                // Update map with latest coordinates

                                itemCoordinates[item.id] = itemPosition

                            }

                            .clickable {

                                // Show context menu when item is tapped

                                val position = itemCoordinates[item.id] ?: itemPosition

                                contextMenuState = ContextMenuState(

                                    text = item.content,

                                    anchorPosition = position

                                )

                            },

                        shape = RoundedCornerShape(12.dp),

                        elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)

                    ) {

                        Text(

                            text = item.content,

                            modifier = Modifier

                                .fillMaxWidth()

                                .padding(16.dp),

                            style = MaterialTheme.typography.bodyLarge

                        )

                    }

                }

            }


            // Context Menu Popup

            contextMenuState?.let { state ->

                Popup(

                    alignment = Alignment.TopStart,

                    offset = IntOffset(state.anchorPosition.x.toInt(), state.anchorPosition.y.toInt() + 20), // slight vertical offset

                    onDismissRequest = { contextMenuState = null },

                    properties = PopupProperties(focusable = true)

                ) {

                    ContextMenuContent(

                        text = state.text,

                        onCopy = {

                            copyText(state.text)

                            contextMenuState = null

                        },

                        onCopyAll = {

                            copyAllTexts()

                            contextMenuState = null

                        },

                        onShare = {

                            shareText(state.text)

                            contextMenuState = null

                        },

                        onTranslate = {

                            translateText(state.text)

                            contextMenuState = null

                        },

                        onDismiss = { contextMenuState = null }

                    )

                }

            }

        }

    }

}


@Composable

fun ContextMenuContent(

    text: String,

    onCopy: () -> Unit,

    onCopyAll: () -> Unit,

    onShare: () -> Unit,

    onTranslate: () -> Unit,

    onDismiss: () -> Unit

) {

    Card(

        modifier = Modifier

            .width(200.dp)

            .shadow(8.dp, shape = RoundedCornerShape(8.dp)),

        shape = RoundedCornerShape(8.dp),

        colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)

    ) {

        Column(

            modifier = Modifier.padding(8.dp)

        ) {

            // Optional: show the selected text preview

            Text(

                text = text.take(50) + if (text.length > 50) "..." else "",

                style = MaterialTheme.typography.labelMedium,

                color = MaterialTheme.colorScheme.onSurfaceVariant,

                modifier = Modifier.padding(bottom = 8.dp)

            )

            Divider(modifier = Modifier.padding(vertical = 4.dp))

            

            // Action Items

            ContextMenuItem(

                text = "Copy",

                onClick = onCopy

            )

            ContextMenuItem(

                text = "Copy All",

                onClick = onCopyAll

            )

            ContextMenuItem(

                text = "Share",

                onClick = onShare

            )

            ContextMenuItem(

                text = "Translate",

                onClick = onTranslate

            )

            Divider(modifier = Modifier.padding(vertical = 4.dp))

            ContextMenuItem(

                text = "Cancel",

                onClick = onDismiss,

                isDestructive = false

            )

        }

    }

}


@Composable

fun ContextMenuItem(

    text: String,

    onClick: () -> Unit,

    isDestructive: Boolean = false

) {

    TextButton(

        onClick = onClick,

        modifier = Modifier.fillMaxWidth(),

        colors = ButtonDefaults.textButtonColors(

            contentColor = if (isDestructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary

        )

    ) {

        Text(

            text = text,

            modifier = Modifier.padding(vertical = 8.dp),

            style = MaterialTheme.typography.bodyMedium

        )

    }

}


// Data class to hold the selected text and its anchor position

data class ContextMenuState(

    val text: String,

    val anchorPosition: Offset

)


// Data class for each text item in the list

data class TextItem(

    val id: Int,

    val content: String

)

```


How the App Works

1. Display Texts – A scrollable list of sample quotes or messages is shown using a LazyColumn.

2. Select a Text – Tapping any text card records its position on the screen and opens a popup context menu.

3. Context Menu Options:

   · Copy – Copies the selected text to the clipboard.

   · Copy All – Copies every text in the list (separated by newlines) to the clipboard.

   · Share – Opens the Android share sheet with the selected text.

   · Translate – Opens Google Translate in a browser with the selected text pre-filled.

   · Cancel – Closes the menu without taking action.

4. Visual Feedback – Toast messages confirm copy actions, and the menu closes automatically after any action.


Key Implementation Details


· The popup is anchored to the exact location of the tapped text item using onGloballyPositioned and positionInRoot().

· All text operations use standard Android APIs: ClipboardManager for copy, Intent.ACTION_SEND for sharing, and an Intent.ACTION_VIEW to Google Translate.

· The UI follows Material 3 guidelines with cards, elevation, and a clean top app bar.