Naprawiono stopkę React Native


128

Próbuję stworzyć natywną aplikację, która wygląda jak istniejąca aplikacja internetowa. Mam stałą stopkę na dole okna. Czy ktoś ma pojęcie, jak można to osiągnąć dzięki React Native?

w istniejącej aplikacji jest to proste:

.footer {
  position: fixed;
  bottom: 0;
}

Odpowiedzi:


167

Mógłbyś to zrobić za pomocą ScrollView . Kontener najwyższego poziomu może być kontenerem elastycznym, wewnątrz którego znajduje się ScrollView u góry i stopka u dołu. Następnie w ScrollView po prostu umieść resztę aplikacji w normalny sposób.


działa świetnie =) thx, właśnie dodane heightdo widoku stopki i wygląda dobrze na 4s i 6
4ega

1
To działa. Ale nie mogłem zrozumieć, dlaczego. Dlaczego to działa?
Aditi,

171

Oto rzeczywisty kod oparty na odpowiedzi Colina Ramsaya:

<View style={{flex: 1}}>
  <ScrollView>main</ScrollView>
  <View><Text>footer</Text></View>
</View>

1
Tak, próbowałem, ale bez fleksa nie zadziałało: D Dzięki za wciśnięcie, aby spróbować ponownie :) A jeśli kliknąłeś na dane wejściowe, chcę wspomnieć o użyciu onContentSizeChange. Więc co zrobiłem, przewinąłem górny widok scrollview w ten sposób: onContentSizeChange = {(width, height) => this.refs.scrollView.scrollTo ({y: this.state.onInputSelectScrollViewPaddingSize})}
Ernestyno

1
to nie działa. Nie rozumiem, dlaczego to zadziała w jakimkolwiek przypadku
Paulo Roberto Rosa

63

Używam stałych stopek dla przycisków w mojej aplikacji. Sposób implementacji stałej stopki wygląda następująco:

<View style={{flex: 1}}>
<View><Text>my text</Text></View>
<View style={{position: 'absolute', left: 0, right: 0, bottom: 0}}><Text>My fixed footer</Text></View>
</View>

A jeśli potrzebujesz stopki, aby przesunąć się w górę, gdy pojawi się klawiatura, możesz na przykład użyć:

const {  DeviceEventEmitter } = React

class MyClass {
  constructor() {
     this.state = {
       btnLocation: 0
     }
  }

  componentWillMount() {
     DeviceEventEmitter.addListener('keyboardWillShow', this.keyboardWillShow.bind(this))
     DeviceEventEmitter.addListener('keyboardWillHide', this.keyboardWillHide.bind(this))
  }

  keyboardWillShow(e) {
    this.setState({btnLocation: e.endCoordinates.height})
  }

  keyboardWillHide(e) {
    this.setState({btnLocation: 0})
  }
}

Następnie użyj {bottom: this.state.btnLocation} w swojej klasie ze stałą stopką. Mam nadzieję, że to pomoże!


2
Ktoś, kto otrzyma „undefined” nie jest obiektem (oceniającym „DeviceEventEmitter.addListener”) ”podczas próby wykonania„ this.setState (…) ”na słuchaczach klawiatury?
John Sardinha

@JohnSardinha Spróbuj import { Keyboard} from 'react-native'; Keyboard.addListener('keyboardWillShow', this.showHandler)zamiast tego.
maxhungry

23

Najpierw otrzymujesz Wymiar, a następnie manipulujesz nim za pomocą stylu elastycznego

var Dimensions = require('Dimensions')
var {width, height} = Dimensions.get('window')

W renderowaniu

<View style={{flex: 1}}>
    <View style={{width: width, height: height - 200}}>main</View>
    <View style={{width: width, height: 200}}>footer</View>
</View>

Inną metodą jest użycie flex

<View style={{flex: 1}}>
    <View style={{flex: .8}}>main</View>
    <View style={{flex: .2}}>footer</View>
</View>

17

@Alexander Dzięki za rozwiązanie

Poniżej znajduje się kod dokładnie tego, czego szukasz

import React, {PropTypes,} from 'react';
import {View, Text, StyleSheet,TouchableHighlight,ScrollView,Image, Component, AppRegistry} from "react-native";

class mainview extends React.Component {
 constructor(props) {
      super(props);

  }

  render() {
    return(
      <View style={styles.mainviewStyle}>
        <ContainerView/>
          <View style={styles.footer}>
          <TouchableHighlight style={styles.bottomButtons}>
              <Text style={styles.footerText}>A</Text>
          </TouchableHighlight>
          <TouchableHighlight style={styles.bottomButtons}>
              <Text style={styles.footerText}>B</Text>
          </TouchableHighlight>
          </View>
      </View>
    );
  }
}

