NativeScript / nativescript-angular

Integrating NativeScript with Angular
http://docs.nativescript.org/angular/tutorial/ng-chapter-0
Apache License 2.0
1.21k stars 241 forks source link

Android keyboard overlay. #1277

Open morzyns opened 6 years ago

morzyns commented 6 years ago

Keyboard overlays the inputs on Android. package.json:

"nativescript": {
    "id": "org.nativescript.BTrex",
    "tns-android": {
      "version": "4.0.0"
    },
    "tns-ios": {
      "version": "4.0.1"
    }
  },
  "scripts": {
    "lint": "tslint \"app/**/*.ts\""
  },
  "dependencies": {
    "@angular/animations": "~5.2.0",
    "@angular/common": "~5.2.0",
    "@angular/compiler": "~5.2.0",
    "@angular/core": "~5.2.0",
    "@angular/forms": "~5.2.0",
    "@angular/http": "~5.2.0",
    "@angular/platform-browser": "~5.2.0",
    "@angular/platform-browser-dynamic": "~5.2.0",
    "@angular/router": "~5.2.0",
    "ccxt": "^1.12.137",
    "crypto-js": "^3.1.9-1",
    "email-validator": "^1.0.7",
    "nativescript-angular": "^5.3.0",
    "nativescript-async": "^1.0.2",
    "nativescript-iqkeyboardmanager": "^1.1.0",
    "nativescript-nodeify": "^0.7.0",
    "nativescript-numeric-keyboard": "^3.0.3",
    "nativescript-theme-core": "1.0.4",
    "nativescript-ui-listview": "^3.5.4",
    "nativescript-ui-sidedrawer": "^4.0.0",
    "nativescript-webview-interface": "^1.4.2",
    "qs": "^6.5.1",
    "reflect-metadata": "0.1.10",
    "rxjs": "^5.5.5",
    "rxjs-tslint-rules": "^3.14.0",
    "tns-core-modules": "^4.0.0",
    "tns-platform-declarations": "^3.4.1",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~5.2.0",
    "@ngtools/webpack": "~1.9.4",
    "@types/node": "^9.6.4",
    "babel-traverse": "6.26.0",
    "babel-types": "6.26.0",
    "babylon": "6.18.0",
    "clean-webpack-plugin": "~0.1.19",
    "codelyzer": "3.2.2",
    "copy-webpack-plugin": "~4.3.0",
    "css-loader": "~0.28.7",
    "extract-text-webpack-plugin": "~3.0.2",
    "lazy": "1.0.11",
    "nativescript-dev-sass": "^1.5.0",
    "nativescript-dev-typescript": "0.7.0",
    "nativescript-dev-webpack": "^0.10.1",
    "nativescript-worker-loader": "~0.8.1",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.2.1",
    "sass-loader": "~6.0.6",
    "tslint": "5.8.0",
    "typescript": "~2.7.2",
    "uglifyjs-webpack-plugin": "~1.1.6",
    "webpack": "~3.10.0",
    "webpack-bundle-analyzer": "^2.9.1",
    "webpack-sources": "~1.1.0"
  }

Presentation

   <GridLayout *ngIf="!isBuyTabActive" class="market-trade sell" rows="auto, auto, auto, auto, auto, *" columns="*, auto" row="2">
                                    <Label [text]="'Balance Available:'" col="0" row="1"></Label>
                                    <Label *ngIf="balances" [text]="balances['BTC'].BalanceWithCurrency" col="0" row="2" class="balance-label"></Label>
                                    <TextField col="0" hint="Price (BTC)" [(ngModel)]="rateSell" row="3" keyboardType="number" style.placeholderColor="#ccc" class="std-text-field"
                                    autocorrect="false" autocapitalizationType="none"></TextField>
                                    <TextField col="0" hint="Amount" [(ngModel)]="quantitySell" keyboardType="number" (ngModelChange)="onChange($event)" row="4" style.placeholderColor="#ccc" class="std-text-field"
                                    autocorrect="false" autocapitalizationType="none"></TextField>

                                    <Button text="Ask Price" (tap)="populatePriceAsk()" class="btn btn-function" col="1" row="3" borderRadius="2"></Button>
                                    <Button text="Max" (tap)="getMaxSell()" class="btn btn-function" col="1" row="4" borderRadius="2"></Button>
                                    <StackLayout colSpan="2" row="5" class="button-container">
                                        <Button text="Sell" (tap)="processTransaction()" class="btn sell-button" borderRadius="2"></Button>
                                    </StackLayout>
                                </GridLayout>

