Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tutosrive/mcbfc/llms.txt

Use this file to discover all available pages before exploring further.

The copy button in MCBFC is wired entirely inside BlockCodeEntry.Holder.init using the standard Android ClipboardManager API. No third-party libraries are required — everything needed is available in the Android framework from API level 11 onward. The click listener is registered once when the Holder is constructed and reused across every code block the holder is recycled into.

The copy flow

1

The click listener fires

btnCopy.setOnClickListener is invoked when the user taps the copy ImageButton. The lambda receives the clicked View as v, though it is not used directly in this implementation.
2

Retrieve the rendered code text

commandText.text.trim() reads the current CharSequence from the TextView and strips any leading or trailing whitespace added by Markwon’s span rendering. Because the read happens at click time — not at bind time — the correct code is always captured even when the holder has been recycled and rebound to a different FencedCodeBlock.
3

Obtain the system clipboard

val clipBoard = ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
Context.getSystemService returns the system-level ClipboardManager for the app’s process. The cast is safe because CLIPBOARD_SERVICE always returns a ClipboardManager on Android.
4

Wrap the text in a ClipData

val textClip = ClipData.newPlainText("Command", text)
ClipData.newPlainText creates a single-item clip with the label "Command" and the code text as its plain-text payload. The label is shown by some system clipboard UIs (e.g. the clipboard history drawer on Samsung One UI) to help users identify the clip.
5

Write to the clipboard

clipBoard.setPrimaryClip(textClip)
setPrimaryClip replaces whatever was previously on the clipboard with the new ClipData. On Android 13 (API 33) and above the system automatically shows a confirmation chip near the navigation bar, so you may choose to suppress the Toast on those versions.
6

Show a confirmation Toast

Toast.makeText(
    ctx,
    "Code copied to clipboard! ${text.subSequence(1..7)} ...",
    Toast.LENGTH_LONG
).show()
A Toast is shown with a short preview of the copied text — the characters at indices 1–7 — so the user can verify that the right block was copied without opening another app.

The button in the layout

The ImageButton is declared directly inside the root FrameLayout of fenced_code_view.xml, layered above the HorizontalScrollView using elevation:
fenced_code_view.xml
<ImageButton
    android:id="@+id/copyCommand"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end"
    android:background="@android:drawable/alert_dark_frame"
    android:elevation="18dp"
    android:src="?attr/actionModeCopyDrawable" />
Key attributes:
  • android:src="?attr/actionModeCopyDrawable" — references the system’s built-in copy action icon, so the button automatically adapts to the active theme (light, dark, or dynamic colour) without bundling any drawable resources.
  • android:elevation="18dp" — places the button above the HorizontalScrollView (elevation 8dp) and the TextView (elevation -1dp), ensuring it remains tappable and fully visible even when code text extends into the button’s area.
  • android:layout_gravity="end" — pins the button to the top-right (end) corner of the FrameLayout, following the layout direction of the device locale.

The click listener code

The full init block from BlockCodeEntry.Holder that wires the click listener:
BlockCodeEntry.kt
init {
    btnCopy.setOnClickListener { v ->
        val text = commandText.text.trim()
        val clipBoard = ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
        val textClip = ClipData.newPlainText("Command", text)
        clipBoard.setPrimaryClip(textClip)
        Toast.makeText(
            ctx,
            "Code copied to clipboard! ${text.subSequence(1..7)} ...",
            Toast.LENGTH_LONG
        ).show()
    }
}
text.subSequence(1..7) will throw an IndexOutOfBoundsException if the copied text is shorter than 8 characters — for example, a one-line code block containing only ls or cd. Guard against this in production by replacing text.subSequence(1..7) with text.take(7), which safely returns however many characters are available without throwing.

Customization tips

  • Branded icon — replace ?attr/actionModeCopyDrawable with your own vector drawable resource (e.g. @drawable/ic_copy) to display a custom icon that matches your app’s design language.
  • Snackbar instead of Toast — swap the Toast for a Snackbar on the parent CoordinatorLayout. A Snackbar supports an Undo action, which you can use to offer re-copy or navigation to the clipboard history.
  • Suppress the Toast on Android 13+ — from API 33 the system shows its own clipboard confirmation UI. Check Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU and skip the Toast to avoid a double confirmation.
  • Adjust z-ordering — if you add additional overlapping views (a language label badge, a line-count chip, etc.), tune android:elevation on each view to control which surfaces appear on top.
  • Longer preview — the text.take(7) preview can be extended to any length, or removed entirely if you prefer a plain “Copied!” message.

Build docs developers (and LLMs) love