Kuidas loobuda klaviatuurist koos reageerimisega navigeerimisega rakenduses React Native

Klaviatuuri kuvamine ja sellest keeldumine näib mobiilirakendustes olevat triviaalne asi, kuid selle reageerimine-navigeerimine ja modaalne esitlus koos selle vallandamisega on keeruline. Vähemalt see on minu esialgse oletuse kohaselt. Selle artikli eesmärk on täpsustada, mida ma olen õppinud klaviatuuri käsitsemise kohta ja kuidas vältida teksti sisendiga suheldes täiendavat koputamist. Tänu kõigile teekidele, mis on avatud lähtekoodiga, toimub ka koodide spelunkeerimine. React Native'i versioon, mida ma kirjutise ajal kasutan, on 0.57.5

Sisseehitatud tekstisisestuskomponent

React Native sisaldab hunnikut põhikomponenti, üks neist on TextInput teksti sisestamiseks rakendusse klaviatuuri kaudu.

impordi reakt, {komponent} rakendusest 'reageerima';
impordi {AppRegistry, TextInput} rakendusest 'react-native';
eksport vaikeklass UselessTextInput laiendab komponenti {
  konstruktor (rekvisiidid) {
    super (rekvisiidid);
    this.state = {tekst: 'Kasutu kohahoidja'};
  }
renderdama () {
    tagasi (
       this.setState ({text})}
        value = {this.state.text}
      />
    );
  }
}

See tähendab, et iga kord, kui klõpsame tekstisisestust, ilmub klaviatuur, mis võimaldab meil väärtusi sisestada. Klaviatuuri loobumiseks ekraanil ükskõik kuhu vajutades on hõlpsaks lahenduseks TouchableWithoutFeedback koos klaviatuuriga. See sarnaneb rakenduse UITapGestureRecognizer iOS UIView's ja väljakutse view.endEditing

impordi {Keyboard} saidist „reageeri natiivi”

Keyboard.dismiss ()

Tekstisisestus rakenduse ScrollView sees

Tavaliselt peaksid kerimiskomponendi sees olema mõned tekstisisestused React Native'is, mis on enamasti ScrollView, et käsitleda pikka sisuloendit ja vältida klaviatuuri kasutamist. Kui TextInput asub ScrollView sees, siis käitub klaviatuuri vallandamise viis veidi erinevalt ja sõltub keyboardShouldPersistTaps

Määrab, millal peaks klaviatuur pärast koputust nähtaval olema.

  • „mitte kunagi” (vaikimisi), klaviatuuri üleslülitamise korral klaviatuuri ülaosas koputades fokuseeritud tekstisisestusest välja, klaviatuur loobub. Kui see juhtub, ei saa lapsed kraani kätte.
  • 'alati', klaviatuur ei lahku automaatselt ja kerimisvaade ei kraani, kuid kerimisvaate lapsed saavad kraanid kinni.
  • "käideldud", ei klaviatuur automaatselt lahti, kui kraan oli laste käes (või esivanema kinni püüdnud).

Kunagi režiim peaks olema enamikul juhtudel soovitud käitumine, klõpsates kuskil väljaspool fookustatud tekstisisestust, tuleks klaviatuur ära jätta.

Minu rakenduses on mõned tekstisisestused ja toimingunupp. Stsenaariumi kohaselt sisestavad kasutajad mõned infod ja seejärel vajutavad seda nuppu andmete registreerimiseks. Kunagi režiimis peame vajutama nuppu kaks korda, ühe klaviatuuri loobumiseks ja kaks nupu onPress jaoks. Seega on lahendus alati režiimi kasutamine. Nii saab Button alati esmalt pressisündmuse.

ScrollView hoolib klaviatuurist

Natiivsel RCTScrollView-klassil, mis võimsusel reageerib algsele ScrollView-le, on kood vallandamise režiimi käsitlemiseks

RCT_SET_AND_PRESERVE_OFFSET (setKeyboardDismissMode, keyboardDismissMode, UIScrollViewKeyboardDismissMode)

Valik, mille ta valib, on klaviatuuriDismissMode omadus UIScrollViewKeyboardDismissMode

Klaviatuuri loobumise viis, kui kerimisvaates lohistamist alustatakse.

Nagu näete, on võimalikud režiimid onDrag ja interaktiivsed. Ja natiivne reageerimine paljastab selle kohandamispunkti keyboardShouldPersistTaps kaudu

