Nativescript 聊天 UI iOS 问题

Posted

技术标签:

【中文标题】Nativescript 聊天 UI iOS 问题【英文标题】:Nativescript Chat UI iOS Issues 【发布时间】:2020-08-31 06:04:39 【问题描述】:

我正在 Nativescript 中创建一个聊天 UI 界面,我几乎可以正常工作,但我在 ios 中遇到了一些我无法弄清楚的问题。 android 中的一切都正常运行。

问题一:

当我专注于 TextView 并且键盘打开时,我无法再滚动到聊天顶部。所有内容似乎都在上移(即使没有足够有趣地使用IQKeyboardManager)。

问题 2:

当我开始在 TextView 中输入时,它会立即移动到屏幕底部,隐藏在键盘后面,我看不到我正在输入的内容。

这是我在 Playground 上创建的一个演示项目,它显示了这个问题。 Playground Demo Project

下面是显示这两个问题的 GIF。

感谢任何帮助。谢谢!

【问题讨论】:

IQKeyboardManager 将您的整个视图包装在 ScrollView 中,因此您的 TextView 可以位于顶部/可见,ListView 位于它自己的容器上,因此它不完全可见。您可能需要考虑至少在 iOS 上使用键盘工具栏插件。 我确实在本地项目中使用了 IQKeyboardManager,但我不知道如何将它添加到 Playground。我添加了 NPM 包,但似乎没有什么不同(至少在 Playground 中)。在本地,当我使用 IQKeyboardManager 时,错误发生了一些变化。我可以输入而不会消失,但是当我按下发送时也会发生同样的事情。 【参考方案1】:

问题一:

这是因为 IQKeyboardManager 在 ViewController (Page) 之上托管了一个 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);
        
    

问题 2:

这是因为文本视图会在文本更新时自行布局。防止这种情况可能会保持滚动位置不变。下面的覆盖检查字段是否获得焦点并忽略布局调用。

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);
    
;

Updated Playground

【讨论】:

【参考方案2】:

上述解决方案对我不起作用。这可能看起来违反直觉,但实际上解决方案是在主布局周围添加一个包装 ScrollView(在我的情况下,是我的 Page 的直接和唯一的孩子)。

举个例子:

<GridLayout rows="*, auto"  >
    <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"  >
        <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>

所以是的,您将有一个嵌套的 ScrollViewListViewRadListView ?

向@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 问题的主要内容,如果未能解决你的问题,请参考以下文章

Nativescript iOS UIColor

如何使用 nativeScript 制作聊天应用程序? [关闭]

Nativescript-vue:如何构建聊天模板

[翻译]Nativescript 中 Web 视图与 Android/IOS 的双向通信

风味“nativescript-ui-listview”具有未知维度“nativescript-ui-listview”

NativeScript 遇到致命错误:Uncaught ReferenceError: __UI_USE_EXTERNAL_RENDERER__ is not defined