Skip to content

Commit

Permalink
Improve AnsiTextView and add optional Emoji2 support on it.
Browse files Browse the repository at this point in the history
  • Loading branch information
Fox2Code committed May 29, 2022
1 parent 4a0abc8 commit 0cf4243
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 22 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# AndroidANSI
Android ANSI rendering library!

See [Wikipedia ANSI Page](https://en.wikipedia.org/wiki/ANSI_escape_code)
See [Wikipedia ANSI Page](https://en.wikipedia.org/wiki/ANSI_escape_code)
for more info on ANSI escape codes.

## Supported ANSI Codes
Expand Down Expand Up @@ -65,7 +65,7 @@ textView.setAnsiText("\\e[1;38;2;164;198;57mAndroid\\e[0;35mAN\u001B[2mSI\u001B[
AnsiParser.FLAG_PARSE_DISABLE_SUBSCRIPT);
```

## TextView w/o Java (Currently not working)
## TextView w/o Java (WIP)
```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
Expand All @@ -78,12 +78,14 @@ textView.setAnsiText("\\e[1;38;2;164;198;57mAndroid\\e[0;35mAN\u001B[2mSI\u001B[
<com.fox2code.androidansi.AnsiTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:setAnsiText="\e[38;5;82mHello \e[38;5;198mWorld"
app:ansiText="\e[38;5;82mHello \e[38;5;198mWorld"
android:id="@+id/ansiView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```
```

Note: AnsiTextView support Emoji2 if the library `androidx.emoji2:emoji2-views-helper:*` is added.
2 changes: 1 addition & 1 deletion androidansiapp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies {
implementation(project(":library"))
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.library' version '7.2.0' apply false
id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.2.1' apply false
id 'com.android.application' version '7.2.1' apply false
}

task clean(type: Delete) {
Expand Down
3 changes: 3 additions & 0 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ android {

dependencies {
api 'androidx.annotation:annotation:1.3.0'
compileOnly('androidx.emoji2:emoji2-views-helper:1.1.0') {
transitive = false
}
}

afterEvaluate {
Expand Down
74 changes: 60 additions & 14 deletions library/src/main/java/com/fox2code/androidansi/AnsiTextView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,95 @@

import static com.fox2code.androidansi.AnsiParser.parseAsSpannable;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.text.InputFilter;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.emoji2.viewsintegration.EmojiTextViewHelper;

public class AnsiTextView extends TextView{
public class AnsiTextView extends TextView {
public static final int FLAG_PARSE_DISABLE_COLORS = AnsiParser.FLAG_PARSE_DISABLE_COLORS;
public static final int FLAG_PARSE_DISABLE_ATTRIBUTES = AnsiParser.FLAG_PARSE_DISABLE_ATTRIBUTES;
public static final int FLAG_PARSE_DISABLE_EXTRAS_COLORS = AnsiParser.FLAG_PARSE_DISABLE_EXTRAS_COLORS;
public static final int FLAG_PARSE_DISABLE_SUBSCRIPT = AnsiParser.FLAG_PARSE_DISABLE_SUBSCRIPT;

public final int FLAG_PARSE_DISABLE_COLORS = AnsiParser.FLAG_PARSE_DISABLE_COLORS;
public final int FLAG_PARSE_DISABLE_ATTRIBUTES = AnsiParser.FLAG_PARSE_DISABLE_ATTRIBUTES;
public final int FLAG_PARSE_DISABLE_EXTRAS_COLORS = AnsiParser.FLAG_PARSE_DISABLE_EXTRAS_COLORS;
public final int FLAG_PARSE_DISABLE_SUBSCRIPT = AnsiParser.FLAG_PARSE_DISABLE_SUBSCRIPT;
private Object mEmojiTextViewHelper; // Hold reference without requiring hard references
private int parseFlags = 0;

public AnsiTextView(Context context) {
super(context);
preInit();
}

public AnsiTextView(Context context, AttributeSet attrs) {
super(context, attrs);
readAttr(context,attrs);
preInit();
readAttr(context, attrs);
}

public AnsiTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
readAttr(context,attrs);
preInit();
readAttr(context, attrs);
}

public void setAnsiText(@NonNull String ansiText) {
super.setText(parseAsSpannable(ansiText));
super.setText(parseAsSpannable(ansiText, this.parseFlags));
}

public void setAnsiText(@NonNull String ansiText, int parseFlags) {
super.setText(parseAsSpannable(ansiText, parseFlags));
}

private void preInit() {
try { // Using "new" for optional classes is ok with ART
mEmojiTextViewHelper = new EmojiTextViewHelper(this, false);
((EmojiTextViewHelper) mEmojiTextViewHelper).updateTransformationMethod();
} catch (Exception ignored) {
mEmojiTextViewHelper = null;
}
}

private void readAttr(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnsiTextView);
@NonNull String text = a.getString(R.styleable.AnsiTextView_setAnsiText) ;
if (text != null) {
super.setText(parseAsSpannable(text));
TypedArray a = null;
try {
a = context.obtainStyledAttributes(attrs, R.styleable.AnsiTextView);
@NonNull String text = a.getString(R.styleable.AnsiTextView_ansiText);
int parseFlags = a.getInt(R.styleable.AnsiTextView_ansiText, -1);
a.recycle(); a = null;
if (parseFlags != -1) {
this.parseFlags = parseFlags;
} else {
parseFlags = this.parseFlags;
}
if (text != null) {
super.setText(parseAsSpannable(text, parseFlags));
}
} catch (Resources.NotFoundException e) {
Log.w("AnsiTextView", "Failed to resolve ansiText resource!", e);
} finally {
if (a != null) a.recycle();
}
}

@Override
public void setFilters(InputFilter[] filters) {
if (this.mEmojiTextViewHelper != null) {
filters = ((EmojiTextViewHelper) this.mEmojiTextViewHelper).getFilters(filters);
}
super.setFilters(filters);
}

@Override
public void setAllCaps(boolean allCaps) {
super.setAllCaps(allCaps);
if (this.mEmojiTextViewHelper != null) {
((EmojiTextViewHelper) this.mEmojiTextViewHelper).setAllCaps(allCaps);
}
a.recycle();
}
}
9 changes: 8 additions & 1 deletion library/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AnsiTextView">
<attr name="setAnsiText" format="string" />
<attr name="ansiText" format="string" />
<attr name="ansiParseFlags">
<flag name="none" value="0x0000" />
<flag name="disableColors" value="0x0001" />
<flag name="disableAttributes" value="0x0002" />
<flag name="disableExtrasColors" value="0x0004" />
<flag name="disableSubscript" value="0x0008" />
</attr>
</declare-styleable>
</resources>

0 comments on commit 0cf4243

Please sign in to comment.