fbpixel
Etiquetas: ,
0
(0)

Una vez que su primera aplicación React Native ha sido creada y está en funcionamiento, es posible que desee reutilizar ciertos elementos como componentes funcionales. Estos componentes pueden configurarse para otras aplicaciones y compartirse como una biblioteca.

Descripción

En este tutorial, vamos a empezar con una aplicación sencilla que contiene cuatro botones. Vamos a crear un componente funcional configurable de React Native en un archivo fuente que reutilizaremos en el archivo principal de la aplicación.

Veremos cómo:

  • pasar propiedades a un componente
  • recuperar datos de componentes a partir de eventos
  • utilizar un componente definido en un archivo fuente en el archivo principal

Aplicación básica: 4 botones

En este código, tenemos una vista principal (View) que cubre la pantalla, el título de la aplicación, y la vista que contiene los 4 botones. Las funciones que se realizan al pulsar los botones y los estilos definidos.

/**
 * https://github.com/jim-at-jibba/react-native-game-pad
 * https://github.com/ionkorol/react-native-joystick
 * 
 */
import React from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";


const GamePad = () =>  {

  let btnAColor = "red",
      btnBColor = "orange",
      btnXColor = "royalblue",
      btnYColor = "limegreen"

  const onButtonAPress = () => {
    console.log('You clicked button A');
  };
  const onButtonBPress = () => {
    console.log('You clicked button B');
  };

  const onButtonXPress = () => {
    console.log('You clicked button X');
  };
  const onButtonYPress = () => {
    console.log('You clicked button Y');
  };

 
    return (
      <View style={styles.mainBody}>
          <Text
            style={styles.mainTitle}>
            AC Controller
          </Text>
          <View style={{ flex: 1,justifyContent: "center", alignItems: "center",}}>
              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"green",
                  zIndex: 100,
                }}
              >
                <TouchableOpacity
                  style={[styles.button, {  top:"30%",backgroundColor: `${btnXColor}` }]} //top:"30%", right:"1%", 
                  onPress={() => onButtonXPress()}
                >
                  <Text style={styles.buttonText}>X</Text>
                </TouchableOpacity>
              </View>

              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"gold",
                }}
              >
                <TouchableOpacity
                  style={[styles.button, { top: "50%", right:"20%", backgroundColor: `${btnYColor}` }]} //top:"2%", left:"10%",
                  onPress={() => onButtonYPress()}
                >
                  <Text style={styles.buttonText}>Y</Text>
                </TouchableOpacity>
              </View>

              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"blue",
                }}
              >
                <TouchableOpacity
                  style={[styles.button, { bottom:"50%", left:"20%", backgroundColor: `${btnAColor}` }]} //bottom:"2%", 
                  onPress={() => onButtonAPress()}
                >
                  <Text style={styles.buttonText}>A</Text>
                </TouchableOpacity>
              </View>


            <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"red",
                }}
              >
                <TouchableOpacity
                  style={[styles.button, { bottom:"30%", backgroundColor: `${btnBColor}` }]} //bottom:"30%", left:"1%",
                  onPress={() => onButtonBPress()}
                >
                  <Text style={styles.buttonText}>B</Text>
                </TouchableOpacity>
              </View>

          </View>
      </View>            

    );
}
export default GamePad;

//parameters
let BACKGROUND_COLOR = "#161616"; //191A19
let BUTTON_COLOR = "#346751"; //1E5128
let ERROR_COLOR = "#C84B31"; //4E9F3D
let TEXT_COLOR = "#ECDBBA"; //D8E9A8

const styles = StyleSheet.create({

  mainBody: {
    flex:1,
    justifyContent: 'center',
    alignItems: "center",
    color:TEXT_COLOR,
    backgroundColor: BACKGROUND_COLOR,
  },

  mainTitle:{
    color: TEXT_COLOR,
    fontSize: 30,
    textAlign: 'center',
    borderBottomWidth: 2,
    borderBottomColor: ERROR_COLOR,
    width:"100%"
  },

  button: {
    height: 90,
    width: 90,
    borderRadius: 90 / 2,
    justifyContent: "center",
    alignItems: "center"
  },
  buttonText: {
    fontSize: 22,
    color: "white",
    fontWeight: "700"
  },


});

al pulsar los botones se ejecutan correctamente las funciones del evento

 BUNDLE  ./index.js

 LOG  Running "CustomApp" with {"rootTag":31}
 LOG  You clicked button Y
 LOG  You clicked button X
 LOG  You clicked button A
 LOG  You clicked button B

Llamar al componente desde un archivo fuente

Vamos a colocar este código en un archivo .

Para poder utilizarla, utilizamos la palabra clave export para definir la función

export const ButtonPad = ()  =>  {
...
}

A continuación, el componente puede utilizarse importándolo

