Stripping out Emoji Fitzpatrick (skin tone) characters in Android TextView - android

I am trying to display some text that can contain emojis that were created on an iOS version of the app. When we render these characters on Android I see [x] next to the emoji.
Is there a way to extend the Android TextView so that skin tone characters are ignored when rendering textviews.
I've tried creating a regex to replace them with empty characters but Android Studio complains that the regex isn't valid because the hex character syntax is not supported and it looks like other escape characters are also stripped out
replaceAll("[\\x{1f3fb}-\\x{1f3ff}]", "")

I think I've finally worked it out.
public class CustomTextView extends AppCompatTextView {
private static final String FITZPATRICK_PREFIX = "\uD83C";
public CustomTextView(Context context) {
this(context, null);
}
public CustomTextView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setText(final CharSequence text, final BufferType type) {
super.setText(stripFitzpatrickCharacters(text == null ? "" : text.toString()), type);
}
public static String stripFitzpatrickCharacters(#NonNull final String string) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && string.contains(FITZPATRICK_PREFIX)) {
final String[] parts = string.split(FITZPATRICK_PREFIX);
final StringBuilder builder = new StringBuilder();
builder.append(parts[0]);
for (int i = 1; i < parts.length; i++) {
builder.append(parts[i].substring(1));
}
return builder.toString();
} else {
return string;
}
}
}

Related

How to remove emoji option from soft input keyboard when input type is textpassword

When i am trying to enter password then i am getting emoji option in my soft input keyboard. So guys does any one has any idea how to remove this emoji option from soft input keyboard if my input type is textpassword
Customize the view.
public class CustomEditText extends EditText {
public CustomEditText(Context context) {
super(context);
init();
}
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setFilters(new InputFilter[]{new EmojiExcludeFilter()});
}
private class EmojiExcludeFilter implements InputFilter {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
int type = Character.getType(source.charAt(i));
if (type == Character.SURROGATE || type == Character.OTHER_SYMBOL) {
return "";
}
}
return null;
}
}
}

How make spacing between letters in Android TextView?