ükski juhtum Klaviatuuri ei saa ühe tõmbega tagasi lükata.

case onDrag Klahvist loobutakse, kui lohistamine algab.

interaktiivne juhtum Klaviatuur järgib puuteekraani lohistamist ja loobumise tühistamiseks saab seda uuesti ülespoole tõmmata.

ScrollView mooduli sees

Kuid see ei toimi, kui ScrollView asub Modali sees. Modali all pidasin silmas modaalkomponenti reaalajas. Ainus teek, mida ma kasutan, on reaalajas navigeerimine ja see toetab ka täisekraani modaali avamist, kuid nad näevad modaali reageerimisena navigeerimisel välja nagu virna ja on segased, nii et ma pigem ei kasutaks seda. Ma kasutan Modali reaalajas ja see töötab päris hästi.

Nii et kui meil on TextInput ScrollView sees Modalis, siis keyboardShouldPersistTaps ei tööta. Tundub, et Modal on vanem ScrollViewst teadlik, nii et peame iga vanema ScrollView kohta kuulutama keyboardShouldPersistTaps = 'alati'. React Native FlatList ja SectionList kasutavad kapoti all ScrollView, seega peame olema teadlikud kõigist nendest ScrollView komponentidest.

Kiire reageerimine-navigeerimine

Kuna minu rakendus tugineb suuresti reageerimisele-navigeerimisele, on hea, kui tunnete selle komponente sügavalt, nii et hoolitseme selle eest, kus probleem peitub. Olen allpool reakt-navigeerimisstruktuurist natuke kirjutanud.

Nagu kõik traditsioonilised mobiilirakendused, koosneb ka minu rakendus paljudest vahelehenavigaatorites olevatest pinu navigaatoritest. IOS-is tähendab see paljusid UINavigationViewController-i UITabbarControlleri sees. Reakt-navigeerimisel kasutan luua createMaterialTopTabNavigatorit sisemuses createBottomTabNavigator

impordi {createMaterialTopTabNavigator} kaustast „reageeri-navigeerimine”
impordi {createBottomTabNavigator, BottomTabBar} kaustast „react-navigation-tab”

Minu ekraanil kuvatav klaviatuuri ekraan on moodul, mis kuvatakse 2. ekraanilt ühes virnade navigaatoris, nii et uurime kõiki võimalikke ScrollView hierarhia ülespoole. See protsess hõlmab palju koodilugemist ja see on viis, miks ma armastan avatud lähtekoodiga tarkvara.

Alustame kõigepealt createBottomTabNavigatoriga, mis kasutab createTabNavigatorit koos oma TabNavigationView'ga

klass TabNavigationView laiendab React.PureComponent 
eksport vaikimisi createTabNavigator (TabNavigationView);

Vahelehtede navigaatoril on ScreenContaineri all sakkide ribavaade, mida kasutatakse vaate kuvamiseks. EkraanContainer pärineb reaalajas ekraanilt “Selle projekti eesmärk on natiivsete navigatsioonikonteineri komponentide paljastamine reaalajas kasutatavatele”. Allpool saate teada, kuidas vahekaardi navigaator töötab.