import {ButtonPad} from "./src/ACJoysticks";
const GamePad = () =>  {
    return (
      <View style={styles.mainBody}>
          <Text
            style={styles.mainTitle}>
            AC Controller
          </Text>
          <ButtonPad/>
      </View>            

    );
};
export default GamePad;

Pasar propiedades a un componente funcional

Para que el componente sea configurable, definimos parámetros en el fichero principal que se pasarán a las propiedades del componente. Las propiedades que queremos pasar al componente son:

  • el texto que aparece en los botones
  • el color de los botones
  • el tamaño de los botones
  • la función onClick, que gestiona todos los botones

Los parámetros del componente se colocan en un ButtonPadProps tipo

type ButtonPadProps = {
  radius?: number;
  names?: string[4];
  colors?: string[4];
  onClick?:(evt: ButtonPadEvent) => void;
};

A continuación, podemos definir estas propiedades como entrada del componente y llamarlas con valores por defecto.

export const ButtonPad = (props : ButtonPadProps)  =>  {
  const { onClick, radius = 45, names= ['X','Y','A','B'], colors = ["royalblue","limegreen","red","orange"] } = props;

Definimos una única función para llamar a los botones

  const onButtonPress = (index:number) => {
    console.log('You clicked button ' + names[index]);
  };

Por último, modificamos el código para tener en cuenta las distintas propiedades.

/**
 * ButtonPad
 */

type ButtonPadProps = {
  radius?: number;
  names?: Array<string>;
  colors?: Array<string>;
  onClick?:(evt: ButtonPadEvent) => void;
};

export const ButtonPad = (props : ButtonPadProps)  =>  {
  const { onClick, radius = 45, names= ['X','Y','A','B'], colors = ["royalblue","limegreen","red","orange"] } = props;
  let textSize = radius;

  const onButtonPress = (index:number) => {
    console.log('You clicked button ' + names[index]);
  };
  

 
    return (

          <View style={{ flex: 1,justifyContent: "center", alignItems: "center",}}>
              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"green",
                  zIndex: 100,
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, {  top:"30%",backgroundColor: `${colors[0]}` }]} //top:"30%", right:"1%", 
                  onPress={() => onButtonPress(0)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[0]}</Text>
                </TouchableOpacity>
              </View>

              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"gold",
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, { top: "50%", right:"20%", backgroundColor: `${colors[1]}` }]} //top:"2%", left:"10%",
                  onPress={() => onButtonPress(1)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[1]}</Text>
                </TouchableOpacity>
              </View>

              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"blue",
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, { bottom:"50%", left:"20%", backgroundColor: `${colors[2]}` }]} //bottom:"2%", 
                  onPress={() => onButtonPress(2)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[2]}</Text>
                </TouchableOpacity>
              </View>


            <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"red",
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, { bottom:"30%", backgroundColor: `${colors[3]}` }]} //bottom:"30%", left:"1%",
                  onPress={() => onButtonPress(3)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[3]}</Text>
                </TouchableOpacity>
              </View>

          </View>
    );
}

Pasar datos del componente a la aplicación

Para devolver datos a la aplicación principal, utilizamos una interfaz que contiene los estados de los botones y el nombre del botón pulsado

interface ButtonPadEvent {
  states : Array<boolean>;
  pressed: string;
}

Modificamos la función onButtonPress para alimentar los estados y enviarlos a la función onClick.

  const onButtonPress = (index:number) => {

    let btnStates= [false,false,false,false];
    btnStates[index] = true;

    if(typeof(onClick)==="function"){
      onClick({
             states: btnStates,
             pressed: names[index]
         });
       }
  };

N.B.: La notación if(typeof(onClick)===»function»){ onClick() } es equivalente a onClick && onClick()

Ahora podemos llamar a nuestro componente en la aplicación principal, crear una función de escucha y modificar sus parámetros.

const GamePad = () =>  {
  const onPadClick = (data: any) => {
    console.log("form ButtonPad: ",data);
  }
    return (
      <View style={styles.mainBody}>
          <Text
            style={styles.mainTitle}>
            AC Controller
          </Text>
          <ButtonPad radius={60} names={['\u2573', '\u25EF', '\u25B3', "\u25A2"]} colors={['black', 'black', 'black', 'black']} onClick={onPadClick} />
      </View>            

    );
}
export default GamePad;
info Reloading app...
 BUNDLE  ./index.js

 LOG  Running "CustomApp" with {"rootTag":81}
 LOG  form ButtonPad:  {"pressed": "╳", "states": [true, false, false, false]}
 LOG  form ButtonPad:  {"pressed": "△", "states": [false, false, true, false]}
 LOG  form ButtonPad:  {"pressed": "▢", "states": [false, false, false, true]}
 LOG  form ButtonPad:  {"pressed": "◯", "states": [false, true, false, false]}

N.B.: para hacer las cosas correctamente, tendrías que crear los observadores onPressIn y onPressOut para poner los estados a cero y modificar la lógica para escuchar varios botones a la vez.