bug

I have checked many times removing platforms, upgrading as much as possible. tns --version -> 4.0.0-2018-04-05-11377

tsonevn commented 6 years ago

Hi @morzyns, You should add the GridLayout container inside a ScrollView. For example:

<ScrollView>
<GridLayout *ngIf="!isBuyTabActive" class="market-trade sell" rows="auto, auto, auto, auto, auto, *" columns="*, auto" row="2">
                                    <Label [text]="'Balance Available:'" col="0" row="1"></Label>
                                    <Label *ngIf="balances" [text]="balances['BTC'].BalanceWithCurrency" col="0" row="2" class="balance-label"></Label>
                                    <TextField col="0" hint="Price (BTC)" [(ngModel)]="rateSell" row="3" keyboardType="number" style.placeholderColor="#ccc" class="std-text-field"
                                    autocorrect="false" autocapitalizationType="none"></TextField>
                                    <TextField col="0" hint="Amount" [(ngModel)]="quantitySell" keyboardType="number" (ngModelChange)="onChange($event)" row="4" style.placeholderColor="#ccc" class="std-text-field"
                                    autocorrect="false" autocapitalizationType="none"></TextField>

                                    <Button text="Ask Price" (tap)="populatePriceAsk()" class="btn btn-function" col="1" row="3" borderRadius="2"></Button>
                                    <Button text="Max" (tap)="getMaxSell()" class="btn btn-function" col="1" row="4" borderRadius="2"></Button>
                                    <StackLayout colSpan="2" row="5" class="button-container">
                                        <Button text="Sell" (tap)="processTransaction()" class="btn sell-button" borderRadius="2"></Button>
                                    </StackLayout>
                                </GridLayout>
</ScrollView>

This should resolve the overlay issue for Android. For iOS use nativescript-iqkeyboardmanager plugin.

morzyns commented 6 years ago

Hi @tsonevn, that suggestion doesn't help unfortunately. We are completely stuck with this bug, can't go to production. Already checked as much we could.

Our last try was that (with scrollView), the solution you suggested also didn't solve this issue.

