Wie kann ich in React Native eine Ansicht über eine andere Ansicht stellen, wobei ein Teil davon außerhalb der Grenzen der Ansicht dahinter liegt?


74

Ich versuche mit React Native ein Layout wie unten zu erstellen.

Geben Sie hier die Bildbeschreibung ein

Wie gebe ich die Position von B relativ zu A an?

Mit iOS Interface Builder und automatischen Einschränkungen kann dies sehr explizit durchgeführt werden und ist ein Kinderspiel. Es ist nicht so offensichtlich, wie man dies mit React Native erreichen könnte.


2
Eine einfache zIndex: 100"schwebende Ansicht" hat für mich in meiner Situation funktioniert.
lsimonetti

Die richtige Kombination aus zIndex:10und einer negativen Marge marginTop:-15sollte Ihnen das bringen, was Sie wollen. Position: 'Absolut' könnte Dinge auf größeren Bildschirmen durcheinander bringen, dies berücksichtigen, möglicherweise vermeiden.
Bobby Axe

Antworten:


85

Fügen Sie der "schwebenden" Ansicht Folgendes hinzu

position: 'absolute'

Möglicherweise müssen Sie auch einen oberen und einen linken Wert für die Positionierung hinzufügen

Siehe dieses Beispiel: https://rnplay.org/apps/OjzcxQ/edit


9
Es ist auch wichtig, dass das in der Hierarchie view Bnachkommt view A, da es momentan keine zIndexUnterstützung gibt .
Zubko

2
Wie würde dies bei verschiedenen Anzeigegrößen und Seitenverhältnissen funktionieren?
Hitmaneidos

@hitmaneidos können Sie unten tun: -15. Dies löst jedoch kein Problem, wenn sich B über zwei Ansichten befindet (stellen Sie sich den Leerraum unten als Ansicht C vor). In diesem Fall muss Ansicht B nach A und C kommen, und da sowohl A als auch C eine variable Höhe haben, kann ich keine Lösung finden, ohne die Höhe jeder Ansicht manuell zu berechnen ...
Klammern

67
Verdammt, diese Verbindung ist tot.
Benutzer

Down-Voting für toten Link, sorry, aber aus diesem Grund verlinken Sie nicht auf die Antwort.
Keith Loughnane

21

Die oben genannten Lösungen haben bei mir nicht funktioniert. Ich habe es gelöst, indem ich eine Ansicht mit der gleichen Hintergrundfarbe wie das übergeordnete Element erstellt und einen negativen Rand hinzugefügt habe, um das Bild nach oben zu verschieben.

<ScrollView style={{ backgroundColor: 'blue' }}>
  <View
    style={{
      width: '95%',
      paddingLeft: '5%',
      marginTop: 80,
      height: 800,
    }}>
    <View style={{ backgroundColor: 'white' }}>

      <Thumbnail square large source={{uri: uri}} style={{ marginTop: -30 }}/>
      <Text>Some Text</Text>
    </View>
  </View>
</ScrollView>

und ich habe das folgende Ergebnis erhalten.

Geben Sie hier die Bildbeschreibung ein


12

Sie können zIndexdamit eine Ansicht über einer anderen platzieren. Es funktioniert wie die CSS-Z-Index-Eigenschaft - Komponenten mit einem größeren zIndexWert werden oben gerendert.

Sie können sich darauf beziehen: Layout Requisiten