I need make design from photoshop layout. There are some fonts on the layouts.
Designer gave me this fonts. But on layout in photoshop, he use spacing between letters. How i can realize this in android textView? I found one solution:
answer on stackoverflow
answer two
but if i make myTextView extends TextView it work wrong. If i adapt for one devise, on the device with biger display, spacing between letters increase is not proportional.
EDIT
public class MyTextView extends TextView {
private float letterSpacing = 0.0f;
private CharSequence originalText = "";
private Typeface typeface;
public MyTextView(Context context) {
this(context, null);
isInEditMode();
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
isInEditMode();
}
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray attributesArray = getResources().obtainAttributes(attrs, R.styleable.MyTextView);
letterSpacing = attributesArray.getDimension(R.styleable.MyTextView_letterSpacing, 0.0f);
String fontName = attributesArray.getString(R.styleable.MyTextView_fontName);
if(!this.isInEditMode()) {
if (null == fontName) {
typeface = Fonts.getBlockBertholdRegular(context);
} else {
typeface = Fonts.get(context, fontName);
}
super.setTypeface(typeface);
}
originalText = super.getText();
applyLetterSpacing();
this.invalidate();
}
public float getLetterSpacing() {
return letterSpacing;
}
public void setLetterSpacing(float letterSpacing) {
this.letterSpacing = letterSpacing;
applyLetterSpacing();
}
#Override
public void setText(CharSequence text, BufferType type) {
originalText = text;
applyLetterSpacing();
}
#Override
public CharSequence getText() {
return originalText;
}
private void applyLetterSpacing() {
if (this == null || this.originalText == null) return;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < originalText.length(); i++) {
String c = "" + originalText.charAt(i);
builder.append(c.toUpperCase());
if (i + 1 < originalText.length()) {
builder.append("\u00A0");
}
}
SpannableString finalText = new SpannableString(builder.toString());
if (builder.toString().length() > 1) {
for (int i = 1; i < builder.toString().length(); i += 2) {
finalText.setSpan(new ScaleXSpan((letterSpacing + 1) / 10), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
super.setText(finalText, BufferType.SPANNABLE);
if(!this.isInEditMode()) {
super.setTypeface(typeface);
}
}
}
Try using the new TextView API method setLetterSpacing.
See here
EDIT
You can also create your own font with spaces inside the font itself and apply it to your TextView.
Since API 21 You can use
setLetterSpacing
Documentation can be found here

Change Letter Spacing/Kerning EditText

I have a costum built EditText Class, I was wondering if it's possible to change the EditText's Kerning, I have an issue with this, because it will be a password field, so it seams I can't use:
builder.append("\u00A0");
Edit: Here is the code.
public class MyEditText extends EditText {
private float mLetterSpacing = 0;
private CharSequence mOriginalText = "";
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public float getLetterSpacing() {
return mLetterSpacing;
}
public void setLetterSpacing(float letterSpacing) {
mLetterSpacing = letterSpacing;
applyLetterSpacing();
}
#Override
public void setText(CharSequence text, BufferType type) {
mOriginalText = text;
applyLetterSpacing();
}
public void applyLetterSpacing() {
StringBuilder builder = new StringBuilder();
for(int i = 0; i < mOriginalText.length(); i++) {
String c = ""+ mOriginalText.charAt(i);
builder.append(c.toLowerCase());
if(i+1 < mOriginalText.length()) {
builder.append("\u00A0");
}
}
SpannableString finalText = new SpannableString(builder.toString());
if(builder.toString().length() > 1) {
for(int i = 1; i < builder.toString().length(); i+=2) {
finalText.setSpan(new ScaleXSpan((mLetterSpacing+1)/10), i, i+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
super.setText(finalText, BufferType.SPANNABLE);
}
public static Spannable applyKerning(CharSequence src, float kerning) {
if (src == null) return null;
final int srcLength = src.length();
if (srcLength < 2) return src instanceof Spannable
? (Spannable)src
: new SpannableString(src);
final String nonBreakingSpace = "\u00A0";
final SpannableStringBuilder builder = src instanceof SpannableStringBuilder
? (SpannableStringBuilder)src
: new SpannableStringBuilder(src);
for (int i = src.length() - 1; i >= 1; i--)
{
builder.insert(i, nonBreakingSpace);
builder.setSpan(new ScaleXSpan(kerning), i, i + 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return builder;
}
}
I tried this, but ofc with no success. I was wondering if it's possible to add the spacing without messing with the "password String".
I think the best (only?) way to do this would be to use a font typeface that has the kerning you want and set that on the EditText. It doesn't look like there is a way to programmatically alter the kerning.

Android RTL password fields?

It appears that if you have an EditText on android with the
android:inputType="textPassword" or android:password="true
fields on them, right-to-left text does NOT appear right-to-left (stays left-to-right).
However without the password denotations the text does appear RTL.
Is this a known issue or is there a workaround?
For 17+ (4.2.x+) you can use textAlignment
android:textAlignment="viewStart"
The only solution I've found was to set the gravity programatically to LEFT or RIGHT after setting the inputType.
In my case, the problem was simply solved by changing the layout_width to wrap_content.
If you put inputType = textPassword or set a passwordTransformation method on EditText, text direction is taken as LTR. It means RTL for password is discouraged. You need to write custom TextView to override this behaviour.
Code snippet from android source for TextView.
// PasswordTransformationMethod always have LTR text direction heuristics returned by
// getTextDirectionHeuristic, needs reset
mTextDir = getTextDirectionHeuristic();
protected TextDirectionHeuristic getTextDirectionHeuristic() {
if (hasPasswordTransformationMethod()) {
// passwords fields should be LTR
return TextDirectionHeuristics.LTR;
}
In My Case both worked fine.
1) android:textAlignment="viewStart"
And
2)
https://stackoverflow.com/a/38291472/6493661
and the right answer is:
RtlEditText mUserPassword = root.findViewById(R.id.register_fragment_password);
mUserPassword.setTransformationMethod(new AsteriskPasswordTransformationMethod());
creating our own EditText!
it work prefectly only if you replace the dot with astrix by AsteriskPasswordTransformationMethod below this code.
public class RtlEditText extends EditText {
public RtlEditText(Context context) {
super(context);
}
public RtlEditText(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public RtlEditText(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public RtlEditText(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public TextDirectionHeuristic getTextDirectionHeuristic() {
// passwords fields should be LTR
return TextDirectionHeuristics.ANYRTL_LTR;
}}
public class AsteriskPasswordTransformationMethod extends PasswordTransformationMethod {
#Override
public CharSequence getTransformation(CharSequence source, View view) {
return new PasswordCharSequence(source);
}
private class PasswordCharSequence implements CharSequence {
private CharSequence mSource;
public PasswordCharSequence(CharSequence source) {
mSource = source; // Store char sequence
}
public char charAt(int index) {
return '*'; // This is the important part
}
public int length() {
return mSource.length(); // Return default
}
public CharSequence subSequence(int start, int end) {
return mSource.subSequence(start, end); // Return default
}
}
}

Performance issue on custom font TextView

I have a custom TextView, with a personalized font attribute:
public class TextViewPlus extends TextView {
private static final String TAG = "TextViewPlus";
public TextViewPlus(Context context) {
super(context);
}
public TextViewPlus(Context context, AttributeSet attrs) {
// This is called all the time I scroll my ListView
// and it make it very slow.
super(context, attrs);
setCustomFont(context, attrs);
}
public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
String customFont = a.getString(R.styleable.TextViewPlus_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface tf = null;
try {
tf = Typeface.createFromAsset(ctx.getAssets(), asset);
setTypeface(tf);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface: "+e.getMessage());
return false;
}
return true;
}
}
I'm using it in my XML files with the attribute customFont="ArialRounded.ttf", and it is working quite well.
I'm using this TextViewPlus in a ListView, populated with an ArrayAdapter.
TextViewPlus dataText = (TextViewPlus) itemView.findViewById(R.id.data_text);
dataText.setText("My data String");
My problem is that the performance, when I'm scrolling the ListView, are terrible! Very slow and full of lags. The TextViewPlus constructor n°2 it's called all the time i scroll the list.
If I change TextViewPlus in a normal TextView, and use dataText.setTypeface(myFont), everything is smood and is working well.
How can I use my TextViewPlus without performance issue?
Why don't you keep the created typface object in memory so that you don't create every time the text view is getting created.
Following is a sample class that creates and cache the typeface object:
public class TypeFaceProvider {
public static final String TYPEFACE_FOLDER = "fonts";
public static final String TYPEFACE_EXTENSION = ".ttf";
private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
4);
public static Typeface getTypeFace(Context context, String fileName) {
Typeface tempTypeface = sTypeFaces.get(fileName);
if (tempTypeface == null) {
String fontPath = new StringBuilder(TYPEFACE_FOLDER).append('/').append(fileName).append(TYPEFACE_EXTENSION).toString();
tempTypeface = Typeface.createFromAsset(context.getAssets(), fontPath);
sTypeFaces.put(fileName, tempTypeface);
}
return tempTypeface;
}
}

Categories

Resources