برنامه نویسی

ساخت برنامه ماشین حساب با React Native و Tailwind CSS

اخیراً یک دوره React Native را تکمیل کردم و در اینجا در مورد اولین پروژه خود – یک برنامه ماشین حساب می نویسم. 😎

تصمیم گرفتم قبل از ورود به برنامه های پیچیده تلفن همراه با پروژه های کوچک شروع کنم. بنابراین، منتظر آموزش های بیشتری در مورد ساخت اپلیکیشن های پیشرفته یا پیچیده موبایل از من باشید.

من این را دارم!

بنابراین، در این آموزش، نحوه ساخت یک برنامه ماشین حساب موبایل با React Native و Tailwind CSS را به شما آموزش می دهم.

💡PS: این آموزش فرض می کند که React Native و یک شبیه ساز (یا دستگاه) روی رایانه خود نصب کرده اید.

React Native چیست؟

React Native یک چارچوب React منبع باز است که به شما امکان می دهد برنامه های بومی برای هر دو IOS و Android با کد جاوا اسکریپت ایجاد کنید. اگرچه در این آموزش، برنامه را با Expo می سازیم.

Expo ما را از پیکربندی های پیچیده مورد نیاز برای ایجاد یک برنامه بومی با React Native CLI نجات می دهد و آن را به ساده ترین و سریع ترین راه برای ساخت و انتشار برنامه های React Native تبدیل می کند.

💡 کارفرمایان بالقوه عزیز! من فعالانه به‌عنوان یک مهندس فرانت‌اند (کارآموز) یا نویسنده فنی به دنبال فرصت‌های دوردست هستم که در آن بتوانم پیشرفت کنم، یاد بگیرم و رشد کنم. اینم نمونه کارها و رزومه من

راه اندازی پروژه

با اجرای قطعه کد زیر یک برنامه Expo جدید ایجاد کنید.

npx create-expo-app calculator-app
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Nativewind و Tailwind CSS را به عنوان وابستگی های پروژه اضافه کنید.

yarn add nativewind
yarn add --dev tailwindcss
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

💡 NativeWind از Tailwind CSS به‌عنوان زبان برنامه‌نویسی خود استفاده می‌کند، بنابراین ما را قادر می‌سازد تا سبک‌های یکسانی را با Tailwind CSS برای برنامه‌های Android و iOS React Native بنویسیم.

اجرا کن npx tailwindcss init برای ایجاد یک tailwind.config.js فایل و آپدیت کنید tailwind.config.js فایل را به صورت زیر انجام دهید.