Snippet:

    <ScrollView>
          <StatusBar backgroundColor="black" barStyle="light-content" />
          <Image style={styles.headerImage} source={{ uri: "http://www.artwallpaperhi.com/thumbnails/detail/20140814/cityscapes%20buildings%20hong%20kong_www.artwallpaperhi.com_18.jpg" }}>
            <View style={styles.back}>
              <TouchableOpacity>
                <Icons name="arrow-back" size={25} color="#ffffff" />
              </TouchableOpacity>
            </View>
            <Image style={styles.subHeaderImage} borderRadius={55} source={{ uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Albert_Einstein_1947.jpg/220px-Albert_Einstein_1947.jpg" }} />
          </Image>

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: "white"
    },
    headerImage: {
        height: height(150),
        width: deviceWidth
    },
    subHeaderImage: {
        height: 110,
        width: 110,
        marginTop: height(35),
        marginLeft: width(25),
        borderColor: "white",
        borderWidth: 2,
        zIndex: 5
    },

9

Sie können dies verwenden OverlayContainer. Der Trick ist, absolutemit 100%Größe zu verwenden. Überprüfen Sie unten ein Beispiel:

// @flow

import React from 'react'
import { View, StyleSheet } from 'react-native'

type Props = {
  behind: React.Component,
  front: React.Component,
  under: React.Component
}

// Show something on top of other
export default class OverlayContainer extends React.Component<Props> {
  render() {
    const { behind, front, under } = this.props

    return (
      <View style={styles.container}>
        <View style={styles.center}>
          <View style={styles.behind}>
            {behind}
          </View>
          {front}
        </View>
        {under}
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    height: '100%',
    justifyContent: 'center',
  },
  center: {
    width: '100%',
    height: '100%',
    alignItems: 'center',
    justifyContent: 'center',
  },
  behind: {
    alignItems: 'center',
    justifyContent: 'center',
    position: 'absolute',
    left: 0,
    top: 0,
    width: '100%',
    height: '100%'
  }
})

2
Bist du sicher, dass du es gemeint hast height: 100,und nicht height: '100%',?
SSC

Ich erinnere mich nicht einmal daran, hier letztes Jahr einen Kommentar abgegeben zu haben, aber es scheint, dass dies (zumindest) das zweite Mal ist, dass diese Antwort für mich sehr hilfreich ist - nochmals vielen Dank! :-) In meinem Fall ist die frontAnsicht eine Animated.View; Ich musste alignItems: 'center' from styles.center` entfernen , sonst würde es nicht angezeigt.
SSC

7
import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';


export default class App extends Component {
  render() {
    return (
       <View>// you need to wrap the two Views an another View
          <View style={styles.box1}></View>
          <View style={styles.box2}></View>
       </View> 
    );
  }
}

const styles = StyleSheet.create({
  box1:{
    height:100,
    width:100,
    backgroundColor:'red'
  },
  box2:{
    height:100,
    width:100,
    backgroundColor:'green',
    position: 'absolute',
    top:10,
    left:30

  },
});

3

Sie können das react-native-view-overflowPlugin verwenden, um eine Ansicht über eine andere zu platzieren. Es funktioniert wie die CSS-Z-Index-Eigenschaft.

import ViewOverflow from 'react-native-view-overflow';

<ViewOverflow />
    <View style={[styles2.cardBox, { marginTop: 50 }]}>
    <View style={[styles2.cardItem]} >
      <Text style={styles2.cardHeader}>userList</Text>
    </View>
      <View style={[styles2.cardContent]}>
        <Text style={styles2.text}>overflow: "visible"</Text>
      </View>
      <View style={[styles2.cardItemFooter]} >
        <Text style={styles2.cardTextFooter}>...</Text>
      </View>
    </View>
  </ViewOverflow>

const styles2 = StyleSheet.create({
  cardBox: {
    borderLeftWidth: 0,
    borderTopWidth: 0,
    backgroundColor: "transparent",
    borderWidth: 1,
    borderColor: "#d0d0d0",
    width: '94%',
    alignSelf: 'center',
    height: 200,
    position: "relative",
    borderRadius: 15,
    overflow: "visible" // doesn't do anything
  },
  cardContent: {
    textAlign: "right",
    backgroundColor: "transparent",
    marginTop: 15,
    alignSelf: 'flex-end',
    padding: 5,
  },
  cardHeader: {
    color: '#fff',
    fontFamily: 'Vazir',
    fontSize: 12
  },
  cardItem: {
    backgroundColor: "#3c4252",
    borderRadius: 3,
    position: "absolute",
    top: -10,
    right: -5,
    width: 50,
    height: 20,
    paddingRight: 5,
  },
})

3
Vielen Dank, dass Sie zu StackOverflow beigetragen haben. Um dies zu einer besseren Antwort zu machen, formatieren Sie bitte den Codeabschnitt korrekt und fügen Sie eine Erklärung oder einen Link zur Dokumentation für die erforderlichen Methoden hinzu. Sie können auch Code-Snippets erstellen, die über jsFiddle ausgeführt werden können.
Sudheesh Singanamalla

2

Der einfachste Weg, dies zu erreichen, ist eine negative Marge.

const deviceWidth = RN.Dimensions.get('window').width

a: {
  alignItems: 'center',
  backgroundColor: 'blue',
  width: deviceWidth,
},
b: {
  marginTop: -16,
  marginStart: 20,
},

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.