React Native Expo 条码扫描仪导航

问题描述 投票:0回答:1

我是 React Native 和 Expo 的新手,我遵循了使用 Expo 的条形码扫描应用程序的在线教程,但它没有涵盖如何从 Expo 相机应用程序导航到另一个屏幕,我无法真正理解它出去。我让扫描仪正常工作,并使用 qrcode 数据创建了 django Rest 后端,但它仅应用文件名称,并且我希望导航到一个页面,该页面还包含我的 django 模型中列出的名称和描述。我确信我可能必须以某种方式更新我的 django 模型,但我确实可以在代码中使用一些帮助。这是我的 Django 模型:

from django.db import models
import qrcode
from io import BytesIO
from django.core.files.base import ContentFile
from PIL import Image


class Event(models.Model):
   name = models.CharField(max_length=200)
   description = models.TextField()
   qr_code = models.ImageField(blank=True, upload_to='qrcodes/')
   date = models.DateField()

   def __str__(self):
        return str(self.name)

   def save(self, *args, **kwargs):
    if not self.qr_code:
        qrcode_img = qrcode.make(self.name)
        canvas = Image.new('RGB', (qrcode_img.pixel_size, qrcode_img.pixel_size), 'white')
        canvas.paste(qrcode_img)
        fname = f'{self.name}.png'
        buffer = BytesIO()
        canvas.save(buffer, 'PNG')
        self.qr_code.save(fname, ContentFile(buffer.getvalue()), save=False)
    super().save(*args, **kwargs)

这是我的条码扫描仪屏幕的反应:

import React, { useState, useEffect } from "react";
import { Text, View, StyleSheet, Button } from "react-native";
import { CameraView, Camera } from "expo-camera";
import { useNavigation } from "@react-navigation/native";

export default function App() {
  const [hasPermission, setHasPermission] = useState(null);
  const [scanned, setScanned] = useState(false);

  useEffect(() => {
    const getCameraPermissions = async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      setHasPermission(status === "granted");
    };

    getCameraPermissions();
  }, []);

  const navigation = useNavigation()
  const handleBarCodeScanned = ({ type, data }) => {

    setScanned(true);
    // alert(`Bar code with type ${type} and data ${data} has been scanned!`);

    if (data) {
        navigation.navigate('Event', {eventId: data} )
    }
  };

  if (hasPermission === null) {
    return <Text>Requesting for camera permission</Text>;
  }
  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }

  return (
    <View style={styles.container}>
      <CameraView
        onBarcodeScanned={scanned ? undefined : handleBarCodeScanned}
        barcodeScannerSettings={{
          barcodeTypes: ["qr", "pdf417"],
        }}
        style={StyleSheet.absoluteFillObject}
      />
      {scanned && (
        <Button title={"Tap to Scan Again"} onPress={() => setScanned(false)} />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "column",
    justifyContent: "center",
  },
});

最后这是我想根据条形码导航到的事件屏幕

import { useNavigation, useRoute } from "@react-navigation/native";
import { useLayoutEffect } from "react";
import { View, Text, StyleSheet } from "react-native";
import { HeaderBackButton } from '@react-navigation/elements';

const EventDetailScreen = () => {
    const route = useRoute()
    const navigation = useNavigation()

    const {eventId, name, description} = route.params

    useLayoutEffect(()=> {
        navigation.setOptions({
            headerTitle: name,
            headerLeft: () => (
                <HeaderBackButton
                    tintColor="white"
                    onPress={()=> navigation.goBack()}
                />
            )
        }, [])
    })

    return (
        <View style={ Styles.screen }>
            <Text style={{fontSize: 20}} >This is the event detail screen for {eventId}</Text>
            <Text style={{fontSize: 20}} >{name}</Text>
            <Text style={{fontSize: 20}} >{description}</Text>
        </View>
    );
}

const Styles = StyleSheet.create({
    screen: {
        padding:20,
    }
})

export default EventDetailScreen

任何帮助将不胜感激。先谢谢你了