Código completo

./src/ACJoysticks.tsx

/**
 * ButtonPad
 */

interface ButtonPadEvent {
  states : Array<boolean>;
  pressed: string;
}

type ButtonPadProps = {
  radius?: number;
  names?: Array<string>;
  colors?: Array<string>;
  onClick?:(evt: ButtonPadEvent) => void;
};



export const ButtonPad = (props : ButtonPadProps)  =>  {
  const { onClick, radius = 45, names= ['X','Y','A','B'], colors = ["royalblue","limegreen","red","orange"] } = props;
  let textSize = radius;
  let btnStates= [false,false,false,false];

  const onButtonPress = (index:number) => {
    btnStates[index] = true;

    if(typeof(onClick)==="function"){
      onClick({
             states: btnStates,
             pressed: names[index]
         });
       }
  };
  
  const onButtonRel = (index:number) => {
    btnStates[index] = false;
    
    if(typeof(onClick)==="function"){
      onClick({
             states: btnStates,
             pressed: names[index]
         });
       }
  };
  
    return (

          <View style={{ flex: 1,justifyContent: "center", alignItems: "center",}}>
              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"green",
                  zIndex: 100,
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, {  top:"30%",backgroundColor: `${colors[0]}` }]} //top:"30%", right:"1%", 
                  //onPress={() => onButtonPress(0)}
                  onPressIn={() => onButtonPress(0)}
                  onPressOut={() => onButtonRel(0)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[0]}</Text>
                </TouchableOpacity>
              </View>

              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"gold",
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, { top: "50%", right:"20%", backgroundColor: `${colors[1]}` }]} //top:"2%", left:"10%",
                  //onPress={() => onButtonPress(1)}
                  onPressIn={() => onButtonPress(1)}
                  onPressOut={() => onButtonRel(1)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[1]}</Text>
                </TouchableOpacity>
              </View>

              <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"blue",
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, { bottom:"50%", left:"20%", backgroundColor: `${colors[2]}` }]} //bottom:"2%", 
                  //onPress={() => onButtonPress(2)}
                  onPressIn={() => onButtonPress(2)}
                  onPressOut={() => onButtonRel(2)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[2]}</Text>
                </TouchableOpacity>
              </View>


            <View
                style={{
                  //flex: 1,
                  justifyContent: "center",
                  alignItems: "center",
                  //backgroundColor:"red",
                }}
              >
                <TouchableOpacity
                  style={[{
                    height: 2*radius,
                    width: 2*radius,
                    borderRadius: radius,
                    justifyContent: "center",
                    alignItems: "center"
                  }, { bottom:"30%", backgroundColor: `${colors[3]}` }]} //bottom:"30%", left:"1%",
                  //onPress={() => onButtonPress(3)}
                  onPressIn={() => onButtonPress(3)}
                  onPressOut={() => onButtonRel(3)}
                >
                  <Text style={{
                            fontSize: textSize,
                            color: "white",
                            fontWeight: "700"
                          }}>{names[3]}</Text>
                </TouchableOpacity>
              </View>

          </View>
    );
}

./App.tsx

import React from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import {ButtonPad} from "./src/ACJoysticks";

const GamePad = () =>  {
  const onPadClick = (data: any) => {
    console.log("from ButtonPad: ",data);
    //data.states[0], data.pressed
  }

    return (
      <View style={styles.mainBody}>
          <Text
            style={styles.mainTitle}>
            AC Controller
          </Text>
          <ButtonPad radius={60} names={[ '\u25B3', '\u25A2', '\u25EF',  '\u2573',]} colors={['black', 'black', 'black', 'black']} onClick={onPadClick} />
      </View>            

    );
}
export default GamePad;

//parameters
let BACKGROUND_COLOR = "#161616"; //191A19
let BUTTON_COLOR = "#346751"; //1E5128
let ERROR_COLOR = "#C84B31"; //4E9F3D
let TEXT_COLOR = "#ECDBBA"; //D8E9A8

const styles = StyleSheet.create({

  mainBody: {
    flex:1,
    justifyContent: 'center',
    alignItems: "center",
    color:TEXT_COLOR,
    backgroundColor: BACKGROUND_COLOR,
  },

  mainTitle:{
    color: TEXT_COLOR,
    fontSize: 30,
    textAlign: 'center',
    borderBottomWidth: 2,
    borderBottomColor: ERROR_COLOR,
    width:"100%"
  },
});

Aplicaciones

  • Cree componentes reutilizables y configurables para sus aplicaciones
  • Cree aplicaciones para controlar sus proyectos mediante Bluetooth, BLE o Wifi

Fuentes

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en una estrella para puntuarlo!

Promedio de puntuación 0 / 5. Recuento de votos: 0

Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.

Ya que has encontrado útil este contenido...

¡Sígueme en los medios sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?