`

<RadSideDrawer tkExampleTitle tkToggleNavButton showOverNavigation="true" class="settings">
    <StackLayout tkDrawerContent>
        <MyDrawer [selectedPage]="'markets'"></MyDrawer>
    </StackLayout>
       <GridLayout class="page page-content market" tkMainContent rows="*" columns="*">
            <ScrollView row="0" column="0">
               <GridLayout class="market-main-tabs" rows="*" columns="*, *" row="0">
                    <Button text="Trade" (tap)="selectMainTab(0)" class="tab-market" [ngClass]="{open: isActive(0)}" col="0" row="1"></Button>
                    <Button text="Open Orders" (tap)="selectMainTab(1)" class="tab-market" [ngClass]="{'open': isActive(1)}" col="1" row="1"></Button>
                </GridLayout>
                <GridLayout #tabContent class="market-main-tabs-content" rows="*" columns="auto" row="1" *ngIf="market">
                    <GridLayout [visible]="isActive(0)" class="market-main-tabs-content" rows="auto, *, *, auto" columns="*" row="1">
                            <GridLayout class="market-info" rows="auto, auto, auto, auto, auto" columns="auto, *, auto, *, *" row="0">
                                <StackLayout colSpan="4" row="0" orientation="horizontal">
                                    <GridLayout rows="*" columns="auto, auto">
                                            <Label [text]="market.MarketName" class="market-name"></Label>
                                            <Label [text]="' / $' +  market.lastDollar" class="market-pair" row="0" col="1"></Label>
                                    </GridLayout>
                                </StackLayout>
                                <StackLayout col="5" row="0" class="span-row" orientation="horizontal" horizontalAlignment="right">
                                    <Label textWrap="true" class="market-offset" [text]="market.Percentage + '%'" [ngClass]="{'market-increments': market.offsetSign, 'market-decrements': !market.offsetSign}" horizontalAlignment="right"></Label>
                                </StackLayout>
                                <Label [text]="'Vol:'" col="0" row="1" class="high-label"></Label>
                                <Label [text]="market.BaseVolume" col="1" row="1"></Label>
                                <Label [text]="'Last:'" col="0" row="2" class="high-label"></Label>
                                <Label [text]="market.Last" col="1" row="2" [ngClass]="{'increments': lastPriceOffset, 'decrements': !lastPriceOffset}"></Label>
                                <Label [text]="'Spread:'" col="0" row="3" class="high-label"></Label>
                                <Label [text]="spread" col="1" row="3"></Label>
                                <Label [text]="'High:'" col="3" row="1" class="high-label"></Label>
                                <Label [text]="market.High" col="4" row="1"></Label>
                                <Label [text]="'Low:'" col="3" row="2" class="high-label"></Label>
                                <Label [text]="market.Low" col="4" row="2"></Label>
                                <Label [text]="'Balance:'" col="3" row="3" class="high-label" [ngClass]="{'gray': !marketBalance}"></Label>
                                <Label *ngIf="marketBalance" [text]="marketBalance" col="4" row="3"></Label>
                                <Label *ngIf="marketBalanceAvailable" [text]="'Available:'" col="3" row="4" class="high-label" [ngClass]="{'gray': !marketBalanceAvailable}"></Label>
                                <Label *ngIf="marketBalanceAvailable" [text]="marketBalanceAvailable" col="4" row="4"></Label>
                            </GridLayout>
                            <GridLayout class="market-chart" rows="*" columns="*" row="1">
                                <Ohlcv [last]="market.Last" [ticker]="market.symbol" *ngIf="market.symbol"></Ohlcv>
                            </GridLayout>
                            <GridLayout row="2" *ngIf="isBuyTabActive" class="market-trade buy" rows="auto, auto, auto, auto, auto, *" columns="*, auto" row="2">
                                <Label [text]="'Balance Available:'" col="0" row="1"></Label>
                                <Label *ngIf="balances" [text]="balances['BTC'].BalanceWithCurrency" col="0" row="2" class="balance-label"></Label>
                                <TextField col="0" style.placeholderColor="#ccc" hint="Price (BTC)" [(ngModel)]="rate" row="3" class="std-text-field"
                                autocorrect="false" autocapitalizationType="none" keyboardType="number"></TextField>
                                <TextField col="0" hint="Amount" [(ngModel)]="quantity" (ngModelChange)="onChange($event)" row="4" style.placeholderColor="#ccc" class="std-text-field"
                                autocorrect="false" autocapitalizationType="none" keyboardType="number"></TextField>

                                <Button text="Bid Price" (tap)="populatePrice()" class="btn btn-function" col="1" row="3" borderRadius="2"></Button>
                                <Button text="Max" (tap)="getMax()" class="btn btn-function" col="1" row="4" borderRadius="2"></Button>
                                <StackLayout colSpan="2" row="5" class="button-container">
                                        <Button text="Buy" colSpan="2" row="5" (tap)="proceedTransaction()" class="btn buy-button" borderRadius="2"></Button>
                                    </StackLayout>
                                    </GridLayout>
                            <GridLayout *ngIf="!isBuyTabActive" class="market-trade sell" rows="auto, auto, auto, auto, auto, *" columns="*, auto" row="2">
                                <Label [text]="'Balance Available:'" col="0" row="1"></Label>
                                <Label *ngIf="balances" [text]="balances['BTC'].BalanceWithCurrency" col="0" row="2" class="balance-label"></Label>
                                <TextField col="0" hint="Price (BTC)" [(ngModel)]="rateSell" row="3" keyboardType="number" style.placeholderColor="#ccc" class="std-text-field"
                                autocorrect="false" autocapitalizationType="none"></TextField>
                                <TextField col="0" hint="Amount" [(ngModel)]="quantitySell" keyboardType="number" (ngModelChange)="onChange($event)" row="4" style.placeholderColor="#ccc" class="std-text-field"
                                autocorrect="false" autocapitalizationType="none"></TextField>

                                <Button text="Ask Price" (tap)="populatePriceAsk()" class="btn btn-function" col="1" row="3" borderRadius="2"></Button>
                                <Button text="Max" (tap)="getMaxSell()" class="btn btn-function" col="1" row="4" borderRadius="2"></Button>
                                <StackLayout colSpan="2" row="5" class="button-container">
                                    <Button text="Sell" (tap)="proceedTransaction()" class="btn sell-button" borderRadius="2"></Button>
                                </StackLayout>
                            </GridLayout>

                            <GridLayout class="market-tabs" rows="auto" columns="*, *" row="3">
                                <StackLayout col="0" row="1"> 
                                    <Button text="BUY" (tap)="selectBuySellTab(true)" class="trade-btn buy" [ngClass]="{open: isBuyTabActive}" borderRadius="3"></Button>
                                </StackLayout>
                                <StackLayout col="1" row="1"> 
                                    <Button text="SELL" (tap)="selectBuySellTab(false)" class="trade-btn sell" borderRadius="3" [ngClass]="{open: !isBuyTabActive}"></Button>
                                </StackLayout>
                            </GridLayout>
                    </GridLayout>

                    <GridLayout *ngIf="isActive(1)" class="market-main-tabs-content" rows="auto, auto" columns="auto" row="2">
                        <GridLayout class="open-orders-header" columns="*,*,*,*">
                            <Label [text]="'Market'" col="0"></Label>
                            <Label [text]="'Remains'" col="1"></Label>
                            <Label [text]="'Price Limit'" col="2"></Label>
                            <Label [text]="'Cancel'" col="3"></Label>
                        </GridLayout>
                        <ListView [items]="watchService.openOrdersSubject | async" row="1" separatorColor="transparent" class="open-orders" (itemTap)="cancelOrder($event.index)">
                            <ng-template let-item="item" let-i="index">
                                <GridLayout class="orders-item" rows="auto" columns="*, *, *, *">
                                        <StackLayout col="0" row="0" class="item" [ngClass]="{'sell-order': item.side === 'sell', 'buy-order': item.side === 'buy'}">
                                            <GridLayout rows="*" columns="auto, auto">
                                                <Label [text]="item.Exchange" row="0" colSpan="2"></Label>
                                            </GridLayout>
                                        </StackLayout>
                                        <StackLayout col="1" row="0" class="item" [ngClass]="{'sell-order': item.side === 'sell', 'buy-order': item.side === 'buy'}">
                                            <Label [text]="item.QuantityRemaining"></Label>
                                        </StackLayout>
                                        <StackLayout col="2" row="0" class="item" [ngClass]="{'sell-order': item.side === 'sell', 'buy-order': item.side === 'buy'}">
                                            <Label [text]="item.Limit" class="market-price"></Label>
                                        </StackLayout>
                                        <StackLayout col="3" row="0" class="item" [ngClass]="{'sell-order': item.side === 'sell', 'buy-order': item.side === 'buy'}">
                                            <GridLayout>
                                                <StackLayout>
                                                    <Image src="res://delete" class="delete-container"></Image>
                                                </StackLayout>
                                            </GridLayout>
                                        </StackLayout>
                                </GridLayout>
                            </ng-template>
                        </ListView>
                    </GridLayout>
            </GridLayout>
            </ScrollView>
        </GridLayout>
</RadSideDrawer>

`

