2015-05-12 8 views
55

Ist es möglich, die Größe (Breite und Höhe) einer bestimmten Ansicht zu erhalten? Zum Beispiel habe ich eine Ansicht, die den Fortschritt:Get Größe einer Ansicht in React Native

<View ref='progressBar' style={{backgroundColor:'red',flex:this.state.progress}} /> 

Ich brauche die tatsächliche Breite der Ansicht, zu wissen, andere Ansichten richtig auszurichten. Ist das möglich?

Antwort

121

Ab React Native 0.4.2 haben View-Komponenten eine onLayout prop. Übergeben Sie eine Funktion, die ein Ereignisobjekt verwendet. Die nativeEvent der Veranstaltung enthält das Layout der Ansicht.

<View onLayout={(event) => { 
    var {x, y, width, height} = event.nativeEvent.layout; 
}} /> 

Der onLayout Handler wird auch aufgerufen werden, wenn die Ansicht geändert wird.

Der Hauptvorbehalt ist, dass der Handler onLayout zum ersten Mal aufgerufen wird, nachdem Ihre Komponente gemountet wurde. Daher sollten Sie Ihre Benutzeroberfläche ausblenden, bis Sie Ihr Layout berechnet haben.

+1

Das Problem dieses Ansatzes ist, wenn Gerät rotiert/Ansicht Größe ändert, bekomme ich onlayout nicht erneut aufgerufen. – Matthew

+2

onLayout wird aufgerufen, wenn sich der Rahmen der Ansicht ändert. Vielleicht verändert Ihre Ansicht nicht ihre Größe oder Position bei Rotation. Sehen Sie sich das onLayout-Beispiel im UIExplorer an, in dem onLayout bei der Rotation aufgerufen wird. – ide

+2

Angenommen, ich möchte eine "Ansicht" abhängig von den Abmessungen unterschiedlich anzeigen. Ich verstehe nicht, wie ich mit der OnLayout-Funktion der View ändern kann, wie ich die View anzeigen kann. Führt das nicht zu einer Endlosschleife? –

8

Vielleicht können Sie measure verwenden:

measureProgressBar() { 
    this.refs.welcome.measure(this.logProgressBarLayout); 
}, 

logProgressBarLayout(ox, oy, width, height, px, py) { 
    console.log("ox: " + ox); 
    console.log("oy: " + oy); 
    console.log("width: " + width); 
    console.log("height: " + height); 
    console.log("px: " + px); 
    console.log("py: " + py); 
} 
+0

Für das Leben von mir kann ich nicht herausfinden, wie man 'NativeMethodsMixin' richtig verwendet. Egal was ich tue, "measure" ist immer undefiniert. Irgendwelche Zeiger? – chandlervdw

+1

Sie müssen 'NativeMethodsMixin' nicht verwenden, die Funktion ist nur für einige Elemente verfügbar.Zum Beispiel hat "TouchableWithFeedback" die Messfunktion, aber ein reguläres 'Touchable' nicht. Versuchen Sie, den von Ihnen verwendeten 'View'-Typ zu ändern, ermitteln Sie den Verweis und prüfen Sie, ob das measure-Element verfügbar ist. Ich bin auch darüber gestolpert. – JensDebergh

43

Sie direkt den Dimensions Modul verwenden können und Ihre Ansichten Größen ber. Eigentlich geben Dimensions Ihnen die Hauptfenstergrößen.

import Dimensions from 'Dimensions'; 

Dimensions.get('window').height; 
Dimensions.get('window').width; 

Ich hoffe, Ihnen zu helfen!

+0

Das ist viel einfacher ... danke! – SkinnyG33k

+0

Das ist, was ich suche. Vielen Dank! – Matthew

+1

Gah, warum ist das nicht deutlicher dokumentiert? Ich habe 'width' und 'height' anstelle von 'window', 'width' usw. versucht. – Ricky

6

Das ist das einzige, was für mich gearbeitet:

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

export default class Comp extends Component { 

    find_dimesions(layout){ 
    const {x, y, width, height} = layout; 
    console.warn(x); 
    console.warn(y); 
    console.warn(width); 
    console.warn(height); 
    } 
    render() { 
    return (
     <View onLayout={(event) => { this.find_dimesions(event.nativeEvent.layout) }} style={styles.container}> 
     <Text style={styles.welcome}> 
      Welcome to React Native! 
     </Text> 
     <Text style={styles.instructions}> 
      To get started, edit index.android.js 
     </Text> 
     <Text style={styles.instructions}> 
      Double tap R on your keyboard to reload,{'\n'} 
      Shake or press menu button for dev menu 
     </Text> 
     </View> 
    ); 
    } 
} 

const styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    justifyContent: 'center', 
    alignItems: 'center', 
    backgroundColor: '#F5FCFF', 
    }, 
    welcome: { 
    fontSize: 20, 
    textAlign: 'center', 
    margin: 10, 
    }, 
    instructions: { 
    textAlign: 'center', 
    color: '#333333', 
    marginBottom: 5, 
    }, 
}); 

AppRegistry.registerComponent('Comp',() => Comp); 
4

Grundsätzlich, wenn Sie Größe festlegen möchten und es dann gesetzt machen ändern, wie dies auf das Layout angeben:

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

const styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    backgroundColor: 'yellow', 
    }, 
    View1: { 
    flex: 2, 
    margin: 10, 
    backgroundColor: 'red', 
    elevation: 1, 
    }, 
    View2: { 
    position: 'absolute', 
    backgroundColor: 'orange', 
    zIndex: 3, 
    elevation: 3, 
    }, 
    View3: { 
    flex: 3, 
    backgroundColor: 'green', 
    elevation: 2, 
    }, 
    Text: { 
    fontSize: 25, 
    margin: 20, 
    color: 'white', 
    }, 
}); 

class Example extends Component { 

    constructor(props) { 
    super(props); 

    this.state = { 
     view2LayoutProps: { 
     left: 0, 
     top: 0, 
     width: 50, 
     height: 50, 
     } 
    }; 
    } 

    onLayout(event) { 
    const {x, y, height, width} = event.nativeEvent.layout; 
    const newHeight = this.state.view2LayoutProps.height + 1; 
    const newLayout = { 
     height: newHeight , 
     width: width, 
     left: x, 
     top: y, 
     }; 

    this.setState({ view2LayoutProps: newLayout }); 
    } 

    render() { 
    return (
     <View style={styles.container}> 
     <View style={styles.View1}><Text>{this.state.view2LayoutProps.height}</Text></View> 
     <View onLayout={(event) => this.onLayout(event)} style={[styles.View2, this.state.view2LayoutProps]} /> 
     <View style={styles.View3} /> 
     </View> 
    ); 
    } 

} 


AppRegistry.registerComponent(Example); 

Sie kann viel mehr Variationen davon erstellen, wie es geändert werden soll, indem Sie dies in einer anderen Komponente verwenden, die eine andere Ansicht als Wrapper hat und einen onResponderRelease-Callback erstellt, der den Berührungsereignisspeicherort in den Status übergibt, der dann an die untergeordnete Komponente übergeben werden kann Eigentum, das könnte über Fahrt onLayout aktualisierten Zustand, indem Sie {[styles.View2, this.state.view2LayoutProps, this.props.touchEventTopLeft]} und so weiter platzieren.