class ContainerView extends React.Component {
constructor(props) {
      super(props);
}

render() {
    return(
      <ScrollView style = {styles.scrollViewStyle}>
          <View>
            <Text style={styles.textStyle}> Example for ScrollView and Fixed Footer</Text>
          </View>
      </ScrollView>
    );
  }
}

var styles = StyleSheet.create({
  mainviewStyle: {
  flex: 1,
  flexDirection: 'column',
},
footer: {
  position: 'absolute',
  flex:0.1,
  left: 0,
  right: 0,
  bottom: -10,
  backgroundColor:'green',
  flexDirection:'row',
  height:80,
  alignItems:'center',
},
bottomButtons: {
  alignItems:'center',
  justifyContent: 'center',
  flex:1,
},
footerText: {
  color:'white',
  fontWeight:'bold',
  alignItems:'center',
  fontSize:18,
},
textStyle: {
  alignSelf: 'center',
  color: 'orange'
},
scrollViewStyle: {
  borderWidth: 2,
  borderColor: 'blue'
}
});

AppRegistry.registerComponent('TRYAPP', () => mainview) //Entry Point    and Root Component of The App

Poniżej znajduje się zrzut ekranu

ScrollView ze stałą stopką


Niezły przykład :)
joey rohan


7

Proste rzeczy tutaj:

O ile nie potrzebujesz ScrollView do tego podejścia, możesz skorzystać z poniższego kodu, aby osiągnąć coś takiego:

Coś takiego

<View style={{flex: 1, backgroundColor:'grey'}}>
    <View style={{flex: 1, backgroundColor: 'red'}} />
    <View style={{height: 100, backgroundColor: 'green'}} />
</View>

7

Poniżej znajduje się kod do ustawiania stopki i elementów powyżej.

import React, { Component } from 'react';
import { StyleSheet, View, Text, ScrollView } from 'react-native';
export default class App extends Component {
    render() {
      return (
      <View style={styles.containerMain}>
        <ScrollView>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
          <Text> Main Content Here</Text>
        </ScrollView>
        <View style={styles.bottomView}>
          <Text style={styles.textStyle}>Bottom View</Text>
        </View>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  containerMain: {
    flex: 1,
    alignItems: 'center',
  },
  bottomView: {
    width: '100%',
    height: 50,
    backgroundColor: '#EE5407',
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute',
    bottom: 0,
  },
  textStyle: {
    color: '#fff',
    fontSize: 18,
  },
});

6

Sposób, w jaki to zrobiłem, polegał na tym, że miałem widok (nazwijmy to P) z flexem 1, a następnie wewnątrz tego widoku miały 2 dodatkowe widoki (C1 i C2) odpowiednio z flexem 0,9 i 0,1 (możesz zmienić wysokości flex na wymagane wartości) . Następnie wewnątrz C1 mają widok przewijania. To zadziałało idealnie dla mnie. Przykład poniżej.

<View style={{flex: 1}}>
    <View style={{flex: 0.9}}>
        <ScrollView>
            <Text style={{marginBottom: 500}}>scrollable section</Text>
        </ScrollView>
    </View>
    <View style={{flex: 0.1}}>
        <Text>fixed footer</Text>
    </View>
</View>

Dodając do tego, lewy, prawy i dolny styl o wartości 0 muszą być dostarczone, aby działał.
IVI

5

Coś podobnego można by osiągnąć w reakcji native speakera position: absolute

let footerStyle = {
  position: 'absolute',
  bottom: 0,
}

Jest jednak kilka rzeczy, o których należy pamiętać.

  1. absolute ustawia element względem jego rodzica.
  2. Konieczne może być ręczne ustawienie szerokości i wysokości elementu.
  3. Szerokość i wysokość zmienią się wraz ze zmianą orientacji. To musi być zarządzane ręcznie

Praktyczna definicja stylu wyglądałaby mniej więcej tak:

import { Dimensions } from 'react-native';

var screenWidth = Dimensions.get('window').width; //full screen width

let footerStyle = {
  position: 'absolute',
  bottom: 0,
  width: screenWidth,
  height: 60
}

5

Najprostszym rozwiązaniem okazało się użycie fleksa.

<View style={{flex:1, 
    justifyContent: 'space-around', 
    alignItems: 'center',
    flexDirection: 'row',}}>

  <View style={{flex:8}}>
    //Main Activity
  </View>
  <View style={{flex:1}}>
    //Footer
  </View>

 </View>

4

Kiedy flex jest liczbą dodatnią, sprawia, że ​​komponent jest elastyczny i będzie miał rozmiar proporcjonalny do jego wartości flex. Tak więc komponent z flex ustawionym na 2 zajmie dwa razy więcej miejsca niż komponent z flex ustawionym na 1.

