Source code syntax highlighting on Android — Taking full control
Android and it’s community has evolved a lot over past decade. Now a days we can find open-source libraries to do almost anything — Zoomable ImageView, CameraX, RecyclerView Sticky Header, Tooltip, and many more.
Syntax highlighting is one of them and there are few libraries for that too. If this is a solved problem, then why am I writing about another solution then?
Well, some of the libraries I have explored are outdated, and some of them might not be as feature rich. So, I wanted to explore how to do-it-myself and write about it so that anybody can take full advantage of well-know JavaScript libraries for syntax highlighting in their Android app.
👍 Pros
- Complete control over how JS plugin is used in the app
- Complete control over the Android code that renders it using WebView
👎 Cons
- You need to have some understanding of web technologies, namely HTML, CSS and JavaScript
- You need to build your own Android CustomView or Fragment to render highlighted syntax. (No worries — this is where this article comes in to help you do that _🤗)_
With the pros and cons in mind, lets explore some well-established and proven syntax highlighting libraries
- PrismJS — Very light weight 2KB-100+KB with extensive plugin collection “Lightweight, robust, elegant syntax highlighting.”
- highlight.js — Fully loaded 25KB-100KB and simple syntax highlighting “Syntax highlighting for the Web”
- Rainbow — Another popular lightweight 6KB-25KB highlighter “Rainbow is a code syntax highlighting library written in Javascript.”
There are many more libraries that does the job, however for rest of the example I will be using PrismJS because of it’s highly modular nature. Note that, the process of using different library will be almost the same.
💡 TIP: All the example code provided here is available in great detail in the GitHub repository mentioned below👇.
Setting up PrismJS Template
We will be leveraging Android’sWebView to load syntax highlighting library with the source code that we want to be highlighted.
This setup is going to be specific to library of your choice. Since we are focusing on PrimsJS, we will follow it’s official guideline.
After you download the library JS and CSS file, you essentially need following HTML to render the highlighted source.
<!DOCTYPE html>
<html>
<head>
<link href="themes/prism.css" rel="stylesheet" />
<script src="prism.js"></script>
</head>
<body>
<pre><code class="language-kotlin">
data class Student(val name: String)
</code></pre>
</body>
</html>
TIP: You can download different CSS theme, and you can choose list of language and plugin you want to support (eg. Kotlin, Show line number)
Put the downloaded files in your Android app’s assets directory, ideally in www subfolder, like — src/main/assets/www/
Now that we have a baseline for the template, next part is to convert it to Kotlin function that can take additional parameter to customize different plugin options. Here is template with some additional data needed for mobile.
fun prismJsHtmlContent (
formattedSourceCode: String,
language: String,
showLineNumbers: Boolean = true
): String {
return """<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="www/prism.css" rel="stylesheet"/>
<script src="www/prism.js"></script>
</head>
<body>
<pre class="${if ( showLineNumbers ) "line-numbers" else ""}">
<code class="language-${language}">${formattedSourceCode}</code>
</pre>
</body>
</html>
"""
}
Defining Syntax Highlighting Custom-View
Making your own custom view is a great way to enhance capabilities. In this case we want to make our custom-view extend from WebView
so that we can load the template we just defined with source code at runtime.
package your.app.code
class SyntaxHighlighterWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : WebView (context, attrs, defStyleAttr) {
companion object {
private const val ANDROID_ASSETS_PATH = "file:///android_asset/"
}
// Our exposed function to show highlighted syntax
fun bindSyntaxHighlighter (
formattedSourceCode: String,
language: String,
showLineNumbers: Boolean = false
) {
settings.javaScriptEnabled = true
loadDataWithBaseURL(
ANDROID_ASSETS_PATH /* baseUrl */,
prismJsHtmlContent (
formattedSourceCode,
language,
showLineNumbers
) /* html-data */,
"text/html" /* mimeType */,
"utf-8" /* encoding */,
"" /* failUrl */
)
}
}
Using the Custom-View in App
Now that we have our SyntaxHighlighterWebView
custom-view with bindSyntaxHighlighter()
function, we can use it from Activity or Fragment layout.
All we need to do is use the view in XML layout like following:
<your.app.code.SyntaxHighlighterWebView
android:id="@+id/syntax_highlighter_webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
And from your Activity or Fragment get reference to the view and bind the source code like following
val highlighter: SyntaxHighlighterWebView = findViewById(R.id.syntax_highlighter_webview)
highlighter.bindSyntaxHighlighter(
formattedSourceCode = "data class Student(val name: String)",
language = "kotlin",
showLineNumbers = true
)
That’s it, once you load the app you should see highlighted syntax on the screen where you have put the custom-view.
All the example source code provided here is available in following GitHub repository. As bonus, I have also provided example of how to use highlight.js too.
If you find any issue, leave a comment here or report an issue at GitHub repository. Hope it helps somebody. ✌️
Top comments (0)