Nativescript 聊天 UI iOS 问题
Nativescript Chat UI iOS Issues
我正在 Nativescript 中创建一个聊天 UI 界面,几乎一切正常,但我在 iOS 中遇到一些我无法弄清楚的问题。 Android 中的所有内容均正常工作。
问题一:
- 当我专注于 TextView 并且键盘打开时,我无法再滚动到聊天顶部。所有内容似乎都向上移动了(即使没有足够有趣地使用 IQKeyboardManager)。
问题二:
- 当我开始在 TextView 中输入时,它立即转移到屏幕底部,隐藏在键盘后面,我看不到我在输入什么。
这是我在 Playground 上创建的演示项目,它显示了这个问题。 Playground Demo Project
下面是显示这两个问题的 GIF。
感谢任何帮助。谢谢!
问题一:
这是因为 IQKeyboardManager 在 ViewController(页面)顶部托管了一个 ScrollView,而 RadListView 有自己的可滚动区域。解决方案是在键盘处于活动状态时调整插图。
下面的代码获取键盘高度,并在首次显示时将其缓存在应用程序对象中。
import * as application from "@nativescript/core/application";
let observer = application.ios.addNotificationObserver(
UIKeyboardDidShowNotification,
notification => {
application.ios.removeNotificationObserver(
observer,
UIKeyboardDidShowNotification
);
(application as any)._keyboardHeight = notification.userInfo.valueForKey(
UIKeyboardFrameBeginUserInfoKey
).CGRectValue.size.height;
}
);
当文本字段获得焦点时调整列表视图的插图
textFieldFocus() {
console.log("Focus on TextField");
(this
.radList as any)._originalContentInset = this.radList.ios.contentInset;
if ((application as any)._keyboardHeight) {
this.radList.ios.contentInset = UIEdgeInsetsMake(
(application as any)._keyboardHeight,
0,
0,
0
);
} else {
setTimeout(() => this.textFieldFocus(), 100);
}
}
问题二:
这是因为文本视图在更新文本时自行布局。防止这种情况可能会保持滚动位置不变。下面的覆盖检查字段是否聚焦并忽略布局调用。
import { TextView } from "@nativescript/core/ui/text-view";
TextView.prototype.requestLayout = function() {
if (
!arguments[0] &&
this.nativeViewProtected &&
this.nativeViewProtected.isFirstResponder
) {
this.nativeViewProtected.setNeedsLayout();
IQKeyboardManager.sharedManager().reloadLayoutIfNeeded();
} else {
View.prototype.requestLayout.call(this);
}
};
以上解决方案对我不起作用。这可能看起来 counter-intuitive,但实际上解决方案是在主布局周围添加一个环绕 ScrollView
(在我的例子中,我的 Page
的直接且唯一的 child)。
举个例子:
<GridLayout rows="*, auto" width="100%" height="100%">
<ScrollView row="0">
<StackLayout orientation="vertical">
<StackLayout *ngFor="let m of messages" [horizontalAlignment]="m.incoming ? 'left' : 'right'">
<Label class="message" [text]="m.message" [class.incoming]="m.incoming" textWrap="true"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
<GridLayout row="1" columns="*, auto" class="input-layout">
<TextView class="text-view" [(ngModel)]="message"></TextView>
<Button column="1" text="Send"></Button>
</GridLayout>
</GridLayout>
会变成:
<ScrollView>
<GridLayout rows="*, auto" width="100%" height="100%">
<ScrollView row="0">
<StackLayout orientation="vertical">
<StackLayout *ngFor="let m of messages" [horizontalAlignment]="m.incoming ? 'left' : 'right'">
<Label class="message" [text]="m.message" [class.incoming]="m.incoming" textWrap="true"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
<GridLayout row="1" columns="*, auto" class="input-layout">
<TextView class="text-view" [(ngModel)]="message"></TextView>
<Button column="1" text="Send"></Button>
</GridLayout>
</GridLayout>
</ScrollView>
所以是的,您将有一个嵌套的 ScrollView
、ListView
或 RadListView
感谢@beeman 和他的 nativescript-chat-ui
样本:https://github.com/beeman/nativescript-chat-ui/blob/master/src/app/messages/containers/message-detail/message-detail.component.html
我正在 Nativescript 中创建一个聊天 UI 界面,几乎一切正常,但我在 iOS 中遇到一些我无法弄清楚的问题。 Android 中的所有内容均正常工作。
问题一:
- 当我专注于 TextView 并且键盘打开时,我无法再滚动到聊天顶部。所有内容似乎都向上移动了(即使没有足够有趣地使用 IQKeyboardManager)。
问题二:
- 当我开始在 TextView 中输入时,它立即转移到屏幕底部,隐藏在键盘后面,我看不到我在输入什么。
这是我在 Playground 上创建的演示项目,它显示了这个问题。 Playground Demo Project
下面是显示这两个问题的 GIF。
感谢任何帮助。谢谢!
问题一:
这是因为 IQKeyboardManager 在 ViewController(页面)顶部托管了一个 ScrollView,而 RadListView 有自己的可滚动区域。解决方案是在键盘处于活动状态时调整插图。
下面的代码获取键盘高度,并在首次显示时将其缓存在应用程序对象中。
import * as application from "@nativescript/core/application";
let observer = application.ios.addNotificationObserver(
UIKeyboardDidShowNotification,
notification => {
application.ios.removeNotificationObserver(
observer,
UIKeyboardDidShowNotification
);
(application as any)._keyboardHeight = notification.userInfo.valueForKey(
UIKeyboardFrameBeginUserInfoKey
).CGRectValue.size.height;
}
);
当文本字段获得焦点时调整列表视图的插图
textFieldFocus() {
console.log("Focus on TextField");
(this
.radList as any)._originalContentInset = this.radList.ios.contentInset;
if ((application as any)._keyboardHeight) {
this.radList.ios.contentInset = UIEdgeInsetsMake(
(application as any)._keyboardHeight,
0,
0,
0
);
} else {
setTimeout(() => this.textFieldFocus(), 100);
}
}
问题二:
这是因为文本视图在更新文本时自行布局。防止这种情况可能会保持滚动位置不变。下面的覆盖检查字段是否聚焦并忽略布局调用。
import { TextView } from "@nativescript/core/ui/text-view";
TextView.prototype.requestLayout = function() {
if (
!arguments[0] &&
this.nativeViewProtected &&
this.nativeViewProtected.isFirstResponder
) {
this.nativeViewProtected.setNeedsLayout();
IQKeyboardManager.sharedManager().reloadLayoutIfNeeded();
} else {
View.prototype.requestLayout.call(this);
}
};
以上解决方案对我不起作用。这可能看起来 counter-intuitive,但实际上解决方案是在主布局周围添加一个环绕 ScrollView
(在我的例子中,我的 Page
的直接且唯一的 child)。
举个例子:
<GridLayout rows="*, auto" width="100%" height="100%">
<ScrollView row="0">
<StackLayout orientation="vertical">
<StackLayout *ngFor="let m of messages" [horizontalAlignment]="m.incoming ? 'left' : 'right'">
<Label class="message" [text]="m.message" [class.incoming]="m.incoming" textWrap="true"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
<GridLayout row="1" columns="*, auto" class="input-layout">
<TextView class="text-view" [(ngModel)]="message"></TextView>
<Button column="1" text="Send"></Button>
</GridLayout>
</GridLayout>
会变成:
<ScrollView>
<GridLayout rows="*, auto" width="100%" height="100%">
<ScrollView row="0">
<StackLayout orientation="vertical">
<StackLayout *ngFor="let m of messages" [horizontalAlignment]="m.incoming ? 'left' : 'right'">
<Label class="message" [text]="m.message" [class.incoming]="m.incoming" textWrap="true"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
<GridLayout row="1" columns="*, auto" class="input-layout">
<TextView class="text-view" [(ngModel)]="message"></TextView>
<Button column="1" text="Send"></Button>
</GridLayout>
</GridLayout>
</ScrollView>
所以是的,您将有一个嵌套的 ScrollView
、ListView
或 RadListView
感谢@beeman 和他的 nativescript-chat-ui
样本:https://github.com/beeman/nativescript-chat-ui/blob/master/src/app/messages/containers/message-detail/message-detail.component.html