   <View style={{flex: 1}>
            
     <ScrollView>
        //your scroll able content will be placed above your fixed footer content. 
        //when your content will grow bigger and bigger it will hide behind 
        //footer content. 
     </ScrollView>

     <View style={styles.footerContainer}>
        //your fixed footer content will sit fixed below your screen 
     </View>

</View>


1
Proszę rozważyć dodanie wyjaśnienia do swojej odpowiedzi.
HMD

3

Najlepszym sposobem jest użycie właściwości justifyContent

<View style={{flexDirection:'column',justifyContent:'flex-end'}}>
     <View>
        <Text>fixed footer</Text>
    </View>
</View>

jeśli masz wiele elementów widoku na ekranie, możesz użyć

<View style={{flexDirection:'column',justifyContent:'space-between'}}>
     <View>
        <Text>view 1</Text>
    </View>
    <View>
        <Text>view 2</Text>
    </View>
    <View>
        <Text>fixed footer</Text>
    </View>
</View>

3
import {Dimensions} from 'react-native'

const WIDTH = Dimensions.get('window').width;
const HEIGHT = Dimensions.get('window').height;

następnie napisz te style

 position: 'absolute',
 top: HEIGHT-80,
 left: 0,
 right: 0,

działał jak urok


2

W przypadku problemów z Androidem:

w app / src / AndroidManifest.xml zmień windowSoftInputMode na następujący.

<activity
   android:windowSoftInputMode="stateAlwaysHidden|adjustPan">

Nie miałem z tym absolutnie żadnych problemów w iOS, korzystając z React-Native i KeyboardAwareScroll. Miałem zaimplementować mnóstwo kodu, aby to rozgryźć, dopóki ktoś nie dał mi tego rozwiązania. Działał doskonale.


2

jeśli po prostu używasz reakcji natywnej, aby móc użyć następującego kodu

<View style={{flex:1}}>

{/* Your Main Content*/}
<View style={{flex:3}}>

<ScrollView>
   {/* Your List View ,etc */}
</ScrollView>

</View>

{/* Your Footer */}
<View style={{flex:1}}>
   {/*Elements*/}
</View>


 </View>

możesz również użyć https://docs.nativebase.io/ w swoim macierzystym projekcie React, a następnie zrobić coś takiego

<Container>

{/*Your Main Content*/}
<Content>

<ScrollView>
   {/* Your List View ,etc */}
</ScrollView>

</Content>

{/*Your Footer*/}
<Footer>
   {/*Elements*/}
</Footer>

</Container>

React_Native

NativeBase.io


2

Ustaw android: windowSoftInputMode = "adjustPan" w swoim pliku manifestu i będzie działać zgodnie z oczekiwaniami.


1

Myślę, że najlepiej i najłatwiej będzie jak poniżej, po prostu umieść resztę widoku w treści i stopce w osobnym widoku.

`<Container>
   <Content>
     <View>
      Ur contents
    </View>
  </Content>
  <View>
  Footer
  </View>
</Container>`

lub możesz użyć stopki z native-base

`<Container>
  <Content>
    <View>
Ur contents
    </View>
  </Content>
<Footer>
Footer
</Footer>
</Container>`

1

Sugestia 1

=> Treść ze stałą stopką

<View style={{ flex: 1, backgroundColor: 'gray' }}>

        <View style={{ flex: 9, backgroundColor: 'gray',alignItems: 'center', justifyContent: 'center',  }}>
          <Text style={{color:'white'}}>...Header or Body</Text>
        </View>


        <View style={{ flex: 1, backgroundColor: 'yellow', alignItems: 'center', justifyContent: 'center', }}>
          <Text>...Footer</Text>
        </View>

</View>

Obraz demonstracyjny

Edytuj 2

=> Body & Fixed footer with tabs

<View style={{ flex: 1, backgroundColor: 'gray' }}>

        <View style={{ flex: 9, backgroundColor: 'gray', alignItems: 'center', justifyContent: 'center', }}>
          <Text style={{ color: 'white' }}>...Header or Body</Text>
        </View>


        <View style={{ flex: 1, backgroundColor: 'yellow', alignItems: 'center', justifyContent: 'center', }}>
          <View style={{ flex: 1, flexDirection: 'row' }}>
            <TouchableOpacity style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white' }}>
              <View>
                <Text>
                  ...Home
              </Text>
              </View>
            </TouchableOpacity>
            <TouchableOpacity style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white' }}>
              <View>
                <Text>
                  ...Settings
              </Text>
              </View>
            </TouchableOpacity>
          </View>
        </View>
</View>

wprowadź opis obrazu tutaj

Uwagi

import {TouchableOpacity} in 'react-native'

Zalety

Możemy korzystać z tej prostej stopki bez reagowania na dolną nawigację

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.