--> -->

skimemo


skimemo - 日記/2019-06-15/NativeScriptのiOS対応時に気をつけること のバックアップ(No.3)


_ NativeScriptのiOS対応時に気をつけること

基本的にはAndroidで開発を行っているのですが、ある程度出来てからiOSで動かしたときに期待通り動かなかった点を中心に、双方のプラットフォームで動かすために気をつけるべき点を五月雨的に書いていきます(随時追記する予定)。

基本的には深く根本原因まで探って対処するというより、「こうしてみたら動いた」的な内容になっていますので、理屈から理解したい方には不向きかも知れません。

_ WebView, HtmlViewの初期高さが1行

まずAndroidとiOSの大きな違いはViewの高さのデフォルト状態です。Androidは基本的に領域一杯に広がって配置されますが、iOSは最小範囲に留まって配置されるようです。このため、WebViewやHtmlViewを画面一杯に表示してスクロールさせたいような場合は、高さを指定する必要があります。

  1
  2
  3
  4
  5
 <GridLayout>
     <ScrollView>
         <WebView height="100%" class="m-10" src="{{ description }}" verticalAlignment="top" />
     </ScrollView>
 </GridLayout> 

この方法は画面内に配置されているViewがWebViewやHtmlView1つだけの場合は有効ですが、上下に他のViewが配置されていると都合が良くありません。何故ならWebView、HtmlViewの部分のみスクロールされてしまい、画面全体のスクロールにならないからです。

対応策は次々項に書きます(無駄に引っ張る(笑))。

_ ページが表示されない

どうやら、<StackLayout>は中にListViewなどの高さが変化するViewを入れるのには不向きで、そういう場合は<GridLayout>を使うと良いようです。

特にRadListViewの時は動きが不可解で、最初上部20%程度しか表示されず、その狭い範囲をスクロールすると徐々に見えるエリアが広がっていきます。こういう場合、外側にGridLayoutを配置すると最初から全体が表示されるようになります。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
<Page class="page"
    xmlns="http://schemas.nativescript.org/tns.xsd"
    xmlns:lv="nativescript-ui-listview"
    navigatingTo="onNavigatingTo">
 
    <StackLayout>
         :
    <lv:RadListView
           :
        <lv:RadListView.itemTemplate>
                     :
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
    </StackLayout>
</Page> 

        ↓

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
<Page class="page"
    xmlns="http://schemas.nativescript.org/tns.xsd"
    xmlns:lv="nativescript-ui-listview"
    navigatingTo="onNavigatingTo">
 
    <GridLayout>
         :
    <lv:RadListView
           :
        <lv:RadListView.itemTemplate>
                     :
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
    </GridLayout>
</Page> 

※ Androidではどちらでも同じように表示されるがiOSでは下でないと期待通り表示されない。

_ ページがスクロールしない

WebViewやHtmlViewは初期配置時に高さが1行分しか確保されません。ところが画面を回転させるとちゃんと全部表示されるようになります[*1]。つまり、描画後に再描画してあげれば良いわけです。

HtmlViewにidを振っておきます。

  1
<HtmlView id="htmlview" class="m-l-2 m-r-2" html="{{ description }}" /> 

ページ表示後、htmlviewを再描画します。

  1
  2
  3
const page = args.object.page;
const htmlview = page.getViewById("htmlview");
htmlview.requestLayout(); 

_ ボタンの高さが低い(ボタンが細くなる)

Androidでは以下のように誤った配置をしてもボタンのCSSを指定してあればそちらが優先されて高さが確保されますが、iOSでは与えられた領域内でのみ高さを確保しようとするようです。

  1
  2
  3
  4
<GridLayout rows="40,5,40,5,40,5,40,5,40" columns="80,*,40" >
                          :
    <Button row="8" colSpan="3" class="btn_search btn btn-primary btn-red btn-rounded-lg btn-active" text="検索" tap="onSearchButtonTap"/>
</GridLayout> 
Everything is expanded.Everything is shortened.
  1
 
.btn_search { margin-top: 24px; }

(GridLayoutで高さ40が指定されているがCSSでmarginが24なのでボタン高さが16しか無い)

この場合、GridLayoutの高さを適切にするか、おまかせにしたい場合はautoにします。

  1
<GridLayout rows="40,5,40,5,40,5,40,5,auto" columns="80,*,40" > 

_ Toastが画面下部に固定されているタブに隠れて見えない

Toastを表示させようとして最初に見つけたnativescript-toastを使っていたのですが、表示位置が画面下部に固定されてしまい、iOSの場合はタブ位置がbottom固定なのでかぶって見えなくなってしまいます。また、このnativescript-toastは表示位置の指定ができません。

というわけで私はnativescript-toastyに乗り換えました。(公式的にはこれ?(nativescript-toasts[*2]))

以下のように、使い勝手はnativescript-toastと同等にし、platformによって位置を自動で変えてくれるようにしています。(ちょっとお行儀悪いかも)

[toast.js]

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
const application = require("tns-core-modules/application");
const Toasty = require("nativescript-toasty");
 
function toast() {
    if (!(this instanceof toast)) {
        return new toast();
    }
}
 
toast.prototype = {
 
    text: "",
    duration: Toasty.ToastDuration.SHORT,
    position: application.android ? Toasty.ToastPosition.BOTTOM : Toasty.ToastPosition.CENTER,
 
    makeText: function makeText(text) {
        this.text = text;
        return this;
    },
 
    show: function show() {
        new Toasty.Toasty(this.text, this.duration, this.position).show();
    },
 
    setDuration: function setDuration(duration) {
        this.duration = "long"==duration.toLowerCase() ? Toasty.ToastDuration.LONG : Toasty.ToastDuration.SHORT;
    },
 
    setPosition: function setPosition(position) {
        if("top"==position.toLowerCase()) this.position = Toasty.ToastPosition.TOP;
        if("center"==position.toLowerCase()) this.position = Toasty.ToastPosition.CENTER;
        if("bottom"==position.toLowerCase()) this.position = Toasty.ToastPosition.BOTTOM;
    },
 
};
global.Toast = new toast(); 

使うとき。

  1
  2
require("toast");
Toast.makeText("メッセージ").show(); 

_ HtmlView, WebViewの見え方が違う(字が小さい、フォントが違う)

未稿。基本的にはHTML内のCSSで制御。

_ ボタンがクリックできない

未稿。

_ ActionBarのBackButtonが表示されない

未稿。

_ モーダルダイアログ(showModal)のNavigationButtonが表示されない

未稿。

_ GridLayout内のStackLayoutは100%の大きさで配置される

未稿。

Category: [NativeScript] - 06:21:16



 


iOS: HtmlView content is cropped when using it inside ScrollView
https://github.com/NativeScript/NativeScript/issues/5926


ただし、さらに他のプラグインが必要なのと、ライセンスがMITじゃないので新たなライセンス表記が必要でちょっと面倒・・・(笑