Android中如何制作传统蒙古文ListView

2024-05-03

如何在 Android 应用程序中为垂直蒙古文制作水平滚动的 ListView?

背景

Android 对世界上许多语言都有相当好的支持,甚至是阿拉伯语和希伯来语等 RTL 语言。但是,没有内置对自上而下语言的支持,例如传统蒙古语 http://en.wikipedia.org/wiki/Mongolian_script(在内蒙古仍然很活跃,不要与西里尔蒙古语 http://en.wikipedia.org/wiki/Mongolian_Cyrillic_alphabet)。下图显示了文本方向,为清楚起见添加了英文。

由于此功能并未内置于 Android 中,因此应用程序开发的几乎每个方面都变得极其困难。对于水平 ListView 来说尤其如此,Android 中不支持开箱即用的水平 ListView。网上提供的信息也非常非常少。有许多传统蒙古文的应用程序开发人员,但无论是出于商业原因还是其他原因,他们似乎都没有将其代码开源。

由于这些困难,我想提出一系列 StackOverflow 问题,这些问题可以作为收集与传统蒙古应用程序开发相关的一些更困难的编程问题的答案的中心位置。即使您不懂蒙古语,我们也将不胜感激您帮助审查代码、提出评论和问题、给出答案甚至对问题进行投票。

蒙古文垂直滚动ListView

蒙古文ListView需要满足以下要求:

  • 从左向右水平滚动
  • 触摸事件的工作方式与普通 ListView 相同
  • 与普通 ListView 一样支持自定义布局

还需要支持一切蒙古文文本视图 https://stackoverflow.com/questions/29739720/how-to-make-a-traditional-mongolian-script-textview-in-android将支持:

  • 支持传统蒙古文字体
  • 从上到下垂直显示文本
  • 换行是从左到右。
  • 换行出现在空格处(与英语相同)

下图展示了蒙古文ListView应具备的基本功能:

我的答案如下,但我欢迎其他解决此问题的方法。

本系列其他相关问题:

  • 如何在Android中制作传统蒙古文TextView https://stackoverflow.com/questions/29739720/how-to-make-a-traditional-mongolian-script-textview-in-android
  • 如何在Android中制作传统蒙古文EditText https://stackoverflow.com/questions/25036816/custom-rotated-edittext-view-with-working-selection-cursor-location-etc
  • 更多内容即将推出...(Toast、对话框、菜单)

iOS:

  • 如何在 Swift 中为 iOS 制作垂直文本 UILabel 和 UITextView? https://stackoverflow.com/questions/28544714/how-do-you-make-a-vertical-text-uilabel-and-uitextview-for-ios-in-swift

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 蒙古文渲染引擎示例。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android中如何制作传统蒙古文ListView 的相关文章