renderdama () {
  const {navigeerimine, renderScene, laisk} = this.props;
  const {route} = navigation.state;
  const {laetud} = see.riik
  tagasi (
    
      
        {marsruudid.map ((marsruut, register) => {
          if (laisk &&! laetud. sisaldab (indeks)) {
            // Ärge renderdage ekraani, kui me pole kunagi sellel navigeerinud
            tagasi null;
          
          const isFocused = navigation.state.index === register
          tagasi (
            
              {renderScene ({route})}
            
          );
        })}
      
      {this._renderTabBar ()}
    
  );
}

Vahelehtede riba kuvatakse funktsiooni BrentiTabBar funktsiooni _renderTabBar abil. Koodi vaadates pole tervel vahelehenavigaatoril ScrollView'ga midagi pistmist.

Seega on kahtlustatavate loendisse jäänud ainult createMaterialTopTabNavigator. Kasutan seda rakenduses swipeEnabled: tõsi. Ja vaadates impordi, on ülemise vahelehe navigaator

importige MaterialTopTabBar, {tippige TabBarOptions,} kaustast .. ../vaated/MaterialTopTabBar ';

MaterialTopTabBar on importinud reaalajas-vahekaardi-vaatest

impordi {TabBar} rakendusest 'reageeri-natiiv-vahekaardilt';

millel on ScrollView


  

AtribuutiklaviatuurShouldPersistTaps seati algul alati olekusse, seejärel seati uuesti käitlemisele, et vältida viga, mille tõttu me ei saa ühtegi klahvi vahekaardiribale vajutada, kui klaviatuur on avatud https://github.com/react-native-community/react-native -tab-vaade / väljaanded / 375

Sellel vahekaardiribal pole aga meie probleemiga midagi, sest see on mõeldud ainult vahekaardi riba nuppude jaoks.

Pühkimine rakenduses createMaterialTopTabNavigator

Vaadates veel kord looduMaterialTopTabNavigatorit, näeme importi reakt-natiiv-sakk-vaates rohkem

impordi {TabView, PagerPan} rakendusest 'reageeri-emakeelena-vahekaardilt';

TabView on swipeEnabled sisse lülitatud

tagasi (
  
);

ja see muudab PagerDefaultiks, mis omakorda kasutab iOS-i jaoks PagerScroll

impordi {platvorm} 'reageeri-natiivist';
las Pager;
lüliti (Platform.OS) {
  juhtum "android":
    Pager = nõua ('./ PagerAndroid'). Vaikimisi;
    vaheaeg;
  juhtum 'ios':
    Pager = nõuda ('./ PagerScroll'). Vaikimisi;
    vaheaeg;
  vaikimisi:
    Pager = nõuda ('./ PagerPan'). Vaikimisi;
    vaheaeg;
}
ekspordi vaikeseade;

Nii kasutab PagerScroll ScrollView abil kerimist, et see vastaks materjali stiilile, mida kasutaja saab lehtede vahel kerida, ning sellel on keyboardShouldPersistTaps = “alati”, mis peaks olema õige.

tagasi (
  

Nii ei näe reageerimisel-navigeerimisel miski kahtlane, mis ärgitab mind oma projekti koodi vaatama.

FlatList, SectionList ja ScrollView silumine

Nagu ma selle artikli alguses ütlesin, on juurprobleem selles, et peame kõigi hierarhias vanema ScrollView jaoks kuulutama keyboardShouldPersistTaps. See tähendab, et tasub vaadata kõiki FlatList, SectionList ja ScrollView

Õnneks on react-devtools, mis näitab kõigi reageeritud rakenduses muudetud komponentide puu, ja seda juhendatakse ka reaalajas silumisosas.

Reacti komponendi hierarhia silumiseks võite kasutada Reacti arendajariistade iseseisvat versiooni. Selle kasutamiseks installige react-devtools pakett globaalselt:

npm install -g reageerida-devtools

Nii et pärast otsimist sain teada, et hierarhias on üles seatud sektsioonList, millel peaks olema keyboardShouldPersistTaps = 'alati', kui seda pole.

Koodi põhjalikult uurides sain teada, et modaal käivitatakse sektsioonloendi elemendist. Me juba teame, et modaali käivitamine reaalajas reageerib tähendab seda, et kinnistada see modaal hierarhiasse ja kontrollida selle nähtavust oleku kaudu. Nii et vaade ja komponent on Modal jaotise nimekirjas. Ja teie huvides, kui sukelduda sügavale reaalkoodi reageerimisele, on minu puhul sektsioonloend lihtsalt VirtualizedSectionList, mis on VirtualizedList, mis kasutab ScrollView

Nii et pärast seda, kui kuulutan jaotises KeyShouldPersistTaps = 'alati', on probleem lahendatud. Nüüd saab kasutaja lihtsalt sisestada mõned väärtused tekstisisestusse ja seejärel vajutada üks kord nuppu Esita, et andmeid esitada. Nupp pildistab nüüd kerimisvaate asemel kõigepealt puuteüritusi.

Kuhu siit edasi minna

Lahendus selleks on õnneks lihtne, kuna see hõlmab meie koodi parandamist, ilma et peaksime muutma reageerimise-navigeerimise koodi. Kuid on hea vaadata raamatukogu koodi, et teada saada, mida see teeb, ja jälgida, kust probleem pärineb. Täname, et jälgisite nii pikka uurimist ja loodan, et saate midagi õppida.

Kui teile see postitus meeldib, kaaluge minu muude artiklite ja rakenduste külastamist