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;
}
4ega
źródło

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.

Colin Ramsay
źródło
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>
Alexander Zaytsev
źródło
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!

dahveed707
źródło
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>
syarul
źródło
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ą

Ashok R
źródło
Niezły przykład :)
joey rohan
7

Możesz także rzucić okiem na NativeBase ( http://nativebase.io ). Jest to biblioteka komponentów dla React Native, która zawiera ładną strukturę układu ( http://nativebase.io/docs/v2.0.0/components#anatomy ), w tym nagłówki i stopki.

To trochę jak Bootstrap for Mobile.

Simon Ordish
źródło
1
Nie zawiera układu dla stałej stopki.
svlada
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>
Cherag Verma
źródło
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,
  },
});
shruti garg
źródło
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>
Rajesh
źródło
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
}
Akash Kurian Jose
źródło
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>
saiftyfirst
źródło
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>

iambinodstha
źródło
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>
Manzoor Samad
źródło
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

Joseph Owigo
źródło
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.

Lisa Faye Cook
źródło
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

ab_did96
źródło
2

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

Andresh Singh
źródło
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>`
Aishwarya Shetty
źródło
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ę

DevAelius
źródło