Skip to content

Commit 74e0b8f

Browse files
author
farfromrefuge
committed
fix(android): faster and lighter(using proguard/native-api-usage) implementation
1 parent 982673b commit 74e0b8f

File tree

5 files changed

+272
-172
lines changed

5 files changed

+272
-172
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package com.nativescript.label;
2+
3+
import androidx.appcompat.widget.AppCompatTextView;
4+
import com.nativescript.text.TextView;
5+
import android.content.Context;
6+
import android.graphics.Paint;
7+
import android.graphics.Color;
8+
import android.graphics.Typeface;
9+
import android.os.Build;
10+
import android.text.method.MovementMethod;
11+
import android.text.style.URLSpan;
12+
import android.text.TextUtils.TruncateAt;
13+
import android.view.Gravity;
14+
import android.view.LayoutInflater;
15+
import androidx.core.widget.TextViewCompat;
16+
17+
public class NSLabel extends TextView {
18+
static int layoutId = -1;
19+
private int lineHeight = -1;
20+
21+
public NSLabel(Context context) {
22+
super(context);
23+
}
24+
public NSLabel(Context context, android.util.AttributeSet attrs) {
25+
super(context, attrs);
26+
}
27+
28+
public static boolean attributedStringHasURLSpan(android.text.Spannable attributeString) {
29+
return attributedStringHasSpan(attributeString, URLSpan.class);
30+
}
31+
32+
public static NSLabel inflateLayout(Context context) {
33+
if (layoutId == -1) {
34+
layoutId = context.getResources().getIdentifier("ns_label", "layout", context.getPackageName());
35+
}
36+
LayoutInflater inflater = (LayoutInflater)context.getSystemService
37+
(Context.LAYOUT_INFLATER_SERVICE);
38+
return (NSLabel)inflater.inflate(layoutId, null);
39+
}
40+
41+
@Override
42+
public void setMaxLines (int maxLines) {
43+
super.setMaxLines(maxLines);
44+
}
45+
46+
@Override
47+
public void setTextIsSelectable (boolean value) {
48+
super.setTextIsSelectable(value);
49+
}
50+
51+
public void setLineBreak (String value) {
52+
switch (value) {
53+
case "end":
54+
setEllipsize(TruncateAt.END);
55+
break;
56+
case "start":
57+
setEllipsize(TruncateAt.START);
58+
break;
59+
case "marquee":
60+
setEllipsize(TruncateAt.MARQUEE);
61+
break;
62+
case "middle":
63+
setEllipsize(TruncateAt.MIDDLE);
64+
break;
65+
case "none":
66+
setEllipsize(null);
67+
break;
68+
}
69+
}
70+
71+
public void setWhiteSpace (String value) {
72+
switch (value) {
73+
case "initial":
74+
case "normal":
75+
setSingleLine(false);
76+
setEllipsize(null);
77+
break;
78+
case "nowrap":
79+
setSingleLine(true);
80+
setEllipsize(TruncateAt.END);
81+
break;
82+
}
83+
}
84+
85+
@Override
86+
public void setShadowLayer (float radius,
87+
float dx,
88+
float dy,
89+
int color) {
90+
super.setShadowLayer(radius, dx, dy, color);
91+
}
92+
93+
protected int getHorizontalGravity(String textAlignment) {
94+
if (textAlignment == null) {
95+
return Gravity.START;
96+
}
97+
switch (textAlignment) {
98+
case "center":
99+
return Gravity.CENTER_HORIZONTAL;
100+
case "right":
101+
return Gravity.END;
102+
default:
103+
return Gravity.START;
104+
}
105+
}
106+
107+
protected int getVerticalGravity(String textAlignment) {
108+
if (textAlignment == null) {
109+
return Gravity.TOP;
110+
}
111+
switch (textAlignment) {
112+
case "middle":
113+
case "center":
114+
return Gravity.CENTER_VERTICAL;
115+
case "bottom":
116+
return Gravity.BOTTOM;
117+
default:
118+
return Gravity.TOP;
119+
}
120+
}
121+
122+
public void setVerticalTextAlignment (String value, String textAlignment) {
123+
setGravity(getHorizontalGravity(textAlignment) | getVerticalGravity(value));
124+
}
125+
126+
public void setLabelTextAlignment (String value, String verticalTextAlignment) {
127+
if (Build.VERSION.SDK_INT >= 26) {
128+
if (value == "justify") {
129+
setJustificationMode(android.text.Layout.JUSTIFICATION_MODE_INTER_WORD);
130+
} else {
131+
setJustificationMode(android.text.Layout.JUSTIFICATION_MODE_NONE);
132+
setGravity(getHorizontalGravity(value) | getVerticalGravity(verticalTextAlignment));
133+
}
134+
} else {
135+
setGravity(getHorizontalGravity(value) | getVerticalGravity(verticalTextAlignment));
136+
}
137+
}
138+
139+
public void enableAutoSize(int minFontSize, int maxFontSize, int step) {
140+
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
141+
this,
142+
minFontSize,
143+
maxFontSize,
144+
step,
145+
android.util.TypedValue.COMPLEX_UNIT_DIP
146+
);
147+
}
148+
149+
public void disableAutoSize() {
150+
TextViewCompat.setAutoSizeTextTypeWithDefaults(
151+
this,
152+
TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE
153+
);
154+
}
155+
156+
public void setLabelTextSize(int unit, float size, int minFontSize ,
157+
int maxFontSize,
158+
int step ) {
159+
160+
boolean autoFontSizeEnabled = TextViewCompat.getAutoSizeTextType(this) == TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM;
161+
162+
// setTextSize is ignored if autoFontSize is enabled
163+
// so we need to disable autoFontSize just to set textSize
164+
if (autoFontSizeEnabled) {
165+
disableAutoSize();
166+
}
167+
setTextSize(unit, size);
168+
169+
if (autoFontSizeEnabled) {
170+
enableAutoSize(minFontSize, maxFontSize, step);
171+
}
172+
}
173+
174+
@Override
175+
public void setLineHeight(int value) {
176+
lineHeight = value;
177+
if (Build.VERSION.SDK_INT >= 28) {
178+
super.setLineHeight(value);
179+
} else {
180+
float fontHeight = getPaint().getFontMetrics(null);
181+
setLineSpacing(value - fontHeight, 1.0f);
182+
}
183+
}
184+
@Override
185+
public void setTypeface(Typeface value) {
186+
super.setTypeface(value);
187+
if (Build.VERSION.SDK_INT < 28 && lineHeight >= 0) {
188+
float fontHeight = getPaint().getFontMetrics(null);
189+
setLineSpacing(lineHeight - fontHeight, 1.0f);
190+
}
191+
}
192+
193+
public void setTextDecoration(String value) {
194+
switch (value) {
195+
case "underline":
196+
setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);
197+
break;
198+
case "line-through":
199+
setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG);
200+
break;
201+
case "underline line-through":
202+
setPaintFlags(
203+
Paint.UNDERLINE_TEXT_FLAG | Paint.STRIKE_THRU_TEXT_FLAG
204+
);
205+
break;
206+
default:
207+
setPaintFlags(0);
208+
break;
209+
}
210+
}
211+
212+
public void setTextDecoration(int value) {
213+
setPaintFlags(value);
214+
}
215+
private MovementMethod defaultMovementMethod = null;
216+
public void setTappableState(boolean value) {
217+
if (value) {
218+
defaultMovementMethod = getMovementMethod();
219+
setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
220+
setHighlightColor(Color.TRANSPARENT);
221+
} else {
222+
setMovementMethod(defaultMovementMethod);
223+
}
224+
}
225+
}

plugin/platforms/android/native-api-usage.json

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
11
{
22
"uses": [
3-
"android.text:Spannable",
4-
"android.text.style:URLSpan",
5-
"android.text.style:ClickableSpan",
6-
"android.text:TextPaint",
7-
"android.text.method:MovementMethod",
8-
"android.text:TextUtils.TruncateAt",
9-
"android.text:Layout",
10-
"android.os:Build",
11-
"android.util:TypedValue",
12-
"android.view:LayoutInflater",
13-
"android.graphics:Paint",
14-
"android.graphics:Paint.FontMetrics",
15-
"android.text:Spanned",
16-
"androidx.core.widget:TextViewCompat"
3+
"com.nativescript.label:NSLabel",
4+
"android.text:Spanned"
175
],
186
"proguard_whitelist": [
197
"org.apache.xerces.jaxp.SAXParserFactoryImpl",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<android.widget.TextView xmlns:android="http://schemas.android.com/apk/res/android"
2+
<com.nativescript.label.NSLabel xmlns:android="http://schemas.android.com/apk/res/android"
33
android:layout_width="match_parent"
44
android:layout_height="match_parent">
5-
</android.widget.TextView>
5+
</com.nativescript.label.NSLabel>

0 commit comments

Comments
 (0)