รับขนาดของมุมมองใน Native React


148

เป็นไปได้หรือไม่ที่จะได้ขนาด (ความกว้างและความสูง) ของมุมมองที่แน่นอน? ตัวอย่างเช่นฉันมีมุมมองที่แสดงความคืบหน้า:

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

ฉันจำเป็นต้องทราบความกว้างจริงของมุมมองเพื่อจัดมุมมองอื่นให้เหมาะสม เป็นไปได้ไหม

คำตอบ:


315

ในฐานะของ React พื้นเมือง 0.4.2 ดูส่วนประกอบมีไม้ค้ำยันonLayout ผ่านในฟังก์ชั่นที่รับวัตถุเหตุการณ์ กิจกรรมnativeEventมีเค้าโครงของมุมมอง

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

onLayoutจัดการยังจะถูกเรียกเมื่อใดก็ตามที่ดูมีการปรับขนาด

ข้อแม้หลักคือonLayoutตัวจัดการถูกเรียกครั้งแรกหนึ่งเฟรมหลังจากที่คอมโพเนนต์ของคุณติดตั้งดังนั้นคุณอาจต้องการซ่อน UI ของคุณจนกว่าคุณจะคำนวณโครงร่างของคุณ


2
ปัญหาของวิธีการนี้คือเมื่ออุปกรณ์หมุน / ดูการเปลี่ยนแปลงขนาดฉันไม่ได้รับ onLayout เรียกอีกครั้ง
Matthew

4
onLayout ถูกเรียกใช้เมื่อเฟรมของมุมมองเปลี่ยนไป บางทีมุมมองของคุณอาจไม่เปลี่ยนขนาดหรือตำแหน่งในการหมุน ดูที่ตัวอย่าง onLayout ใน UIExplorer โดยที่ onLayout ถูกเรียกใช้เมื่อมีการหมุน
ide

2
สมมติว่าฉันต้องการที่จะแสดงที่Viewแตกต่างกันขึ้นอยู่กับขนาด ฉันไม่เข้าใจว่าฉันสามารถใช้onLayoutฟังก์ชันของมุมมองเพื่อเปลี่ยนวิธีการแสดงมุมมองได้อย่างไร นั่นนำไปสู่การวนซ้ำไม่สิ้นสุดใช่ไหม
Lane Rettig

2
@LaneRettig ใช่มันเป็นเช่นนั้นถ้านี่คือสิ่งที่คุณต้องการทำจริงๆคุณควรเขียนโค้ดของคุณในแบบที่ทำให้เกิดดุลยภาพ แต่ดูเหมือนคุณอาจต้องการปรับแต่งมุมมองของคุณตามขนาดหน้าจอในกรณีที่onLayoutไม่เกี่ยวข้อง
ide

7
@ ด้านวิธีที่คุณจะซ่อน UI จนกว่าจะมีการคำนวณโครงร่าง
Irfanlone

27

นี่เป็นสิ่งเดียวที่ใช้ได้สำหรับฉัน:

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);

14

โดยทั่วไปถ้าคุณต้องการตั้งค่าขนาดและทำการเปลี่ยนแปลงจากนั้นตั้งค่าเป็นสถานะในรูปแบบดังนี้:

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);

คุณสามารถสร้างรูปแบบที่หลากหลายของวิธีการแก้ไขโดยใช้สิ่งนี้ในองค์ประกอบอื่นที่มีมุมมองอื่นเป็น wrapper และสร้างการเรียกกลับ onResponderRelease ซึ่งสามารถส่งผ่านตำแหน่งเหตุการณ์การสัมผัสเข้าสู่สถานะซึ่งสามารถส่งผ่านไปยังองค์ประกอบลูก เป็นคุณสมบัติซึ่งสามารถแทนที่สถานะที่อัปเดตของ Layout โดยการวาง{[styles.View2, this.state.view2LayoutProps, this.props.touchEventTopLeft]}และอื่น ๆ


11

คุณสามารถใช้Dimensionsโมดูลและคำนวณขนาดมุมมองของคุณได้โดยตรง จริง ๆ แล้วDimensionsให้ขนาดหน้าต่างหลักให้คุณ

import { Dimensions } from 'Dimensions';

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

หวังว่าจะช่วยคุณ!

อัปเดต : วันนี้ใช้ Native StyleSheetพร้อมFlexการจัดเรียงมุมมองของคุณช่วยในการเขียนโค้ดที่สะอาดด้วยโซลูชันเลย์เอาต์ที่หรูหราในกรณีที่กว้างแทนที่จะคำนวณขนาดมุมมองของคุณ

แม้ว่าการสร้างคอมโพเนนต์กริดแบบกำหนดเองซึ่งตอบสนองต่อการปรับขนาดหน้าต่างเหตุการณ์สามารถสร้างโซลูชันที่ดีในส่วนประกอบวิดเจ็ตอย่างง่าย


3
Gah ทำไมเอกสารนี้ไม่ชัดเจนมากขึ้น! ฉันพยายาม 'ความกว้าง' และ 'ความสูง' แทน ('หน้าต่าง') ความกว้างเป็นต้น

273
ตัวอย่างที่คุณระบุให้ขนาดของหน้าต่างไม่ใช่มุมมองที่กำหนด สิ่งนี้เกี่ยวข้องกันอย่างไร
Mark Amery

1
@MarkAmery ด้วยขนาดหน้าต่างคุณสามารถวางแผนว่ามุมมองของคุณจะเป็นอย่างไร
Bruno Guerra

2
@BrunoGuerra คุณสามารถแสดงรหัสเพื่อให้ได้ขนาดมุมมอง (ไม่ใช่หน้าต่าง) ตามขนาดหรือไม่
Spark.Bao

4
ส่วนข้อมูลจะไม่ได้รับการอัปเดตบนอุปกรณ์หลายชนิดเมื่อหมุนอุปกรณ์ นี่เป็นปัญหาที่ทราบแล้วและดูเหมือนจะไม่ได้รับการแก้ไขในฐานะที่เป็นเจ้าของภาษา 0.32.0-rc.0
Glenn Lawrence

10

บางทีคุณสามารถใช้measure:

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);
}

NativeMethodsMixinสำหรับชีวิตของฉันที่ฉันไม่สามารถคิดออกวิธีการใช้อย่างถูกต้อง ไม่ว่าสิ่งที่ผมทำmeasureไม่ได้กำหนดเสมอ ตัวชี้ใด ๆ
chandlervdw

2
คุณไม่จำเป็นต้องใช้NativeMethodsMixinฟังก์ชั่นนี้มีในบางองค์ประกอบเท่านั้น ตัวอย่างเช่นTouchableWithFeedbackมีฟังก์ชั่นการวัด แต่ปกติTouchableไม่ได้ ลองเปลี่ยนประเภทที่Viewคุณใช้รับการอ้างอิงและตรวจสอบว่ามีองค์ประกอบการวัดหรือไม่ ฉันเคยเจอสิ่งนี้เช่นกัน
n0rm

-3

สำหรับฉันการตั้งค่ามิติการใช้% เป็นสิ่งที่ใช้ได้ผลสำหรับฉัน width:'100%'


-4

นี่คือรหัสเพื่อรับขนาดของมุมมองที่สมบูรณ์ของอุปกรณ์

var windowSize = Dimensions.get("window");

ใช้แบบนี้:

width=windowSize.width,heigth=windowSize.width/0.565


ไม่เป็นไร แต่ไม่ตอบคำถาม
Moso Akinyemi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.