I am writing an app that displays in the Hebrew language and for that I am right aligning TextView's text.
While developing on a Nexus device all works great and texts are displayed as it should, using the android:gravity="right" for TextView.
When I am running the same app on a local mobile carrier device (Israel) which is running a custom ROM all TextView widgets that were set with gravity="right" are appearing as if they were set as gravity="left". If I go and change the gravity to left (you guessed it..) it will align right.
I have tried changing the default locale of the device back to US English using code and using the device configuration itself. Nothing helped.
The carrier device I am working on is a Galaxy SII.
Seems to me like who ever created the ROM just changed the align values and now right means left and left means right. The ROM is an official one from Samsung.
Did anyone experienced this issue? Any ideas for solutions?
What I've tried already:
1. Changing the device locale from the settings menu.
2. Changing the device locale programmatic.
3. Forcing the root Layout in the layout file to left/right layout_gravity/gravity
Only thing currently working is changing the gravity of the TextView to left, which means it stops working on global devices like the Nexus etc...
Answering my own question.
After looking all over I have found no answer. Because the ROM is custom made for people living in Israel and speaking Hebrew, it seems that the alignment inside a width MATCH_PARENT TextView is flipped. Meaning, Align left means right and right means left.
The only way to change that is to use TextView with WRAP_CONTENT and align the TextView itself to the right inside it's parent.
Because I've already written the app and all the screens layouts, I did not want to change everything.
So what I did is implemented a custom control which wraps a TextView inside a LinearLayout and exposes it for easy use from the out side.
This way, the MATCH_PARENT will effect the LinearLayout while the control will take care of aligning the wrapped TextView to the right.
And this is how:
First, the control class itself (HebrewTextView.java):
public class HebrewTextView extends LinearLayout
{
private TextView mTextView;
public HebrewTextView(Context context)
{
super(context);
init(null);
}
public HebrewTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
init(attrs);
}
public TextView getTextView()
{
return mTextView;
}
private void init(AttributeSet attrs)
{
mTextView = new TextView(getContext());
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
lp.gravity = Gravity.RIGHT;
mTextView.setLayoutParams(lp);
mTextView.setGravity(Gravity.CENTER_VERTICAL);
addView(mTextView);
if(attrs!=null)
{
TypedArray params = getContext().obtainStyledAttributes(attrs, R.styleable.HebrewTextView);
mTextView.setText(params.getString(R.styleable.HebrewTextView_android_text));
mTextView.setTextColor(params.getColor(R.styleable.HebrewTextView_android_textColor, Color.WHITE));
mTextView.setTextSize(params.getDimension(R.styleable.HebrewTextView_android_textSize, 10));
mTextView.setSingleLine(params.getBoolean(R.styleable.HebrewTextView_android_singleLine, false));
mTextView.setLines(params.getInt(R.styleable.HebrewTextView_android_lines, 1));
params.recycle();
}
}
}
The control XML attributes under values/attrs.xml. Notice that the custom attributes match the TextView attributes so I wont have to change the layout files:
Note: these are the attributes I needed, if you are using some more, just add to the XML and read it in the init() of the class.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HebrewTextView">
<attr name="android:text"/>
<attr name="android:textColor"/>
<attr name="android:lines"/>
<attr name="android:textSize"/>
<attr name="android:singleLine"/>
</declare-styleable>
</resources>
After that is done all I had to do is to run over the problematic layouts and replace TextView with HebrewTextView and if it was a TextView that is referenced by the code, change the casting.
The method getTextView() was defined in the control class so that sections in the code that changes the text and/or other TextView properties will work after adding the .getTextView() postfix.
Hope that helps.