更新
RecyclerViews具有水平布局。因此,在其中放置一个垂直的蒙古文本视图相对容易。这里是来自mongol-library
的示例。
![enter image description here](https://istack.dev59.com/0N8yh.webp)
请参阅此答案,了解使用RecyclerView
制作水平滚动列表的通用解决方案。
旧答案
非常不幸地,Android API没有提供水平ListView。有许多StackOverflow Q&A谈论如何实现它们。以下是一些示例:
但是当我尝试实现这些建议并结合蒙古语垂直文本时,我遇到了很大的困难。在我的搜索中,我找到了一个略微不同的答案。它是一个旋转整个布局的类。它通过扩展ViewGroup来实现。以这种方式,任何东西(包括ListView)都可以放在ViewGroup中并旋转。所有触摸事件也都有效。
正如我在关于蒙古文本视图的答案中所解释的那样,仅仅旋转蒙古文本是不够的。如果每个ListView项(或ViewGroup中的其他文本元素)只有一行,那就足够了,但是旋转多行会使换行走向错误的方向。然而,水平镜像布局并使用垂直镜像字体可以克服这个问题,如下图所示。
![enter image description here](https://istack.dev59.com/Yp7ZI.webp)
我将旋转的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 {
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();
}
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时(但不是当我使用旋转的TextView时),我的应用程序中也出现了同样的伪影。如果有人知道它们来自哪里,请给我留言!
![enter image description here](https://istack.dev59.com/sUMnZ.webp)
- 此解决方案无法处理Unicode文本的呈现。您要么需要使用非Unicode文本(不建议),要么需要在应用程序中包含呈现引擎。(Android目前不支持OpenType智能字体呈现。希望将来会改变。相比之下,iOS支持复杂的文本呈现字体。)请参见此链接以获取Unicode蒙古文呈现引擎示例。