Update
RecyclerView 具有水平布局。因此,将垂直蒙古文 TextView 放入其中之一相对容易。Here https://github.com/suragch/mongol-library#horizontal-recyclerview是一个例子mongol-library https://github.com/suragch/mongol-library.
See 这个答案 https://stackoverflow.com/questions/28460300/how-to-build-a-horizontal-listview-with-recyclerview/45953855#45953855对于使用的通用解决方案RecyclerView
制作水平滚动列表。
旧答案
非常不幸的是,Android API 不提供水平 ListView。不过,有许多 StackOverflow 问答讨论了如何做到这一点。以下是几个示例:
- 如何在Android中制作水平ListView? https://stackoverflow.com/questions/3877040/how-can-i-make-a-horizontal-listview-in-android
- Android 中的水平 ListView? https://stackoverflow.com/questions/3240331/horizontal-listview-in-android
但当我真正尝试实施这些建议并合并蒙古竖排文本时,我度过了一段糟糕的时光。在我的搜索中,我发现了一个略有不同的答案。它是旋转整个布局的类 https://github.com/rongi/rotate-layout。它是通过扩展 ViewGroup 来实现的。通过这种方式,任何东西(包括 ListView)都可以放入 ViewGroup 中并进行旋转。所有触摸事件也都有效。
正如我所解释的我关于蒙古文TextViews的回答 https://stackoverflow.com/a/29739721/3681880,仅仅旋转蒙古文文本是不够的。如果每个 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>
已知的问题:
- 如果仔细观察下图,您可以看到文本周围有淡淡的水平线和垂直线。虽然此图像来自另一个开发人员的应用程序,但当我使用旋转的 ViewGroup 时,我在应用程序中得到了相同的工件(但当我使用旋转的文本视图 https://stackoverflow.com/a/29739721/3681880)。如果有人知道这些来自哪里,请给我评论!
- 此解决方案不处理 Unicode 文本的渲染。您需要使用非 Unicode 文本(不鼓励),或者需要在应用程序中包含渲染引擎。 (Android 目前不支持 OpenType smartfont 渲染。希望将来会改变。相比之下,iOS 支持复杂的文本渲染字体。)请参阅这个链接 https://github.com/suragch/Chimee/blob/master/app/src/main/java/net/studymongolian/chimee/MongolUnicodeRenderer.javaUnicode 蒙古文渲染引擎示例。