如何为旧版 Android API 实现 TextView 行间距方法?

Posted

技术标签:

【中文标题】如何为旧版 Android API 实现 TextView 行间距方法?【英文标题】:How to implement TextView line spacing methods for older Android API? 【发布时间】:2015-12-09 08:41:17 【问题描述】:

之前,我在 *** 上问了一个标题为“How to paginate text in android”的问题,得到了一个很好的答案,对我帮助很大。现在我需要将代码移植到较旧的 Android API 上,以防万一,Android API 版本 8,这样我就可以在几乎所有 Android 设备上运行我的应用程序,从 Android 2.2 开始。

我遇到的问题是答案中使用的某些方法仅在Android API 16+中可用。

        mPagination = new Pagination(mText,
                mTextView.getWidth(),
                mTextView.getHeight(),
                mTextView.getPaint(),
                mTextView.getLineSpacingMultiplier(),
                mTextView.getLineSpacingExtra(),
                mTextView.getIncludeFontPadding());

所以,我至少要实现这些方法:

                TextView.getLineSpacingMultiplier()
                TextView.getLineSpacingExtra()
                TextView.getIncludeFontPadding()

第二个好像已经被here描述为:

mTextView.getPaint().getFontSpacing()
* mTextView.getLineSpacingMultiplier() + mTextView.getLineSpacingExtra()

但是我不知道另外两个在2.2中是否相关,如果是,如何在Android API版本8中实现。有一些提示here,使用Android的源代码TextView我无法完全理解。

【问题讨论】:

见androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/…和androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/…和androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/… @pskink 跟踪这些私有字段的变化源并不容易,所以我只是将它们替换为默认值:1.0f0.0ftrue 以使其正常工作。但我不知道可能的副作用。 @pskink 这些方法返回私有字段。复制这些字段的默认值很容易,但是通过代码跟踪这些字段的更改,并复制根据配置更改这些字段的完全相同的行为并不容易,至少对我来说是这样。例如,如果是attr==com.android.internal.R.styleable.TextView_lineSpacingMultiplier,那么mSpacingMult = a.getFloat(attr, mSpacingMult) 依赖于attra 哪个a=context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes),并且这种依赖关系还在继续。 @Onik 抱歉,感谢您关注我的问题。 :-/ 我想出了如何(部分)通过使用默认值来解决问题,并忽略其余代码!我想问另一个关于你的解决方案的问题,关于我在那里遇到的 RTL 问题。 @Ho1 好的。如果您找到了解决方案,您可能希望发布您自己问题的答案,或者,如果它不是解决方案,只是解决问题的方法,请编辑发布新结果的问题。关于 RTL 问题,您也可能会提出一个新问题以获得更好的解决方案...而不是注释 here 【参考方案1】:

如果我们查看TextView's 来源,我们可以看到以下内容。

Android 5.0:

private float mSpacingMult = 1.0f;
private float mSpacingAdd = 0.0f;
...
private boolean mIncludePad = true;

Android 2.0:

private float mSpacingMult = 1;
private float mSpacingAdd = 0;
...
private boolean mIncludePad = true;

所以默认值是相等的。

话虽如此,您可以将Pagination's 构造函数与适用于API 8+ 的默认值一起使用:

new Pagination(mText,
            mTextView.getWidth(),
            mTextView.getHeight(),
            mTextView.getPaint(),
            1.0f, 0.0f, true);

如果您让用户更改/设置(通过设置菜单)这些参数,同样无需使用getters。您只需使用TextView's setters 之一设置参数的新值,并将相同的值传递给Pagination's 构造函数。例如,

new Pagination(mText,
            mTextView.getWidth(),
            mTextView.getHeight(),
            mTextView.getPaint(),
            newValueOfSpacingMultiplier,
            newValueOfSpacingExtra,
            newValueOfIncludeFontPadding);

编辑

我想说的是,没有必要“在 Android API 版本 8 中实现它们”。一旦设置参数在TextView's 生命周期内永远不会改变。你可以通过一个简单的测试来检查它。只需在设置任何文本之前(例如,在 sample code 的 onCreate() 中)和之后(在 onGlobalLayout() 中,在 mPagination 初始化之后或在 update() 方法中)查看它们的值。

TextView 的所有参数传递给Pagination's 构造函数的想法是在TextViewPagination 的引擎盖下使用Layout 类的相同配置实例。因此,与其将参数传递给先前使用gettersTextView 检索的Pagination's 构造函数,您可以通过将您想要的任何值传递给Pagination 并将相同的值设置为@ 来实现相同配置的Layout 987654352@ 和正确的 settersAPI version 8 中已经遇到。

【讨论】:

@Ho1 但是,从 "...通过代码跟踪这些字段的更改,并复制更改这些字段的完全相同的行为..." 我似乎就像您认为这些参数在TextView 内的文本处理过程中发生变化一样。我对吗?因为我在源代码中没有注意到类似的东西,所以在测试它时。即,如果我们在 TextView 初始化之后立即查看这 3 个参数,然后在 onGlobalLayout()(视图已经用文本绘制的地方,包括跨区)查看,参数的值是一样。 @Ho1 所以,总而言之,我不必担心“将代码移植到旧的Android API”,只需按照答案使用它们即可。 @Ho1 继续编辑答案,希望能澄清我对使用Pagination 类的想法。真的有兴趣听听您的意见或怀疑吗? :)

以上是关于如何为旧版 Android API 实现 TextView 行间距方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Android 测试生成缩放/捏合手势

如何为小于 24 的 API 添加 Android 网络安全配置

如何为 android 制作更长的 facebook Graph API 会话

如何为个人 android 项目获取 OpenStreetMaps 或 OpenTilesMaps API?

如何为 API 级别 < 23 的项目设置重力

如何为我的 Android 应用获取 Google Places API 密钥