module.exports = {
    content: [
        "./App.{js,jsx,ts,tsx}",
        "./<custom directory>/**/*.{js,jsx,ts,tsx}",
    ],
    theme: {
        extend: {},
    },
    plugins: [],
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت افزونه Babel را به آن اضافه کنید babel.config.js.

// babel.config.js
module.exports = function (api) {
    api.cache(true);
    return {
        presets: ["babel-preset-expo"],
        plugins: ["nativewind/babel"],
    };
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تبریک می‌گوییم!🎉 شما Tailwind CSS را با موفقیت پیکربندی کردید. اکنون می توانید برنامه را با Tailwind CSS استایل دهید.

ساخت رابط کاربری اپلیکیشن

در این بخش، نحوه ساخت رابط کاربری برای اپلیکیشن را یاد خواهید گرفت.

رابط رابط کاربری برنامه

از تصویر بالا یک نمایشگر بزرگ و یک گروه دکمه داریم. در مرحله بعد، یک مؤلفه ایجاد کنید که یک ردیف از دکمه‌های حاوی اعداد و یک عملیات را برمی‌گرداند.

ردیف دکمه

import { Pressable, Text, View } from "react-native";
import React from "react";

const ButtonGroup = ({
    first,
    second,
    third,
    fourth,
    handleNumberPress,
    handleOperationPress,
}) => {
    return (
        <View className='flex-row items-center w-full space-x-3 justify-center px-10 mb-2'>
            <Pressable
                className=' bg-white py-4 rounded-xl shadow-md w-1/4'
                onPress={() => handleNumberPress(first)}
            >
                <Text className='text-3xl text-gray-600 font-semibold text-center'>
                    {first}
                </Text>
            </Pressable>
            <Pressable
                className=' bg-white py-4   rounded-xl shadow-md w-1/4'
                onPress={() => handleNumberPress(second)}
            >
                <Text className='text-3xl text-gray-600 font-semibold text-center'>
                    {second}
                </Text>
            </Pressable>
            <Pressable
                className=' bg-white py-4 rounded-xl shadow-md w-1/4'
                onPress={() => handleNumberPress(third)}
            >
                <Text className='text-3xl text-gray-600 font-semibold text-center'>
                    {third}
                </Text>
            </Pressable>
            <Pressable
                className='bg-blue-600 py-4  rounded-xl shadow-md w-1/4'
                onPress={() => handleOperationPress(fourth)}
            >
                <Text className='text-3xl text-white font-semibold text-center'>
                    {fourth}
                </Text>
            </Pressable>
        </View>
    );
};

export default ButtonGroup;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد بالا هر مقدار از دکمه و عملکردی را که باید با فشار دادن دکمه ها اجرا شود را می پذیرد. آخرین دکمه درون کامپوننت شامل یک عملیات خواهد بود. به همین دلیل است که عملکرد دیگری وجود دارد – handleOperationPress برای عملش

بعد، به روز رسانی کنید App.js فایل برای رندر مؤلفه رابط کاربری زیر.

return (
    <SafeAreaView className='flex-1 items-center'>
        <View className='flex-1 w-full bg-blue-50 rounded-xl p-4 mb-4 items-end justify-end'>
            <Text className={`${firstNumber.length <= 7 ? "text-8xl" : "text-6xl"}`}>
                {display()}
            </Text>
        </View>

        <View className='w-full rounded-xl py-4'>
            {/* --- button container ---*/}
        </View>
    </SafeAreaView>
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد بالا صفحه نمایش ماشین حساب را نمایش می دهد.

دکمه ها را با استفاده از قطعه کد زیر رندر کنید.

<View className='w-full rounded-xl py-4'>
    <View className='flex-row items-center w-full space-x-3 justify-center px-10 mb-2'>
        <Pressable
            className='bg-gray-600 py-4   rounded-xl shadow-md w-1/4'
            onPress={() => clearScreen()}
        >
            <Text className='text-3xl text-white font-semibold text-center'>C</Text>
        </Pressable>
        <Pressable
            className='bg-gray-600 py-4   rounded-xl shadow-md w-1/4'
            onPress={() => changeSignFunction()}
        >
            <Text className='text-3xl text-white font-semibold text-center'>+/-</Text>
        </Pressable>
        <Pressable
            className='bg-gray-600 py-4 rounded-xl shadow-md w-1/4'
            onPress={() => percentageFunction()}
        >
            <Text className='text-3xl text-white font-semibold text-center'>%</Text>
        </Pressable>
        <Pressable
            className='bg-blue-600 py-4   rounded-xl shadow-md w-1/4'
            onPress={() => handleOperationPress("÷")}
        >
            <Text className='text-3xl text-white font-semibold text-center'>÷</Text>
        </Pressable>
    </View>
    <ButtonGroup
        first='7'
        second='8'
        third='9'
        fourth='x'
        handleNumberPress={handleNumberPress}
        handleOperationPress={handleOperationPress}
    />
    <ButtonGroup
        first='4'
        second='5'
        third='6'
        fourth='-'
        handleNumberPress={handleNumberPress}
        handleOperationPress={handleOperationPress}
    />
    <ButtonGroup
        first='1'
        second='2'
        third='3'
        fourth='+'
        handleNumberPress={handleNumberPress}
        handleOperationPress={handleOperationPress}
    />
    <View className='flex-row items-center w-full space-x-3 justify-center px-10 mb-2'>
        <Pressable
            className='bg-white py-4   rounded-xl shadow-md w-1/4'
            onPress={() => handleNumberPress(".")}
        >
            <Text className='text-3xl text-gray-600 font-semibold text-center'>
                .
            </Text>
        </Pressable>
        <Pressable
            className='py-4   rounded-xl shadow-md w-1/4'
            onPress={() => handleNumberPress("0")}
        >
            <Text className='text-3xl text-gray-600 font-semibold text-center'>
                0
            </Text>
        </Pressable>
        <Pressable
            className='bg-white py-4 rounded-xl items-center justify-center shadow-md w-1/4'
            onPress={() => deleteFunction()}
        >
            <Feather name='delete' size={24} color='black' />
        </Pressable>
        <Pressable
            className='bg-blue-600 py-4 rounded-xl shadow-md w-1/4'
            onPress={() => getResult()}
        >
            <Text className='text-3xl text-white font-semibold text-center'>=</Text>
        </Pressable>
    </View>
</View>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد دکمه ها را روی صفحه نمایش می دهد. من استفاده نکردم ButtonGroup جزء برای ردیف بالا و پایین زیرا عملکردها و رنگ های آن با بقیه متفاوت است.

ایجاد قابلیت های دکمه

ابتدا باید سه حالت مختلف ایجاد کنید که مقادیر دکمه و عملیات را نگه می دارد.

import { StatusBar } from "expo-status-bar";
import { Pressable, SafeAreaView, Text, View } from "react-native";
import ButtonGroup from "./components/ButtonGroup";
import { Feather } from "@expo/vector-icons";
import { useState } from "react";

export default function App() {
    const [firstNumber, setFirstNumber] = useState("");
    const [secondNumber, setSecondNumber] = useState("");
    const [operation, setOperation] = useState("");

    return <div>{/* --- UI components ---*/}</div>;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه کد بالا نشان می دهد که کاربر می تواند حداقل دو عدد را به ماشین حساب و یک عملیات وارد کند، به جز عملیات درصد.

ایجاد یک display عملکردی که ورودی کاربر را روی صفحه نمایش می دهد.

const display = () => {
    if (!secondNumber && !firstNumber) {
        return "0";
    }
    if (!secondNumber) {
        return `${firstNumber}${operation}`;
    } else {
        return `${secondNumber}`;
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تابع بالا بررسی می کند که آیا کاربر عددی را وارد نکرده است، سپس “0” را برمی گرداند. در غیر این صورت عدد مناسب را روی صفحه نمایش برمی گرداند.

عملکردی را اضافه کنید که وقتی کاربر روی دکمه‌های عملیات کلیک می‌کند اجرا شود.

const handleOperationPress = (value) => {
    if (
        firstNumber[firstNumber.length - 1] === "x" ||
        firstNumber[firstNumber.length - 1] === "+" ||
        firstNumber[firstNumber.length - 1] === "-" ||
        firstNumber[firstNumber.length - 1] === "%" ||
        firstNumber[firstNumber.length - 1] === "÷" ||
        operation !== ""
    ) {
        return;
    }
    setOperation(value);
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

عملکرد بالا قبل از به‌روزرسانی، بررسی می‌کند که آیا آخرین ورودی عملیاتی نیست operation حالت.

عملکرد دیگری ایجاد کنید که هر بار که کاربر یک عدد را فشار می دهد اجرا می شود.

const handleNumberPress = (value) => {
    if (!operation && firstNumber.length < 10) {
        if (value !== ".") {
            setFirstNumber(firstNumber + value);
        } else {
            if (firstNumber.includes(".")) {
                return;
            } else {
                setFirstNumber(firstNumber + value);
            }
        }
    }
    if (operation && secondNumber.length < 10) {
        if (value !== ".") {
            setSecondNumber(secondNumber + value);
        } else {
            if (secondNumber.includes(".")) {
                return;
            } else {
                setSecondNumber(secondNumber + value);
            }
        }
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

عملکرد بالا بررسی می کند که آیا کاربر قبل از تنظیم عملیات وارد شده است یا خیر firstNumber و secondNumber ارزش های دولت
هنگامی که کاربر یک دکمه عددی را فشار می دهد، ماشین حساب مقدار آن را روی عدد تنظیم می کند firstNumber متغیر. هر عدد بعدی پس از علامت عملیات به عنوان عدد تنظیم می شود secondNumber.

تابع برابر به شکل زیر را ایجاد کنید.

const getResult = () => {
    switch (operation) {
        case "+":
            clearScreen();
            setFirstNumber(parseFloat(firstNumber) + parseFloat(secondNumber));
            setOperation("");
            setSecondNumber("");
            break;
        case "-":
            clearScreen();
            setFirstNumber(parseFloat(firstNumber) - parseFloat(secondNumber));
            setOperation("");
            setSecondNumber("");
            break;
        case "x":
            clearScreen();
            setFirstNumber(parseFloat(firstNumber) * parseFloat(secondNumber));
            setOperation("");
            setSecondNumber("");
            break;
        case "÷":
            clearScreen();
            const value = parseInt(firstNumber) / parseInt(secondNumber);
            if (value !== Math.round(value) && value !== Math.trunc(value)) {
                setFirstNumber(value.toFixed(5));
            } else {
                setFirstNumber(value);
            }
            setOperation("");
            setSecondNumber("");
            break;
        default:
            clearScreen();
            break;
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تابع بالا مقادیر the را می پذیرد firstNumber و secondNumber بیان می کند و عملیات درست را روی مقادیر انجام می دهد.

وقتی کاربر روی تابع درصد کلیک می کند، مقدار را به درصد برمی گرداند.

const percentageFunction = () => {
    if (!secondNumber) {
        return setFirstNumber(parseFloat(firstNumber) / 100);
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

عملکردی را اضافه کنید که به کاربران امکان می دهد صفحه را پاک کنند یا مقدار وارد شده اخیر را حذف کنند.

//👇🏻 clears the screen
const clearScreen = () => {
    setFirstNumber("");
    setSecondNumber("");
    setOperation("");
};

//👇🏻 removes the recently entered value
const deleteFunction = () => {
    if (operation) {
        return setSecondNumber(secondNumber.slice(0, -1));
    }
    return setFirstNumber(firstNumber.toString().slice(0, -1));
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت، ایجاد کنید changeSignFunction عملکردی که کاربران را قادر می سازد مقادیر منفی و مثبت را در ماشین حساب وارد کنند. تابع علامت روی یک عدد را بررسی می کند و آن را تغییر می دهد.

const changeSignFunction = () => {
    if (operation) {
        if (secondNumber.startsWith("-")) {
            return setSecondNumber(secondNumber.replace("-", "+"));
        }
        if (secondNumber.startsWith("+")) {
            return setSecondNumber(secondNumber.replace("+", "-"));
        }
        return setSecondNumber(`-${secondNumber}`);
    } else {
        if (firstNumber.toString().startsWith("-")) {
            return setFirstNumber(firstNumber.toString().replace("-", "+"));
        }
        if (firstNumber.toString().startsWith("+")) {
            return setFirstNumber(firstNumber.toString().replace("+", "-"));
        }
        return setFirstNumber(`-${firstNumber}`);
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نتیجه

همانطور که قبلاً گفتم، این یک پروژه React Native مبتدی است. امیدوارم به شما کمک کند تا با React Native شروع کنید یا اولین برنامه تلفن همراه خود را بسازید.

می‌توانید کد منبع را در GitHub دریافت کنید و نسخه آزمایشی پروژه را در اینجا امتحان کنید.

با تشکر از شما برای خواندن! 🎉

باز به کار🙂

آیا از این مقاله لذت بردید یا برای یک نقش از راه دور، تمام وقت یا مبتنی بر قرارداد به یک نویسنده فنی / React Developer با تجربه نیاز دارید؟ هر موقع خواستی با من تماس بگیر.
گیت هاب || لینکدین || توییتر

برای دیوید قهوه بخر
متشکرم

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا