دليل Xamarin المختصر
Xamarin - Cross-Platform Mobile Apps with .NET
Xamarin هي منصة مفتوحة المصدر لبناء تطبيقات حديثة وعالية الأداء لأنظمة iOS، Android، وWindows باستخدام .NET. Xamarin هي طبقة تجريد تدير التواصل بين الكود المشترك وكود المنصة الأساسي.
[No text to translate] ```bash # Install Visual Studio (Windows) or Visual Studio for Mac (macOS) # Make sure to include the "Mobile development with .NET" workloadFor iOS development on Windows, you need a Mac with Xcode and Visual Studio for Mac installed
```bash
# Open Visual Studio Installer
# Check if "Mobile development with .NET" is installed
# Check for Android SDK and NDK
# Visual Studio > Tools > Options > Xamarin > Android Settings
# Check for Xcode and Apple SDKs (macOS)
# Visual Studio for Mac > Preferences > Projects > SDK Locations > Apple
```### التحقق من التثبيت
```bash
# In Visual Studio
# File > New > Project
# Select "Mobile App (Xamarin.Forms)"
# Choose a template (Blank, Tabbed, Shell)
# In Visual Studio for Mac
# File > New Solution
# Select "Multiplatform > App > Xamarin.Forms"
# Choose a template (Blank, Tabbed, Shell)
```### إنشاء مشروع جديد
```bash
# Select a startup project (Android or iOS)
# Choose a device or emulator
# Click the "Run" button or press F5
```### تشغيل التطبيق
MyApp/ ├── MyApp/ # .NET Standard library (shared code) │ ├── App.xaml │ ├── App.xaml.cs │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ ├── Models/ │ ├── Views/ │ ├── ViewModels/ │ └── Services/ ├── MyApp.Android/ # Android-specific project │ ├── MainActivity.cs │ ├── Resources/ │ └── Assets/ ├── MyApp.iOS/ # iOS-specific project │ ├── AppDelegate.cs │ ├── Main.cs │ └── Info.plist └── MyApp.sln # Solution file
```csharp
// ContentPage
public class MyContentPage : ContentPage
{
public MyContentPage()
{
Content = new StackLayout
{
Children = { new Label { Text = "Welcome to Xamarin.Forms!" } }
};
}
}
// TabbedPage
public class MyTabbedPage : TabbedPage
{
public MyTabbedPage()
{
Children.Add(new MyContentPage { Title = "Tab 1" });
Children.Add(new MyContentPage { Title = "Tab 2" });
}
}
// FlyoutPage (Master-Detail)
public class MyFlyoutPage : FlyoutPage
{
public MyFlyoutPage()
{
Flyout = new ContentPage { Title = "Menu" };
Detail = new NavigationPage(new MyContentPage());
}
}
```### الصفحات
```csharp
// StackLayout
new StackLayout
{
Orientation = StackOrientation.Vertical,
Spacing = 10,
Children = { new Label(), new Button() }
};
// Grid
new Grid
{
RowDefinitions = { new RowDefinition { Height = GridLength.Auto } },
ColumnDefinitions = { new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) } },
Children = { { new Label(), 0, 0 } }
};
// FlexLayout
new FlexLayout
{
Direction = FlexDirection.Row,
JustifyContent = FlexJustify.SpaceBetween,
Children = { new Label(), new Button() }
};
// AbsoluteLayout
new AbsoluteLayout
{
Children = { { new BoxView { Color = Colors.Blue }, new Rectangle(0, 0, 100, 100) } }
};
// RelativeLayout
new RelativeLayout
{
Children = { { new BoxView(), Constraint.Constant(0) } }
};
```### التخطيطات
```csharp
// Label
new Label { Text = "Hello, Xamarin!", FontSize = 24 };
// Button
new Button { Text = "Click Me", Command = new Command(() => DisplayAlert("Title", "Message", "OK")) };
// Entry
new Entry { Placeholder = "Enter text" };
// Editor
new Editor { Placeholder = "Enter multi-line text" };
// SearchBar
new SearchBar { Placeholder = "Search..." };
// Slider
new Slider { Minimum = 0, Maximum = 100 };
// Stepper
new Stepper { Minimum = 0, Maximum = 10 };
// Switch
new Switch { IsToggled = true };
// DatePicker
new DatePicker();
// TimePicker
new TimePicker();
// ListView
new ListView
{
ItemsSource = new[] { "Item 1", "Item 2" },
ItemTemplate = new DataTemplate(() =>
{
var cell = new TextCell();
cell.SetBinding(TextCell.TextProperty, ".");
return cell;
})
};
// CollectionView
new CollectionView
{
ItemsSource = new[] { "Item 1", "Item 2" }
};
```### عناصر التحكم
```csharp
// MainActivity.cs
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
var button = FindViewById<Button>(Resource.Id.myButton);
button.Click += (sender, e) =>
{
Toast.MakeText(this, "Button Clicked!", ToastLength.Short).Show();
};
}
}
```### Xamarin.Android
```csharp
// ViewController.cs
public partial class ViewController : UIViewController
{
public ViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
var button = new UIButton(UIButtonType.System);
button.Frame = new CGRect(20, 200, 280, 44);
button.SetTitle("Click Me", UIControlState.Normal);
button.TouchUpInside += (sender, e) =>
{
var alert = UIAlertController.Create("Title", "Message", UIAlertControllerStyle.Alert);
alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
PresentViewController(alert, true, null);
};
View.AddSubview(button);
}
}
```### Xamarin.iOS
```xml
<!-- MainPage.xaml -->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage">
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<Button Text="Click Me" Clicked="OnButtonClicked" />
</StackLayout>
</ContentPage>
// MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void OnButtonClicked(object sender, EventArgs e)
{
DisplayAlert("Title", "Message", "OK");
}
}
```## XAML
```xml
<!-- ViewModel -->
public class MyViewModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<!-- XAML -->
<ContentPage.BindingContext>
<local:MyViewModel />
</ContentPage.BindingContext>
<Entry Text="{Binding Name, Mode=TwoWay}" />
<Label Text="{Binding Name}" />
```## ربط البيانات
```csharp
// Push a new page
await Navigation.PushAsync(new DetailsPage());
// Pop a page
await Navigation.PopAsync();
// Pop to root
await Navigation.PopToRootAsync();
// Pass data
await Navigation.PushAsync(new DetailsPage(item));
// Modal navigation
await Navigation.PushModalAsync(new ModalPage());
await Navigation.PopModalAsync();
```## التنقل
```csharp
// Define an interface in shared code
public interface ITextToSpeech
{
void Speak(string text);
}
// Implement the interface in platform-specific projects
// Android
[assembly: Dependency(typeof(TextToSpeech_Android))]
namespace MyApp.Droid
{
public class TextToSpeech_Android : ITextToSpeech { ... }
}
// iOS
[assembly: Dependency(typeof(TextToSpeech_iOS))]
namespace MyApp.iOS
{
public class TextToSpeech_iOS : ITextToSpeech { ... }
}
// Use the service in shared code
DependencyService.Get<ITextToSpeech>().Speak("Hello, Xamarin!");
```## DependencyService
```csharp
// Create a custom control in shared code
public class MyEntry : Entry { }
// Create a custom renderer in platform-specific projects
// Android
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace MyApp.Droid
{
public class MyEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.SetBackgroundColor(Android.Graphics.Color.LightGreen);
}
}
}
}
// iOS
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace MyApp.iOS
{
public class MyEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.BackgroundColor = UIColor.FromRGB(204, 153, 255);
}
}
}
}
```## المُعالِجات المخصصة
```csharp
// Create an effect in shared code
public class FocusEffect : RoutingEffect
{
public FocusEffect() : base("MyApp.FocusEffect") { }
}
// Implement the effect in platform-specific projects
// Android
[assembly: ResolutionGroupName("MyApp")]
[assembly: ExportEffect(typeof(FocusEffect_Android), "FocusEffect")]
namespace MyApp.Droid
{
public class FocusEffect_Android : PlatformEffect { ... }
}
// Use the effect in XAML
<Entry>
<Entry.Effects>
<local:FocusEffect />
</Entry.Effects>
</Entry>
```## التأثيرات
```csharp
// Subscribe to a message
MessagingCenter.Subscribe<MainPage, string>(this, "Hi", (sender, arg) =>
{
// Do something with the message
});
// Send a message
MessagingCenter.Send(this, "Hi", "John");
// Unsubscribe
MessagingCenter.Unsubscribe<MainPage, string>(this, "Hi");
```## مركز الرسائل
The translations maintain the original markdown formatting, keep technical terms in English, and preserve the structure of the original text.```csharp
// Set a value
Preferences.Set("my_key", "my_value");
// Get a value
var value = Preferences.Get("my_key", "default_value");
```### نظام الملفات
```csharp
// Get the local app data folder
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var filename = Path.Combine(path, "myfile.txt");
// Write to a file
File.WriteAllText(filename, "Hello, Xamarin!");
// Read from a file
var content = File.ReadAllText(filename);
```### SQLite
```csharp
// Install sqlite-net-pcl NuGet package
// Create a model
public class MyItem
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Text { get; set; }
}
// Create a database connection
var db = new SQLiteAsyncConnection(dbPath);
await db.CreateTableAsync<MyItem>();
// Save an item
await db.InsertAsync(item);
// Get all items
var items = await db.Table<MyItem>().ToListAsync();
```## الشبكات
```csharp
var client = new HttpClient();
var response = await client.GetAsync("https://api.example.com/items");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var items = JsonConvert.DeserializeObject<List<MyItem>>(content);
}
```### HttpClient
```csharp
// Install Refit NuGet package
// Define an interface
public interface IMyApi
{
[Get("/items")]
Task<List<MyItem>> GetItems();
}
// Use the interface
var api = RestService.For<IMyApi>("https://api.example.com");
var items = await api.GetItems();
```### Refit
```csharp
// Use a testing framework like NUnit or xUnit
[Test]
public void MyViewModel_MyCommand_ShouldDoSomething()
{
// Arrange
var viewModel = new MyViewModel();
// Act
viewModel.MyCommand.Execute(null);
// Assert
Assert.IsTrue(viewModel.MyProperty);
}
```## الاختبار
```csharp
// Use Xamarin.UITest
[Test]
public void AppLaunches()
{
app.Screenshot("First screen.");
}
[Test]
public void TappingButton_ShouldNavigateToDetails()
{
app.Tap(c => c.Button("MyButton"));
app.WaitForElement(c => c.Marked("DetailsPage"));
app.Screenshot("Details screen.");
}
```### اختبار الوحدة
```bash
# Build the app in Release mode
# Archive the app
# Distribute the archive (e.g., to Google Play)
```### اختبار واجهة المستخدم
```bash
# Build the app in Release mode
# Archive the app
# Distribute the archive (e.g., to the App Store)
```## أفضل الممارسات
- **استخدم MVVM**: افصل واجهة المستخدم عن منطق العمل.
- **استخدم الربط البياني**: بسّط كود واجهة المستخدم واجعله أكثر قابلية للصيانة.
- **استخدم DependencyService للكود الخاص بالمنصة**: حافظ على نظافة الكود المشترك.
- **حسّن الأداء**: استخدم الربط المترجم، التحميل الكسول، وتقنيات أخرى.
- **اكتب اختبارات**: تأكد من عمل التطبيق بشكل صحيح.
## استكشاف المشكلات
### المشكلات الشائعة
- **أخطاء البناء**: تحقق من مسارات SDK وحزم NuGet.
- **أخطاء النشر**: تحقق من مفاتيح التوقيع وملفات التوفير.
- **أخطاء وقت التشغيل**: استخدم المصحح وتحقق من سجلات الجهاز.
---
## ملخص
Xamarin هي منصة قوية لبناء تطبيقات الهاتف المحمول عبر المنصات باستخدام .NET. مميزاتها الرئيسية تشمل:
- **الأداء الأصلي**: يتم ترجمة تطبيقات Xamarin إلى كود أصلي.
- **واجهة مستخدم أصلية**: يوفر Xamarin وصولاً لعناصر التحكم الأصلية.
- **كود مشترك**: مشاركة ما يصل إلى 90% من الكود عبر المنصات.
- **نظام بيئي .NET**: استفد من قوة منصة .NET ونظامها البيئي.
- **Visual Studio**: استخدم بيئة التطوير Visual Studio القوية.
Xamarin خيار رائع للمطورين في .NET الذين يريدون بناء تطبيقات الهاتف المحمول عبر المنصات دون تعلم لغات أو أطر عمل جديدة.
<script>
function copyToClipboard() {
const commands = document.querySelectorAll("code");
let allCommands = "";
commands.forEach(cmd => allCommands += cmd.textContent + "\n");
navigator.clipboard.writeText(allCommands);
alert("تم نسخ جميع الأوامر إلى الحافظة!");
}
function generatePDF() {
window.print();
}
</script>