That might be some conflicts with sideDrawer or webView?

bug2

AndroidManifest.xml:


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android" package="__PACKAGE__" android:versionCode="1" android:versionName="1.0">
    <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
    <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="__APILEVEL__" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/LaunchScreenTheme" android:windowSoftInputMode="adjustResize">
            <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.tns.ErrorReportActivity" />
    </application>
</manifest>
tsonevn commented 6 years ago

Hi @morzyns, This issue has been fixed with NativeScript 4.0. Can you confirm that you are reproducing the issue with latest NativeScript? If you are using 3.4, try upgrading the project to 4.0.

{
    "description": "NativeScript Application",
    "license": "SEE LICENSE IN <your-license-filename>",
    "readme": "NativeScript Application",
    "repository": "<fill-your-repository-here>",
    "nativescript": {
        "id": "org.nativescript.testNg"
    },
    "dependencies": {
        "@angular/animations": "~5.2.0",
        "@angular/common": "~5.2.0",
        "@angular/compiler": "~5.2.0",
        "@angular/core": "~5.2.0",
        "@angular/forms": "~5.2.0",
        "@angular/http": "~5.2.0",
        "@angular/platform-browser": "~5.2.0",
        "@angular/platform-browser-dynamic": "~5.2.0",
        "@angular/router": "~5.2.0",
        "nativescript-angular": "~5.3.0",
        "nativescript-theme-core": "~1.0.4",
        "reflect-metadata": "~0.1.8",
        "rxjs": "~5.5.2",
        "tns-core-modules": "~4.0.0",
        "zone.js": "~0.8.2"
    },
    "devDependencies": {
        "nativescript-dev-typescript": "~0.7.0",
        "typescript": "~2.7.2"
    }
}
morzyns commented 6 years ago

