Description
Squircle IDE currently supports coding in the following programming languages: ActionScript, C, C++, C#, Groovy, HTML, Java, JavaScript, Json, Julia, Kotlin, Lisp, Lua, Markdown, PHP, Python, Ruby, Shell, SQL, TypeScript, Visual Basic, XML and YAML.
Squircle IDE alternatives and similar packages
Based on the "TextView/EditText Widget" category.
Alternatively, view Squircle-CE alternatives based on common mentions on social networks and blogs.
-
ExpandableTextView
Android's TextView that can expand/collapse like the Google Play's app description -
android-autofittextview
A TextView that automatically resizes text to fit perfectly within its bounds. -
android-edittext-validator
Android form edit text is an extension of EditText that brings data validation facilities to the edittext. -
AutoLinkTextView
AutoLinkTextView is TextView that supports Hashtags (#), Mentions (@) , URLs (http://), Phone and Email automatically detecting and ability to handle clicks. -
Android-RobotoTextView
Implementation of a TextView and all its direct/indirect subclasses with native support for the Roboto fonts, includes the brand new Roboto Slab fonts. -
WaitingDots
Small library that provides... bouncing dots. This feature is used in number of messaging apps (such as Hangouts or Messenger), and lately in Android TV (for example when connecting to Wifi). -
SecretTextView
A TextView that simulates the effect from the app Secret where the characters fade in/out at different speeds. -
AwesomeText
A tool that facilitates working with Spans on TextViews or any extension of them (EditTexts, Buttons...). -
Masked-Edittext
Android library contain custom realisation of EditText component for masking and formatting input text -
chips-edittext-library
Chips EditText, Token EditText, Bubble EditText, Spannable EditText and etc.. There are many names of this control. Here I develop easy to understand , modify and integrate Chips Edit Text widget for Android -
AnimatedEditText
Androids EditText that animates the typed text. EditText is extended to create AnimatedEditText and a PinEntryEditText. -
EmailAutoCompleteTextView
An AutoCompleteTextView with builtin Adapter with the emails in the device. -
CurrencyEditText
A module designed to encapsulate the use of an Android EditText field for gathering currency information from a user. Supports all ISO-3166 compliant locales/currencies. -
AutosizeEditText
AutosizeEditText for Android is an extension of native EditText that offer a smooth auto scale text size. -
Android-SingleInputForm
A single EditText instead of a classical form. Library that implements flavienlaurent's singleinputform -
anytextview
An extension of Android's TextView, EditText and Button that let's you use the font of your choice -
android-formidable-validation
Form validation and feedback library for Android. Provides .setText for more than just TextView and EditText widgets. Provides easy means to validate with dependencies. -
MaskFormatter
Add text masking functionality to Android EditText. It will prevent user from inserting not allowed signs, and format input as well. -
KerningViews
Provides a set of views which allows to adjust the spacing between the characters of that view, AKA, Kerning effect.
CodeRabbit: AI Code Reviews for Developers
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of Squircle IDE or a related project?
README
Squircle CE
Squircle CE is a fast and free multi-language code editor for Android.
Table of Contents
EditorKit
- Gradle Dependency
- The Basics
- More Options
- Code Suggestions
- Undo Redo
- Navigation
- Theming
- Custom Plugin
Languages
EditorKit
The editorkit
module provides code editor without any support for
programming languages.
If you are upgrading from any older version, please have a look at
the [migration guide](MIGRATION-GUIDE.md).
Please note that this library only supports Kotlin.
Gradle Dependency
Add this to your module's build.gradle
file:
dependencies {
...
implementation 'com.blacksquircle.ui:editorkit:2.2.0'
}
The editorkit
module does not provide support for syntax
highlighting, you need to add specific language dependency. You can see
list of available languages here.
The Basics
First, you need to add TextProcessor
in your layout:
<com.blacksquircle.ui.editorkit.widget.TextProcessor
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top|start"
android:id="@+id/editor" />
Second, you need to provide a Language
object to support syntax
highlighting by using following code:
val editor = findViewById<TextProcessor>(R.id.editor)
editor.language = JavaScriptLanguage() // or any other language you want
Third, you need to call setTextContent
to set the text. Don't
use the default setText
method.
editor.setTextContent("your code here")
Also you might want to use setTextContent(PrecomputedTextCompat)
if
you're working with large text files.
Finally, after you set the text you need to clear undo/redo history because you don't want to keep the change history of previous file:
import com.blacksquircle.ui.editorkit.model.UndoStack
editor.undoStack = UndoStack()
editor.redoStack = UndoStack()
Now you can begin using the code editor.
More Options
Configuration
You can change the default code editor behavior by using Plugin DSL as shown below:
val pluginSupplier = PluginSupplier.create {
pinchZoom { // whether the zoom gesture enabled
minTextSize = 10f
maxTextSize = 20f
}
lineNumbers {
lineNumbers = true // line numbers visibility
highlightCurrentLine = true // whether the current line will be highlighted
}
highlightDelimiters() // highlight open/closed brackets beside the cursor
autoIndentation {
autoIndentLines = true // whether the auto indentation enabled
autoCloseBrackets = true // automatically close open parenthesis/bracket/brace
autoCloseQuotes = true // automatically close single/double quote when typing
}
}
editor.plugins(pluginSupplier)
To enable/disable plugins in runtime, surround necessary methods with
if (enabled) { ... }
operator:
val pluginSupplier = PluginSupplier.create {
if (preferences.isLineNumbersEnabled) {
lineNumbers()
}
if (preferences.isPinchZoomEnabled) {
pinchZoom()
}
// ...
}
editor.plugins(pluginSupplier)
Remember: everytime you call editor.plugins(pluginSupplier)
it
compares current plugin list with the new one, and then detaches plugins
that doesn't exists in the PluginSupplier
.
Text Scroller
To attach the text scroller you need to add TextScroller
in layout:
<com.blacksquircle.ui.editorkit.widget.TextScroller
android:layout_width="30dp"
android:layout_height="match_parent"
android:id="@+id/scroller"
app:thumbNormal="@drawable/fastscroll_normal"
app:thumbDragging="@drawable/fastscroll_pressed"
app:thumbTint="@color/blue" />
Now you need to pass a reference to a view inside attachTo
method:
val editor = findViewById<TextProcessor>(R.id.editor)
val scroller = findViewById<TextScroller>(R.id.scroller)
scroller.attachTo(editor)
// or using Plugin DSL:
val pluginSupplier = PluginSupplier.create {
...
textScroller {
scroller = findViewById<TextScroller>(R.id.scroller)
}
}
Code Suggestions
When you working with a code editor you want to see the list of code
suggestion. (Note that you have to provide a Language
object before
start using it.)
First, you need to create a layout file that will represent the suggestion item inside dropdown menu:
<!-- item_suggestion.xml -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:padding="6dp"
android:textSize="12sp"
android:typeface="monospace"
android:id="@+id/title" />
Second, you need to create custom SuggestionAdapter
:
class AutoCompleteAdapter(context: Context) : SuggestionAdapter(context, R.layout.item_suggestion) {
override fun createViewHolder(parent: ViewGroup): SuggestionViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.item_suggestion, parent, false)
return AutoCompleteViewHolder(view)
}
class AutoCompleteViewHolder(itemView: View) : SuggestionViewHolder(itemView) {
private val title: TextView = itemView.findViewById(R.id.title)
override fun bind(suggestion: Suggestion?, query: String) {
title.text = suggestion?.text
}
}
}
Third, enable the code completion plugin and set
SuggestionAdapter
:
val pluginSupplier = PluginSupplier.create {
...
codeCompletion {
suggestionAdapter = AutoCompleteAdapter(this)
}
}
UPD: If you having an issues with the popup position (e.g vertical offset), this might be solved by explicitly setting android:dropDownAnchor in XML.
Undo Redo
The TextProcessor
supports undo/redo operations, but remember that you
must check the ability to undo/redo before calling actual methods:
// Undo
if (editor.canUndo()) {
editor.undo()
}
// Redo
if (editor.canRedo()) {
editor.redo()
}
Also you may have a use case when you want to update undo/redo buttons
visibility or other UI after the text replacements is done, this can be
achieved by adding OnUndoRedoChangedListener
:
editor.onUndoRedoChangedListener = object : OnUndoRedoChangedListener {
override fun onUndoRedoChanged() {
val canUndo = editor.canUndo()
val canRedo = editor.canRedo()
// ...
}
}
Navigation
Text Navigation
You can use these extension methods to navigate in text:
editor.moveCaretToStartOfLine()
editor.moveCaretToEndOfLine()
editor.moveCaretToPrevWord()
editor.moveCaretToNextWord()
...or use «Go to Line» feature to place the caret at the specific line:
import com.blacksquircle.ui.editorkit.exception.LineException
try {
editor.gotoLine(lineNumber)
} catch (e: LineException) {
Toast.makeText(this, "Line does not exists", Toast.LENGTH_SHORT).show()
}
Find and Replace
The TextProcessor
has built-in support for search and replace
operations, including:
- Search forward or backward
- Regular Expressions
- Match Case
- Words Only
The class itself contains self-explanatory methods for all your searching needs:
find(params)
- Find all possible results in text with provided options.replaceFindResult(replaceText)
- Finds current match and replaces it with new text.replaceAllFindResults(replaceText)
- Finds all matches and replaces them with the new text.findNext()
- Finds the next match and scrolls to it.findPrevious()
- Finds the previous match and scrolls to it.clearFindResultSpans()
- Clears all find spans on the screen. Call this method when you're done searching.
import com.blacksquircle.ui.editorkit.model.FindParams
val params = FindParams(
query = "function", // text to find
regex = false, // regular expressions
matchCase = true, // case sensitive
wordsOnly = true // words only
)
editor.find(params)
// To navigate between results use findNext() and findPrevious()
Shortcuts
If you're using bluetooth keyboard you probably want to use keyboard
shortcuts to write your code faster. To support the keyboard shortcuts
you need to enable the shortcuts plugin and set OnShortcutListener
:
val pluginSupplier = PluginSupplier.create {
...
shortcuts {
onShortcutListener = object : OnShortcutListener {
override fun onShortcut(shortcut: Shortcut): Boolean {
val (ctrl, shift, alt, keyCode) = shortcut
return when {
ctrl && keyCode == KeyEvent.KEYCODE_DPAD_LEFT -> editor.moveCaretToStartOfLine()
ctrl && keyCode == KeyEvent.KEYCODE_DPAD_RIGHT -> editor.moveCaretToEndOfLine()
alt && keyCode == KeyEvent.KEYCODE_DPAD_LEFT -> editor.moveCaretToPrevWord()
alt && keyCode == KeyEvent.KEYCODE_DPAD_RIGHT -> editor.moveCaretToNextWord()
// ...
else -> false
}
}
}
}
}
The onShortcut
method will be invoked only if at least one of
following keys is pressed: ctrl, shift,
alt.
You might already noticed that you have to return a Boolean
value as
the result of onShortcut
method. Return true
if the listener has
consumed the shortcut event, false
otherwise.
Theming
The editorkit
module includes some default themes in the EditorTheme
class:
editor.colorScheme = EditorTheme.DARCULA // default
// or you can use one of these:
EditorTheme.MONOKAI
EditorTheme.OBSIDIAN
EditorTheme.LADIES_NIGHT
EditorTheme.TOMORROW_NIGHT
EditorTheme.VISUAL_STUDIO_2013
You can also write your own theme by changing the ColorScheme
properties. The example below shows how you can programmatically load
the color scheme:
editor.colorScheme = ColorScheme(
textColor = Color.parseColor("#C8C8C8"),
backgroundColor = Color.parseColor("#232323"),
gutterColor = Color.parseColor("#2C2C2C"),
gutterDividerColor = Color.parseColor("#555555"),
gutterCurrentLineNumberColor = Color.parseColor("#FFFFFF"),
gutterTextColor = Color.parseColor("#C6C8C6"),
selectedLineColor = Color.parseColor("#141414"),
selectionColor = Color.parseColor("#454464"),
suggestionQueryColor = Color.parseColor("#4F98F7"),
findResultBackgroundColor = Color.parseColor("#1C3D6B"),
delimiterBackgroundColor = Color.parseColor("#616161"),
numberColor = Color.parseColor("#BACDAB"),
operatorColor = Color.parseColor("#DCDCDC"),
keywordColor = Color.parseColor("#669BD1"),
typeColor = Color.parseColor("#669BD1"),
langConstColor = Color.parseColor("#669BD1"),
preprocessorColor = Color.parseColor("#C49594"),
variableColor = Color.parseColor("#9DDDFF"),
methodColor = Color.parseColor("#71C6B1"),
stringColor = Color.parseColor("#CE9F89"),
commentColor = Color.parseColor("#6BA455"),
tagColor = Color.parseColor("#DCDCDC"),
tagNameColor = Color.parseColor("#669BD1"),
attrNameColor = Color.parseColor("#C8C8C8"),
attrValueColor = Color.parseColor("#CE9F89"),
entityRefColor = Color.parseColor("#BACDAB")
)
Custom Plugin
Since v2.1.0 the EditorKit library supports writing custom
plugins to extend it's functionality. If you're using the latest version,
you might be familiar with PluginSupplier
and know how to use it's DSL.
See More Options for info.
First, you need to create a class which extends the EditorPlugin
and provide it's id in the constructor:
class CustomPlugin : EditorPlugin("custom-plugin-id") {
var publicProperty = true
override fun onAttached(editText: TextProcessor) {
super.onAttached(editText)
// TODO enable your feature here
}
override fun onDetached(editText: TextProcessor) {
super.onDetached(editText)
// TODO disable your feature here
}
}
Second, you can override lifecycle methods, for example afterDraw
,
which invoked immediately after onDraw(Canvas)
in code editor:
class CustomPlugin : EditorPlugin("custom-plugin-id") {
var publicProperty = true
private val dividerPaint = Paint().apply {
color = Color.GRAY
}
override fun afterDraw(canvas: Canvas?) {
super.afterDraw(canvas)
if (publicProperty) {
var i = editText.topVisibleLine
while (i <= editText.bottomVisibleLine) {
val startX = editText.paddingStart + editText.scrollX
val startY = editText.paddingTop + editText.layout.getLineBottom(i)
val stopX = editText.paddingLeft + editText.layout.width + editText.paddingRight
val stopY = editText.paddingTop + editText.layout.getLineBottom(i)
canvas?.drawLine( // draw divider for each visible line
startX.toFloat(), startY.toFloat(),
stopX.toFloat(), stopY.toFloat(),
dividerPaint
)
i++
}
}
}
}
Third, create an extension function to improve code readability when
adding your plugin to a PluginSupplier
:
fun PluginSupplier.lineDividers(block: CustomPlugin.() -> Unit = {}) {
plugin(CustomPlugin(), block)
}
Finally, you can attach your plugin using DSL:
val pluginSupplier = PluginSupplier.create {
lineDividers {
publicProperty = true // whether should draw the dividers
}
...
}
editor.plugins(pluginSupplier)
Languages
The language modules provides support for programming languages. This
includes syntax highlighting, code suggestions and source code parser.
(Note that source code parser currently works only in
language-javascript
module, but it will be implemented for more
languages in the future)
Gradle Dependency
Select your language and add it's dependency to your module's
build.gradle
file:
dependencies {
...
implementation 'com.blacksquircle.ui:language-actionscript:2.2.0'
implementation 'com.blacksquircle.ui:language-base:2.2.0' // for custom language
implementation 'com.blacksquircle.ui:language-c:2.2.0'
implementation 'com.blacksquircle.ui:language-cpp:2.2.0'
implementation 'com.blacksquircle.ui:language-csharp:2.2.0'
implementation 'com.blacksquircle.ui:language-groovy:2.2.0'
implementation 'com.blacksquircle.ui:language-html:2.2.0'
implementation 'com.blacksquircle.ui:language-java:2.2.0'
implementation 'com.blacksquircle.ui:language-javascript:2.2.0'
implementation 'com.blacksquircle.ui:language-json:2.2.0'
implementation 'com.blacksquircle.ui:language-julia:2.2.0'
implementation 'com.blacksquircle.ui:language-kotlin:2.2.0'
implementation 'com.blacksquircle.ui:language-lisp:2.2.0'
implementation 'com.blacksquircle.ui:language-lua:2.2.0'
implementation 'com.blacksquircle.ui:language-markdown:2.2.0'
implementation 'com.blacksquircle.ui:language-php:2.2.0'
implementation 'com.blacksquircle.ui:language-plaintext:2.2.0'
implementation 'com.blacksquircle.ui:language-python:2.2.0'
implementation 'com.blacksquircle.ui:language-ruby:2.2.0'
implementation 'com.blacksquircle.ui:language-shell:2.2.0'
implementation 'com.blacksquircle.ui:language-smali:2.2.0'
implementation 'com.blacksquircle.ui:language-sql:2.2.0'
implementation 'com.blacksquircle.ui:language-toml:2.2.0'
implementation 'com.blacksquircle.ui:language-typescript:2.2.0'
implementation 'com.blacksquircle.ui:language-visualbasic:2.2.0'
implementation 'com.blacksquircle.ui:language-xml:2.2.0'
implementation 'com.blacksquircle.ui:language-yaml:2.2.0'
}
Custom Language
First, add this to your module's build.gradle
file:
dependencies {
...
implementation 'com.blacksquircle.ui:language-base:2.2.0'
}
Second, implement the Language
interface:
import com.blacksquircle.ui.language.base.Language
import com.blacksquircle.ui.language.base.parser.LanguageParser
import com.blacksquircle.ui.language.base.provider.SuggestionProvider
import com.blacksquircle.ui.language.base.styler.LanguageStyler
class CustomLanguage : Language {
override val languageName = "custom language"
override fun getParser(): LanguageParser {
return CustomParser()
}
override fun getProvider(): SuggestionProvider {
return CustomProvider()
}
override fun getStyler(): LanguageStyler {
return CustomStyler()
}
}
Every language consist of 3 key components:
- LanguageParser is responsible for analyzing the source code. The code editor does not use this component directly.
- SuggestionProvider is responsible for collecting the names of functions, fields, and keywords within your file scope. The code editor use this component to display the list of code suggestions.
- LanguageStyler is responsible for syntax highlighting. The code editor use this component to display syntax highlight spans on the screen.
LanguageParser
LanguageParser
is an interface which detects syntax errors so you can
display them in the TextProcessor
later.
To create a custom parser you need to implement execute
method that
will return a ParseResult
.
If ParseResult
contains an exception it means that the source code
can't compile and contains syntax errors. You can highlight an error
line by calling editor.setErrorLine(lineNumber)
method.
Remember that you shouldn't use this method on the main thread.
class CustomParser : LanguageParser {
override fun execute(name: String, source: String): ParseResult {
// TODO Implement parser
val lineNumber = 0
val columnNumber = 0
val parseException = ParseException("describe exception here", lineNumber, columnNumber)
return ParseResult(parseException)
}
}
SuggestionProvider
SuggestionProvider
is an interface which provides code suggestions to
display them in the TextProcessor
.
The text scanning is done on a per-line basis. When the user edits code
on a single line, that line is re-scanned by the current
SuggestionsProvider
implementation, so you can keep your suggestions
list up to date. This is done by calling the processLine
method. This
method is responsible for parsing a line of text and saving the code
suggestions for that line.
After calling setTextContent
the code editor will call processLine
for each line to find all possible code suggestions.
class CustomProvider : SuggestionProvider {
// You can use WordsManager
// if you don't want to write the language-specific implementation
private val wordsManager = WordsManager()
override fun getAll(): Set<Suggestion> {
return wordsManager.getWords()
}
override fun processLine(lineNumber: Int, text: String) {
wordsManager.processLine(lineNumber, text)
}
override fun deleteLine(lineNumber: Int) {
wordsManager.deleteLine(lineNumber)
}
override fun clearLines() {
wordsManager.clearLines()
}
}
LanguageStyler
LanguageStyler
is an interface which provides syntax highlight spans
to display them in the TextProcessor
.
The execute
method will be executed on the background thread every
time the text changes. You can use regex or lexer to find the keywords
in text.
Remember: the more spans you add, the more time it takes to render on the main thread.
class CustomStyler : LanguageStyler {
override fun execute(source: String, scheme: ColorScheme): List<SyntaxHighlightSpan> {
val syntaxHighlightSpans = mutableListOf<SyntaxHighlightSpan>()
// TODO Implement syntax highlighting
return syntaxHighlightSpans
}
}
*Note that all licence references and agreements mentioned in the Squircle IDE README section above
are relevant to that project's source code only.