RaTeX
July 28, 2026 · View on GitHub
Native LaTeX math on Android (Kotlin + Canvas). AAR includes KaTeX fonts. minSdk 21, targetSdk 34.
Out of the box
- Add dependency — In your app's
build.gradle:implementation("io.github.erweixin:ratex-android:0.1.14") - Use — Add
RaTeXViewin your layout and set LaTeX in code; fonts load automatically on first render.
Optional: To preload fonts at startup, callbinding.mathView.latex = """\frac{-b \pm \sqrt{b^2-4ac}}{2a}""" binding.mathView.fontSize = 24f // dp — no manual density conversion neededRaTeXFontLoader.loadFromAssets(context, "fonts")in yourApplicationor first screen.
Local development (building from source)
Prerequisites: NDK 26+, Rust + cargo install cargo-ndk, and targets:
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
Build from repo root:
bash platforms/android/build-android.sh
# → src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86_64}/libratex_ffi.so
Include as a local module in settings.gradle:
include(":ratex-android")
project(":ratex-android").projectDir = file("path/to/RaTeX/platforms/android")
Then in your app: implementation(project(":ratex-android")).
Usage
Block formula — RaTeXView
<io.ratex.RaTeXView android:id="@+id/mathView"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
binding.mathView.latex = """\frac{-b \pm \sqrt{b^2-4ac}}{2a}"""
binding.mathView.fontSize = 24f // dp — no manual density conversion needed
binding.mathView.displayMode = true // true = display/block (default); false = inline/text
binding.mathView.color = android.graphics.Color.parseColor("#1E88E5")
Inline formula — RaTeXSpan
RaTeXSpan is a ReplacementSpan that renders a LaTeX formula inline with surrounding text, baseline-aligned, with line height expanding automatically.
Rendering is async. Call RaTeXSpan.create from a coroutine:
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
fun showInlineFormula(textView: TextView) {
scope.launch {
val span = RaTeXSpan.create(
context = this@MainActivity,
latex = """\frac{1+\sqrt{5}}{2}""",
fontSize = 18f // dp
)
val ssb = SpannableStringBuilder("黄金比例 φ = ")
val start = ssb.length
ssb.append("\u200B")
ssb.setSpan(span, start, ssb.length, 0)
ssb.append(" ≈ 1.618")
textView.text = ssb
}
}
| Parameter | Type | Description |
|---|---|---|
context | Context | Used for asset access during font loading. |
latex | String | LaTeX math-mode string (no surrounding $ or \[…\]). |
fontSize | Float | Font size in dp. Converted to px internally. |
Throws RaTeXException if the formula cannot be parsed.
Low-level (Compose / custom drawing)
import android.graphics.Color
// display mode (default)
val dl = RaTeXEngine.parse(latex)
// inline mode
val dl = RaTeXEngine.parse(latex, displayMode = false)
// custom default color
val blueDl = RaTeXEngine.parse(latex, color = Color.parseColor("#1E88E5"))
val renderer = RaTeXRenderer(dl, fontSize) { RaTeXFontLoader.getTypeface(it) }
renderer.draw(canvas)
Explicit LaTeX colors such as \color{...} still take precedence over the default color.
Demo
From repo root: bash platforms/android/build-android.sh, then open demo/android in Android Studio and run.
Troubleshooting: UnsatisfiedLinkError → run build-android.sh. NDK not found → install NDK 26+ or set ANDROID_NDK_HOME.
Publishing (maintainers)
- Local:
./gradlew :ratex-android:publishReleasePublicationToMavenLocal - Maven Central: configure central.sonatype.com + GPG, set
SONATYPE_NEXUS_USERNAME/SONATYPE_NEXUS_PASSWORD/GPG_PRIVATE_KEY/GPG_PASSPHRASEin gradle.properties. - CI: push tag
v{VERSION}→.github/workflows/release-android.ymlpublishes to Central automatically.