我正在构建一个NativeScript应用程序,它在ListView
中显示文本行。每行(现在)有几个Label
字段,一行显示可选行标签,另一行显示文本。我希望字体大小能够根据行的实际宽度自动缩放。我很难让它正常工作。我有三个主要问题,如下所述。这是我到目前为止所做的:
行布局:
<GridLayout columns="*,25">
<Label #text [text]="row.full.join(' ')" col="0" class="pointed tikkuntext"></Label>
<Label #label col="1" class="tikkunlabel" *ngIf="row.label">
<FormattedString>
<Span #chapter *ngIf="row.label.chapter" [text]="row.label.chapter + ' '" fontSize="11" fontAtttributes="Bold"></Span>
<Span #verse [text]="row.label.verse.join(',')"></Span>
</FormattedString>
</Label>
</GridLayout>
这封装在每行的自定义组件中:
import { Component, ElementRef, Input, AfterViewInit, ViewChild } from '@angular/core';
import { Page } from "ui/page";
import { Label } from "ui/label";
import { Span } from "text/span";
@Component({
moduleId: module.id,
selector: "tikkun-row",
styleUrls: ["tikkun-row.css"],
templateUrl: "tikkun-row.component.html"
})
export class TikkunRow implements AfterViewInit {
@Input() row: any;
@ViewChild("text") textField: ElementRef;
@ViewChild("label") labelField: ElementRef;
@ViewChild("chapter") chapterSpan: ElementRef;
constructor(private page: Page) {}
ngAfterViewInit() {
let width = this.page.frame.getActualSize().width;
width /= 375; // magic number!
if (width > 0) {
let textSize = 14 * width; // more magic numbers!
let verseSize = 9 * width;
let chapterSize = 11 * width;
let textField = <Label>this.textField.nativeElement;
textField.style.fontSize = textSize;
if (this.labelField) {
let labelField = <Label>this.labelField.nativeElement;
labelField.style.fontSize = verseSize;
if (this.chapterSpan) {
let span = <Span>this.chapterSpan.nativeElement
span.fontSize = chapterSize;
}
}
}
}
}
这是ngAfterViewInit()
方法,我需要一些帮助。
问题1
我的第一个问题是文本缩放并不总是适用于Android中列表的第一行:
这似乎是断断续续的;每隔一段时间第一行就会正确显示,但大部分时间都如上所示。我无法弄清楚它的模式。奇怪的是,如果我每次调用ngAfterViewInit()
时都记录宽度,我会在iOS中获得一个控制台输出行,在Android中获得八个输出行(其中第一个是0,其他是相同的正值)。尽管列表有七行!
编辑我已经设法通过修改我探测宽度的方式来消除这个问题(但并不完全)。我没有对getActualSize()
进行一次性调用,而是在定时循环中进行。以下是相关的代码更改:
ngAfterViewInit() {
let width = this.page.frame.getActualSize().width;
let wait = () => {
if (width > 0) {
// the same stuff as before
} else {
width = this.page.frame.getActualSize().width;
setTimeout(wait, 10);
}
};
wait();
}
随着这种变化,间歇性缺乏字体缩放几乎完全消失了。然而,一旦罕见,它仍然出现。也许很重要,当它确实出现时并不总是在列表的第一行。它并不总是整排;有时它只是右侧标签。也许这更像是一个渲染问题?
问题2
在iOS上,每行的两个<Label>
元素在文本基线上垂直对齐,如下所示:
在Android上,我无法做到这一点。上面第一张图片中的内容是使用vertical-align: center
的效果,这是我能得到的最接近的效果。遗憾的是,NativeScript仅支持top
,center
,bottom
和stretch
,其中任何一个都不正常。有没有办法(可能通过降低到本机)强制Android中GridLayout
行的基线对齐?
问题3
似乎ngAfterViewInit()
不是覆盖的正确生命周期方法。它在开始时被调用(一次用于iOS,每行一次[+1额外!]用于Android),但如果我在iOS或Android中更改横向和纵向之间的设备方向,则不会调用它。我已经尝试了所有Angular lifecycle hooks,似乎没有任何工作正常。有没有办法检测行的实际宽度何时发生变化,以便更新文本(和标签)大小?在某个地方我可以订阅一些有用的事件吗?