随机推荐

  • 当其长度不是所需总长度的倍数时重复向量

    我有一个 1666 行的数据框 我想添加一列 其中包含重复序列1 5与使用cut 进行交叉验证 它看起来像这样 Y x1 x2 Id1 1 15 3 6 1 0 1 1 2 2 2 0 05 3 3 3 0 45 2 8 4 1 85 3
  • 格式化 XmlGregorianCalendar 时区问题

    我需要将 java XmlGregorianCalendar 格式化为 yyMMdd 字符串 我的实现 XMLGregorianCalendar date getDate getting the date if date null Simp
  • 谁能解释一下POJO或POCO的含义和用法[重复]

    这个问题在这里已经有答案了 可能的重复 纯旧 Java 对象 POJO 一词的确切含义是什么 https stackoverflow com questions 3326319 what does the term plain old ja
  • 通过 iOS 应用程序在 Twitter 上分享视频

    是否可以使用 SLRequest 分享视频 我可以使用相同的方式共享图像 SLRequest postRequest SLRequest requestForServiceType SLServiceTypeTwitter requestM
  • 服务器重新启动时显示等待页面

    我有一个服务器并为其创建一个 Web 界面 如果用户按下页面上的重新启动按钮 则用户将被重定向到reboot php他应该看到一个旋转 gif 直到服务器再次可访问并且服务器通过 shell 执行重新启动 如果服务器可以访问 那么我需要重定
  • jQuery-UI 的自动完成显示效果不佳,z-index 问题

    我目前正在我的客户网上商店中实现 jQuery UI 的自动完成功能 问题是 自动完成所在的元素的 z 索引高于自动完成的 z 索引 我尝试手动设置自动完成 z index 但我感觉 jQuery UI 正在覆盖它 事实上我的问题是重复的自
  • Flex Slider 无法在手机上运行

    我在这个页面上使用 flexslider 的网站上工作 http www intensetomatoes co nz story timeline http www intensetomatoes co nz story timeline
  • 如何将空目录添加到 Git 存储库?

    如何将空目录 不包含文件 添加到 Git 存储库 使目录 在存储库中 保持 几乎 空的另一种方法是创建一个 gitignore该目录中的文件包含以下四行 Ignore everything in this directory Except
  • Perforce Dev 分支 - 稀疏分支与私有分支

    我正在寻找一些关于可用于在 Perforce 仓库中创建单独开发分支的方法的优点和缺点的反馈 如果我理解正确的话 有两种方法可以处理这个问题 第一个是创建一个私有分支 它是您正在处理的分支的完整副本 该分支将完全独立 并将您的更改与目标分支
  • 如何替换 PowerPoint (.ppt) 文档中的文本?

    有哪些解决方案 我只知道用 Apache POI 替换 Word doc 文件中的书签的解决方案 是否还可以更改 doc 和 ppt 文档中的图像 布局 文本样式 我考虑替换 Word 和 PowerPoint 文档中的区域以进 行批量处理
  • “无法从构建环境获取 Google 服务文件中的 GOOGLE_APP_ID”错误

    我正在使用下面的指南为我的使用 flutter firebase 的项目设置开发和生产环境https www tengio com blog multiple firebase environments with flutter https
  • 是否可以对不同的服务使用不同的 .env?

    我遇到一种情况 最好有多个 env 文件 每个 env 文件对应 docker compose yml 中的每个服务 有什么方法可以指定要使用的不同文件名吗 这可以在个人服务层面上做到吗 我尝试使用env file不幸的是 这设置了在 Do
  • audioTrack play() 只播放一次

    第一次使用Android的AudioTrack 我创建了一个 AndroidAudioDevice 类 我用这个构造函数初始化它 public AndroidAudioDevice constructor Log i Audio const
  • $_FILES 未定义 PHP 上传表单。无法弄清楚[重复]

    这个问题在这里已经有答案了 可能的重复 尝试在 PHP 中使用 FILE 时出现 未定义索引 错误 https stackoverflow com questions 8727947 getting undefined index erro
  • 健全性检查 SSH 公钥? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我已要求用户提供他们的公共 id rsa pub ssh 密钥 然后将其放入 home theiraccount ssh authorized key
  • 使用 AWK 或 SED 以及以下标签以逗号分隔

    使用 AWK 或 SED 以及下面使用的标签以逗号分隔 BEGIN AccountID BEGIN CallerID BEGIN Billed Account Attributes 1111111 1111111 1111111 END B
  • 如何使用 Talend Open Studio Data Integration 创建属性文件?

    我曾经使用 Talend Open Integration studio 创建作业并从 IDE 运行它或将其导出为可执行 jar 文件 但我并没有广泛使用它 是否可以创建一个包含不同服务器名称和其他变量的外部配置文件 以便在创建 Talen
  • 尝试关闭 Visual Basic 中所有打开的窗体

    我想要它 所以当单击我的按钮时 我退出我的应用程序 我尝试了一个简单的 for 循环 Private Sub CloseAllToolStripMenuItem Click sender As Object e As EventArgs H
  • 更改按钮文本jquery mobile

    我正在使用新的 jquery mobile 1 0 alpha 1 版本来构建移动应用程序 并且我需要能够切换按钮的文本 切换文本工作正常 但一旦执行文本替换 CSS 格式就会被破坏 格式混乱的屏幕截图 http awesomescreen
  • Android中如何制作传统蒙古文ListView

    如何在 Android 应用程序中为垂直蒙古文制作水平滚动的 ListView 背景 Android 对世界上许多语言都有相当好的支持 甚至是阿拉伯语和希伯来语等 RTL 语言 但是 没有内置对自上而下语言的支持 例如传统蒙古语 http