reactjs django react-native expo
1个回答
0
投票

方法

  1. 更新 Django 后端:
  2. 在 React Native 中获取事件详细信息:
  3. 更新导航和事件详细信息屏幕

Django 后端

首先,更新 Django 后端以提供 API 端点以通过事件 ID 获取事件详细信息。

# views.py

from django.shortcuts import get_object_or_404
from django.http import JsonResponse
from .models import Event

def get_event(request, event_id):
    event = get_object_or_404(Event, id=event_id)
    data = {
        "name": event.name,
        "description": event.description,
        "date": event.date
    }
    return JsonResponse(data)
# urls.py

from django.urls import path
from .views import get_event

urlpatterns = [
    path('event/<int:event_id>/', get_event, name='get_event'),
]

反应本机应用程序

确保您已在导航器中注册了

EventDetailScreen

// App.js

import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import BarcodeScannerScreen from './BarcodeScannerScreen';
import EventDetailScreen from './EventDetailScreen';

const Stack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="BarcodeScanner" component={BarcodeScannerScreen} />
        <Stack.Screen name="EventDetail" component={EventDetailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

更新条形码扫描仪屏幕以导航至事件详细信息屏幕并传递事件 ID。

// BarcodeScannerScreen.js

import React, { useState, useEffect } from "react";
import { Text, View, StyleSheet, Button } from "react-native";
import { Camera } from "expo-camera";
import { useNavigation } from "@react-navigation/native";

export default function BarcodeScannerScreen() {
  const [hasPermission, setHasPermission] = useState(null);
  const [scanned, setScanned] = useState(false);

  useEffect(() => {
    const getCameraPermissions = async () => {
      const { status } = await Camera.requestPermissionsAsync();
      setHasPermission(status === "granted");
    };

    getCameraPermissions();
  }, []);

  const navigation = useNavigation();
  const handleBarCodeScanned = ({ type, data }) => {
    setScanned(true);

    if (data) {
      navigation.navigate('EventDetail', { eventId: data });
    }
  };

  if (hasPermission === null) {
    return <Text>Requesting for camera permission</Text>;
  }
  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }

  return (
    <View style={styles.container}>
      <Camera
        onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
        style={StyleSheet.absoluteFillObject}
      />
      {scanned && (
        <Button title={"Tap to Scan Again"} onPress={() => setScanned(false)} />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "column",
    justifyContent: "center",
  },
});

更新事件详细信息屏幕,以便在导航到后端时从后端获取事件详细信息。

// EventDetailScreen.js

import { useNavigation, useRoute } from "@react-navigation/native";
import React, { useEffect, useState } from "react";
import { View, Text, StyleSheet } from "react-native";

const EventDetailScreen = () => {
  const route = useRoute();
  const navigation = useNavigation();
  const { eventId } = route.params;
  const [event, setEvent] = useState(null);

  useEffect(() => {
    const fetchEventDetails = async () => {
      try {
        const response = await fetch(`http://your-django-backend-url/event/${eventId}/`);
        const data = await response.json();
        setEvent(data);
        navigation.setOptions({ headerTitle: data.name });
      } catch (error) {
        console.error(error);
      }
    };

    fetchEventDetails();
  }, [eventId]);

  if (!event) {
    return <Text>Loading...</Text>;
  }

  return (
    <View style={styles.screen}>
      <Text style={{ fontSize: 20 }}>{event.name}</Text>
      <Text style={{ fontSize: 20 }}>{event.description}</Text>
      <Text style={{ fontSize: 20 }}>{event.date}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  screen: {
    padding: 20,
  },
});

export default EventDetailScreen;

总结

  1. Django 后端:添加了一个端点以通过事件 ID 获取事件详细信息。
  2. BarcodeScannerScreen:导航至具有扫描事件 ID 的
    EventDetailScreen
  3. EventDetailScreen:根据事件ID获取并显示事件详细信息。
© www.soinside.com 2019 - 2024. All rights reserved.