如何在Android应用中为垂直蒙古语脚本水平滚动ListView?
Android对许多世界语言都有相当好的支持,甚至包括阿拉伯语和希伯来语等RTL语言。但是,没有像traditional Mongolian这样的自上而下语言的内置支持(在内蒙古仍然非常活跃,不要与Cyrillic Mongolian混淆)。为清晰起见,下图显示了添加了英语的文本方向。
由于此功能未内置于Android中,因此几乎使应用程序开发的每个方面都非常困难。对于水平ListViews尤其如此,Android中不支持开箱即用。在线提供的信息非常非常少。有许多针对传统蒙古语的应用程序开发人员,但无论是出于商业原因还是其他原因,他们似乎都没有使他们的代码成为开源代码。
由于存在这些困难,我想提出一系列StackOverflow问题,这些问题可以作为收集与传统蒙古应用程序开发相关的一些更困难的编程问题的答案的中心位置。即使您没有蒙古语识字,我们也会感谢您帮助查看代码,提出意见和问题,给出答案甚至是对问题进行投票。
Mongolian ListView需要具备以下要求:
还需要支持Mongolian TextView支持的所有内容:
下图显示了Mongolian ListView应具备的基本功能:
我的回答如下,但我欢迎其他方法来解决这个问题。
的iOS:
答案 0 :(得分:2)
RecyclerViews具有水平布局。因此,将Vertical Mongolian TextView放在其中一个中相对容易。 Here是mongol-library
的一个示例。
有关使用RecyclerView
制作水平滚动列表的一般解决方案,请参阅this answer。
非常不幸的是Android API没有提供水平ListView。然而,有很多StackOverflow Q& As谈论如何做到这一点。以下是几个样本:
但是,当我真正尝试实施这些建议以及合并蒙古文垂直文本时,我度过了一段可怕的时光。在我搜索的某处,我发现了一个略有不同的答案。那是a class that rotated an entire layout。它通过扩展ViewGroup来实现。通过这种方式,任何东西(包括ListView)都可以放在ViewGroup中并旋转。所有的触摸事件也都有效。
正如我在my answer about Mongolian TextViews中解释的那样,仅仅旋转蒙古文本是不够的。如果每个ListView项(或ViewGroup中的其他文本元素)只是一行,那就足够了,但是旋转多行会使换行方向错误。但是,水平镜像布局并使用垂直镜像字体可以克服此问题,如下图所示。
我调整了旋转的ViewGroup代码以执行水平镜像。
public class MongolViewGroup extends ViewGroup {
private int angle = 90;
private final Matrix rotateMatrix = new Matrix();
private final Rect viewRectRotated = new Rect();
private final RectF tempRectF1 = new RectF();
private final RectF tempRectF2 = new RectF();
private final float[] viewTouchPoint = new float[2];
private final float[] childTouchPoint = new float[2];
private boolean angleChanged = true;
public MongolViewGroup(Context context) {
this(context, null);
}
public MongolViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
}
public View getView() {
return getChildAt(0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View view = getView();
if (view != null) {
measureChild(view, heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(resolveSize(view.getMeasuredHeight(), widthMeasureSpec),
resolveSize(view.getMeasuredWidth(), heightMeasureSpec));
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (angleChanged) {
final RectF layoutRect = tempRectF1;
final RectF layoutRectRotated = tempRectF2;
layoutRect.set(0, 0, right - left, bottom - top);
rotateMatrix.setRotate(angle, layoutRect.centerX(), layoutRect.centerY());
rotateMatrix.postScale(-1, 1);
rotateMatrix.mapRect(layoutRectRotated, layoutRect);
layoutRectRotated.round(viewRectRotated);
angleChanged = false;
}
final View view = getView();
if (view != null) {
view.layout(viewRectRotated.left, viewRectRotated.top, viewRectRotated.right,
viewRectRotated.bottom);
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.rotate(-angle, getWidth() / 2f, getHeight() / 2f);
canvas.scale(-1, 1);
super.dispatchDraw(canvas);
canvas.restore();
}
@Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
invalidate();
return super.invalidateChildInParent(location, dirty);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
viewTouchPoint[0] = event.getX();
viewTouchPoint[1] = event.getY();
rotateMatrix.mapPoints(childTouchPoint, viewTouchPoint);
event.setLocation(childTouchPoint[0], childTouchPoint[1]);
boolean result = super.dispatchTouchEvent(event);
event.setLocation(viewTouchPoint[0], viewTouchPoint[1]);
return result;
}
}
蒙古垂直镜像字体仍然需要设置在其他地方。我发现制作自定义TextView最简单:
public class MongolNonRotatedTextView extends TextView {
// This class does not rotate the textview. It only displays the Mongol font.
// For use with MongolLayout, which does all the rotation and mirroring.
// Constructors
public MongolNonRotatedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MongolNonRotatedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MongolNonRotatedTextView(Context context) {
super(context);
init();
}
// This class requires the mirrored Mongolian font to be in the assets/fonts folder
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"fonts/MongolMirroredFont.ttf");
setTypeface(tf);
}
}
然后自定义ListView项目xml布局可能如下所示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rlListItem"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.MongolNonRotatedTextView
android:id="@+id/tvListViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"/>
</RelativeLayout>