Cross-Platform Mobile Development

Introduction

Cross-platform development allows you to build mobile applications that run on multiple platforms using a single codebase. This guide covers popular frameworks and best practices for cross-platform development.

Key Benefits:

  • Single codebase for multiple platforms
  • Faster development time
  • Cost-effective maintenance
  • Consistent user experience
  • Broader market reach
  • Code reusability

React Native Development

Basic App Structure

// App.js
import React, { useState } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  StyleSheet,
  Alert
} from 'react-native';

const App = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = () => {
    if (!username || !password) {
      Alert.alert('Error', 'Please fill in all fields');
      return;
    }
    
    // Add login logic here
    console.log('Login:', { username, password });
  };

  return (
    
      Welcome
      
      
      
      
      
      
        Login
      
    
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
  },
  input: {
    height: 50,
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    marginBottom: 15,
    paddingHorizontal: 15,
  },
  button: {
    backgroundColor: '#007AFF',
    height: 50,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

Custom Components

// components/CustomButton.js
import React from 'react';
import {
  TouchableOpacity,
  Text,
  StyleSheet,
  ActivityIndicator
} from 'react-native';

const CustomButton = ({
  title,
  onPress,
  isLoading,
  disabled,
  style,
}) => {
  return (
    
      {isLoading ? (
        
      ) : (
        {title}
      )}
    
  );
};

const styles = StyleSheet.create({
  button: {
    backgroundColor: '#007AFF',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
  disabled: {
    backgroundColor: '#ccc',
  },
  text: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

export default CustomButton;

Flutter Development

Basic App Structure

// main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginScreen(),
    );
  }
}

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State {
  final _formKey = GlobalKey();
  String? _username;
  String? _password;
  bool _isLoading = false;

  void _handleLogin() {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();
      setState(() => _isLoading = true);
      
      // Simulate API call
      Future.delayed(Duration(seconds: 2), () {
        setState(() => _isLoading = false);
        print('Login: $_username, $_password');
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Login')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Username',
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter username';
                  }
                  return null;
                },
                onSaved: (value) => _username = value,
              ),
              SizedBox(height: 16),
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Password',
                  border: OutlineInputBorder(),
                ),
                obscureText: true,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter password';
                  }
                  return null;
                },
                onSaved: (value) => _password = value,
              ),
              SizedBox(height: 24),
              SizedBox(
                width: double.infinity,
                height: 50,
                child: ElevatedButton(
                  onPressed: _isLoading ? null : _handleLogin,
                  child: _isLoading
                      ? CircularProgressIndicator(color: Colors.white)
                      : Text('Login'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Custom Widget

// custom_button.dart
import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  final String title;
  final VoidCallback onPressed;
  final bool isLoading;
  final bool disabled;

  const CustomButton({
    Key? key,
    required this.title,
    required this.onPressed,
    this.isLoading = false,
    this.disabled = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 50,
      child: ElevatedButton(
        onPressed: (disabled || isLoading) ? null : onPressed,
        style: ElevatedButton.styleFrom(
          primary: disabled ? Colors.grey : Colors.blue,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(8),
          ),
        ),
        child: isLoading
            ? SizedBox(
                width: 24,
                height: 24,
                child: CircularProgressIndicator(
                  color: Colors.white,
                  strokeWidth: 2,
                ),
              )
            : Text(
                title,
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                ),
              ),
      ),
    );
  }
}

Xamarin Development

Basic App Structure

// LoginPage.xaml.cs
using Xamarin.Forms;

public partial class LoginPage : ContentPage
{
    private readonly LoginViewModel _viewModel;

    public LoginPage()
    {
        InitializeComponent();
        _viewModel = new LoginViewModel();
        BindingContext = _viewModel;
    }
}

// LoginViewModel.cs
public class LoginViewModel : INotifyPropertyChanged
{
    private string _username;
    private string _password;
    private bool _isLoading;
    private ICommand _loginCommand;

    public string Username
    {
        get => _username;
        set
        {
            _username = value;
            OnPropertyChanged();
        }
    }

    public string Password
    {
        get => _password;
        set
        {
            _password = value;
            OnPropertyChanged();
        }
    }

    public bool IsLoading
    {
        get => _isLoading;
        set
        {
            _isLoading = value;
            OnPropertyChanged();
        }
    }

    public ICommand LoginCommand
    {
        get
        {
            return _loginCommand ?? (_loginCommand = 
                new Command(async () => await Login()));
        }
    }

    private async Task Login()
    {
        if (string.IsNullOrEmpty(Username) || 
            string.IsNullOrEmpty(Password))
        {
            await Application.Current.MainPage
                .DisplayAlert("Error", "Please fill in all fields", "OK");
            return;
        }

        IsLoading = true;

        try
        {
            // Add login logic here
            await Task.Delay(2000); // Simulate API call
            Debug.WriteLine($"Login: {Username}, {Password}");
        }
        catch (Exception ex)
        {
            await Application.Current.MainPage
                .DisplayAlert("Error", ex.Message, "OK");
        }
        finally
        {
            IsLoading = false;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(
        [CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, 
            new PropertyChangedEventArgs(propertyName));
    }
}

Deployment

Deployment Steps:

  • Android Deployment:
    • Generate signed APK
    • Configure Play Store listing
    • Upload APK/Bundle
    • Release management
  • iOS Deployment:
    • Code signing
    • App Store Connect setup
    • TestFlight testing
    • App Store submission

Framework Comparison

React Native:

  • Pros:
    • Large community
    • JavaScript/React familiarity
    • Hot reloading
    • Native performance
  • Cons:
    • Bridge overhead
    • Platform-specific code
    • Native module dependencies

Flutter:

  • Pros:
    • Single UI codebase
    • High performance
    • Rich widget library
    • Great documentation
  • Cons:
    • Dart learning curve
    • Larger app size
    • Newer ecosystem

Xamarin:

  • Pros:
    • C# development
    • Native UI
    • Microsoft support
    • Code sharing
  • Cons:
    • Smaller community
    • Platform-specific UI
    • Commercial licensing