tns --version 4.0

jogboms commented 6 years ago

@morzyns Could you add android:windowSoftInputMode="stateHidden|adjustResize" to your root activity within App_Resources?

morzyns commented 6 years ago

hi @jogboms , im using the latest AndroidManifest.xml with suggested changes

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="__PACKAGE__"
    android:versionCode="1"
    android:versionName="1.0">

    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true"/>

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="__APILEVEL__"/>

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name="com.tns.NativeScriptApplication"
        android:allowBackup="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <activity
            android:name="com.tns.NativeScriptActivity"
            android:label="@string/title_activity_kimera"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:theme="@style/LaunchScreenTheme"
            android:windowSoftInputMode="stateHidden | adjustResize">

            <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.tns.ErrorReportActivity"/>
    </application>
</manifest>

Unfortunately the issue still exists. Checked after removing platform android and running tns run android --clean

tsonevn commented 6 years ago

Hi @morzyns, I reused some part of the attached code from your previous comment, however, I am unable to recreate the issue with the keyboard overlay. It would help if you could provide a sample project, which could be used for debugging.

jogboms commented 6 years ago

@morzyns Oh! In that case, i might think it has something to do with

ScrollView
    > GridLayout
    > GridLayout

How about wrapping both GridLayouts with a StackLayout

ScrollView
    > StackLayout
        > GridLayout
        > GridLayout
morzyns commented 6 years ago

Hi again @jogboms & @tsonevn.

After checking everything up step by step it came up, the issue is when the navigation.

Issue is when navigating via angular/router

This caused the issue. this.router.navigate(['/market', {market: this.markets[$event.index].symbol}]); after changing to RouterExtensions it works good.

Thank you for the help. @jogboms Btw. i think you're right that ScrollView should have just one child element.

tsonevn commented 6 years ago

Hi @morzyns, We will check this scenario on our side. Update: @morzyns can you provide sample project, which demonstrates the case with the Angular router and Android keyboard overlay?

jogboms commented 6 years ago

@morzyns That sure is a weird bug to experience. 🤓

morzyns commented 6 years ago

Another use case that caused the bug:

<StackLayout visibility="{{ !loading ? 'visible' : 'collapsed' }}" height="100%" width="100%" orientation="vertical" row="0">
        <web-view (loadFinished)="pageLoaded()" height="100%" width="100%" #wView></web-view>
</StackLayout> 

While using just

<web-view (loadFinished)="pageLoaded()" height="100%" width="100%" #wView></web-view> works fine.. I don't know if it's just element's visibility or webView specific bug.

jogboms commented 6 years ago

@morzyns I believe i've experienced this one before i think i switched the StackLayout to a GridLayout

morzyns commented 6 years ago
<ios>
    <GridLayout visibility="{{ !loading ? 'visible' : 'collapsed' }}">
        <web-view (loadFinished)="pageLoaded()" height="100%" width="100%" #wView></web-view>
    </GridLayout>
    <ActivityIndicator *ngIf="loading" busy="{{true}}" width="100" height="100"></ActivityIndicator>
</ios>
<android>
    <web-view height="100%" width="100%" #wView></web-view>
</android> 

Can't preload web-view without issues on Android. (Issues with keyboard for instance)

just that works <web-view height="100%" width="100%" #wView></web-view>

jibon57 commented 6 years ago

Hello everyone,

I am facing same problem. None of above tricks work for me :(

<GridLayout rows="*">
<WebView row= "0" height="100%" width="100%" #webview id="webview" *ngIf="link" src="{{link}}"></WebView>
</GridLayout>

tns info:

√ Component nativescript has 4.0.1 version and is up to date.
√ Component tns-core-modules has 4.0.0 version and is up to date.
√ Component tns-android has 4.0.1 version and is up to date.

Any other suggestions?

morzyns commented 6 years ago

Still unstable as hell. Sometimes works sometimes not.. - depends on page data loading.

Guys, could you feedback on this? It's serious bug. I can't event downgrade, - this issue exists and have no clue what's caused it..

For now, after 1,5 month WebView == unstable.

kbajjuri commented 6 years ago

Try adding android:windowSoftInputMode="adjustPan" to your App_Resources/AndroidManifest.xml . adjustSize will not work.

jibon57 commented 6 years ago

@tsonevn any work around for this? Using webview in Android became impossible now.

ematechno commented 6 years ago

I have the same issue with Angular on Android.

The issue can be reproduced easily.

I created the project using "Angular Drawer Navigation Template" from: https://github.com/NativeScript/template-drawer-navigation-ng

Then I updated "settings.components.html" as per below:

<GridLayout class="page page-content">
    <ScrollView>
        <StackLayout class="page form p-15">
            <StackLayout class="input-field">                    
                <Label class="label font-weight-bold m-b-5" text="{{'lastname'  }}" textWrap="true"></Label>
                <TextField id="customer-lastname" [(ngModel)]="customer.lastname" class="input"></TextField>
                <Label class="label font-weight-bold m-b-5" text="{{'name'  }}" textWrap="true"></Label>
                <TextField [(ngModel)]="customer.firstname" class="input"></TextField> 
                <Label class="label font-weight-bold m-b-5" text="{{'phone'  }}" textWrap="true"></Label>
                <TextField [(ngModel)]="customer.phone" keyboardType="phone" class="input"></TextField>  
                <Label class="label font-weight-bold m-b-5" text="{{'email'  }}" textWrap="true"></Label>
                <TextField [(ngModel)]="customer.email" keyboardType="email" autocorrect="false" autocapitalizationType="none" class="input"></TextField>
                <Label class="label font-weight-bold m-b-5" text="{{'lastname'  }}" textWrap="true"></Label>
                <TextField id="customer-lastname" [(ngModel)]="customer.lastname" class="input"></TextField>
                <Label class="label font-weight-bold m-b-5" text="{{'name'  }}" textWrap="true"></Label>
                <TextField [(ngModel)]="customer.firstname" class="input"></TextField> 
                <StackLayout class="hr-light"></StackLayout>                                     
                <Label class="label font-weight-bold m-b-5 m-t-20" text="{{'notes'  }}" textWrap="true"></Label>
                <TextView [(ngModel)]="customer.notes" maxLength="130" borderWidth="1" returnKeyType="send" class="input input-border"></TextView>
            </StackLayout>
        </StackLayout>
    </ScrollView>
</GridLayout> 

I tried to update "AndroidManifest.xml" with "android:windowSoftInputMode="adjustResize", but nothing changed!!!

Attach my sample project.

Any suggestion or work-aroud? sample.zip

neil-119 commented 6 years ago

Like the above users, I would love to know a solution for this as well.

tsonevn commented 6 years ago

Hi all, I researched the case again and found a possible solution about this scenario. You can try to set up SOFT_INPUT_ADJUST_RESIZE flag in the project via code behind on page loaded event and to check whether the view will be displayed above the keyboard. For example: TypeScript

import { Component, OnInit } from "@angular/core";
import * as app from "application"
import {Page} from "ui/page"
import { Item } from "./item";
import { ItemService } from "./item.service";
declare var android:any;
@Component({
    selector: "ns-items",
    moduleId: module.id,
    templateUrl: "./items.component.html",
})
export class ItemsComponent implements OnInit {
    items: Item[];

    // This pattern makes use of Angular’s dependency injection implementation to inject an instance of the ItemService service into this class. 
    // Angular knows about this service because it is included in your app’s main NgModule, defined in app.module.ts.
    constructor(private itemService: ItemService, private page:Page) { 
        this.page.on("loaded", (args)=>{
            var window = app.android.startActivity.getWindow();
            window.setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        })
    }

    ngOnInit(): void {
        this.items = this.itemService.getItems();
    }
}
jibon57 commented 6 years ago

Thanks for reply @tsonevn but unfortunately it isn't working...

<WebView id="webview" src="http://m-dg.oreyw.com/"></WebView>

this.page.on("loaded", (args) => {
            var window = app.android.startActivity.getWindow();
            window.setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        })
ematechno commented 6 years ago

@tsonevn - thanks for suggestion but I confirm it doesn't work for me as well.

As suggested on NS community, I tried to set "fitsSystemWindows" to true for "adjustResize" - this works but it has a weird side effect on drawer appearence - all details in below link:

https://discourse.nativescript.org/t/android-keyboard-overlay-tns-4-1-3/6778

tsonevn commented 6 years ago

Hi @jibon57, Make sure that after the changes, you are making a clear project rebuild. Regarding that I would suggest to try the described steps below and to check again if the behaviour will be the same:

  1. remove the platform with tns platform remove android
  2. delete the app from the simulator or device, which you used for debugging 3, rebuild the app with tns run android.

For your convenience, I am attaching the sample project and the video, which demonstrates the behaviour on my side after adding the flag via code-behind. Archive.zip testvideo.zip

@ematechno, if you are facing a problem with the drawer component, please log an issue in the nativescript-ui-feedback repository. While opening the issue, also provide a sample project, which can be used for debugging.

jibon57 commented 6 years ago

@tsonevn thanks again. I have noticed this problem is happening mainly with tns-template-drawer-navigation-ng or tns-template-tab-navigation-ng. Blank one seems work well. Please have a look the attached project.

Archive.zip

ematechno commented 6 years ago

@tsonevn as suggested, I have just opened a new bug in nativescript-ui-feedback repository

https://github.com/telerik/nativescript-ui-feedback/issues/730

tsonevn commented 6 years ago

HI @jibon57, Thank you for the sample project. I tested it on my side, and this seems to be related to the scenario when the RadSideDrawer is used as a root component. Regarding that, I will suggest leaving your comment in the issue logged by @ematechno and attach there your project.

kpinzon commented 6 years ago

window.setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

Is working for me. As well as setting SOFT_INPUT_ADJUST_PAN in code for the page.

I had it set in the manifest as AdjustUnspecified. I noticed that after setting one page to AdjustResize in the page code, as above, it persisted as AdjustResize across the app. Every textfield after hitting the page with the above code would now follow the same keyboard adjust style. I am now setting the keyboard for each page to either AdjustPan or AdjustResize and that seems to work for me. Hopefully this helps someone.

I also had to redo the layout on my page. The AdjustResize was finicky. It would push up bottom navigation if the main grid didn't have a * row. With a * row it pushes everything above the textfield but not the bottom nav. Setting each row's height with a specific height also forced bottom nav to show under textfield, it was ugly. So for me, using a grid, I had to play around with rows, even added a whitespace row with a height, change some to auto, etc.. I don't know why, but for my project I got it at a place I'm happy with. I had to just keep trying diff grid sizes, , auto, etc...but the keyboard is now working well on android. Still confused on why it acts a certain way with AdjustResize depending on how many rows are `` rows or auto rows or have height specified etc, trial and error.

nericode commented 5 years ago

+1

Manbearpixel commented 5 years ago

Hey all, I appreciate all the input everyone has added here in this issue! I've asked this related question and posted an answer for it which sums up details I've so far read between this issue and a few others like it (and linked back to it as a resource).

I hope the solution I've gathered so far works here and for anyone else! I'd also like to note that I think there may be a bug in NativeScript which ends up ignoring the windowSoftInputMode property in AndroidManifest.xml IF the application is suspended and resumed on the same view this issue occurs!

https://stackoverflow.com/questions/53980913/stop-keyboard-overlay-when-interacting-with-textfield-in-a-nativescript-applicat


I'd also like to add that maybe we can get together and provide examples of how we have our layout constructed where it works for us and compile that into the StackOverflow q/a I posted above. This way, we can better understand what structure works best to avoid this as an issue!

ibnYusrat commented 5 years ago

@Manbearpixel The issue here is mainly with people using the SideDrawer.

Manbearpixel commented 5 years ago

@ibnYusrat I use the RadSideDrawer in my project and have resolved the keyboard overlay issue.

Macarthurval commented 5 years ago

For those who are desperate how I, with this method can easily detect if the keyboard is shown or hidden and also its height:

if ( app.android ) {
    var prevHeightDiff = 0
    const group = frameModule.topmost().android.rootViewGroup
    group.getViewTreeObserver().addOnGlobalLayoutListener(new android.view.ViewTreeObserver.OnGlobalLayoutListener({
        onGlobalLayout: function() {

            var r = new android.graphics.Rect();
            group.getWindowVisibleDisplayFrame(r);
            var dm = group.getResources().getDisplayMetrics();
            var heightDiff = group.getBottom() - r.bottom;

            if( heightDiff != prevHeightDiff ){
                prevHeightDiff = heightDiff
                if( heightDiff ){
                    console.log( "KEYBOARD SHOWN!!!" )
                    console.log( "keyboard height: " + heightDiff )
                }else{
                    console.log( "KEYBOARD HIDDEN!!!" )
                }
            }
        }
    }))
}

This works without any additional configuration even with sidedrawer.

Macarthurval commented 5 years ago

Just found the perfect solution that works for me!, in AndroidManifest.xml in application tag, add the property android:windowSoftInputMode="adjustResize", and inside the page when you have the webview add a on page loaded event:

exports.onLoaded = function( args ){
    if ( args.object.android ) {
        args.object.android.setFitsSystemWindows(true);
    }
}

Working perfect with SideDrawer and webview.

oluwaseye commented 5 years ago

I fixed mine by adding the android:windowSoftInputMode="stateAlwaysHidden|adjustResize" to the activity tag in the AndroidManifest.xml

and updating the /vaules/styles.xml by adding a new item tag <item name="android:fitsSystemWindows">true</item>

This also helped with device notch issue by fitting the app in the device

zhiyong-ft commented 5 years ago

@oluwaseye could you specify where to add entries into both xml files? I am having the same issues, so far everything else seems not working. Weird thing is if install app through tns preview, keypad seems to be located perfectly fine.

oluwaseye commented 5 years ago

@zhiyong80 I added mine within the LaunchScreenThemeBase Style <style name="LaunchScreenThemeBase" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:fitsSystemWindows">true</item>

Just in one xml file, the App_Resources/Android/src/main/res/values/styles.xml

rommyarb commented 5 years ago

After adding android:windowSoftInputMode="stateHidden|adjustResize" to the main activity in _/YourProject/app/AppResources/Android/src/main/AndroidManifest.xml , don't forget to remove the platforms directory. Finally, build and run it again.

valera1401 commented 5 years ago

Hi all. Thank you for your suggestions. I've tried everything but unfortunately nothing helped.
'adjustPan' is working but it moves the Action Bar out of the screen. stateAlwaysHidden|adjustResize + android:fitsSystemWindows is working as well but in this case Action Bar looks ugly as described here https://github.com/NativeScript/nativescript-ui-feedback/issues/730#issuecomment-408487871

My application has the Side drawer. And keyboard overlaps text fields only when ScrollView is the root component of the page.