Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Android için .NET derlemesinin bir parçası olarak Android kaynakları işlenir ve oluşturulan bir _Microsoft.Android.Resource.Designer.dll derleme aracılığıyla Android kimliklerini gösterir.
Örneğin, içeriği olan dosya Reources\layout\Main.axml göz önünde bulundurulduğunda:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android">
<Button android:id="@+id/myButton" />
<fragment
android:id="@+id/log_fragment"
android:name="commonsamplelibrary.LogFragment"
/>
<fragment
android:id="@+id/secondary_log_fragment"
android:name="CommonSampleLibrary.LogFragment"
/>
</LinearLayout>
Ardından derleme zamanında aşağıdakine benzer içeriklere sahip bir _Microsoft.Android.Resource.Designer.dll derleme:
namespace _Microsoft.Android.Resource.Designer;
partial class Resource {
partial class Id {
public static int myButton {get;}
public static int log_fragment {get;}
public static int secondary_log_fragment {get;}
}
partial class Layout {
public static int Main {get;}
}
}
Geleneksel olarak, Kaynaklar ile etkileşim, Resource türü ve FindViewById<T>() yöntemindeki sabitler kullanılarak kodla yapılır.
partial class MainActivity : Activity {
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.myButton);
button.Click += delegate {
button.Text = $"{count++} clicks!";
};
}
}
Xamarin.Android 8.4'den başlayarak, C# kullanırken Android kaynaklarıyla etkileşim kurmanın iki ek yolu vardır:
Bu yeni özellikleri etkinleştirmek için
$(AndroidGenerateLayoutBindings) msbuild komut satırında msBuild özelliği True :
dotnet build -p:AndroidGenerateLayoutBindings=true MyProject.csproj
veya .csproj dosyanızda:
<PropertyGroup>
<AndroidGenerateLayoutBindings>true</AndroidGenerateLayoutBindings>
</PropertyGroup>
Bağlamalar
Bağlama, düzen dosyasındaki tüm kimlikler için kesin olarak yazılan özellikler içeren, Android düzen dosyası başına bir tane olmak üzere oluşturulan bir sınıftır. Bağlama türleri, düzen dosyası adını yansıtan tür adlarıyla global::Bindings ad alanı içinde üretilir.
Bağlama türleri, Android kimlikleri içeren tüm düzen dosyaları için oluşturulur.
Android Düzen dosyası Resources\layout\Main.axmlgöz önünde bulundurulduğunda:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools">
<Button android:id="@+id/myButton" />
<fragment
android:id="@+id/fragmentWithExplicitManagedType"
android:name="commonsamplelibrary.LogFragment"
xamarin:managedType="CommonSampleLibrary.LogFragment"
/>
<fragment
android:id="@+id/fragmentWithInferredType"
android:name="CommonSampleLibrary.LogFragment"
/>
</LinearLayout>
ardından aşağıdaki tür oluşturulur:
// Generated code
namespace Binding {
sealed class Main : global::Xamarin.Android.Design.LayoutBinding {
[global::Android.Runtime.PreserveAttribute (Conditional=true)]
public Main (
global::Android.App.Activity client,
global::Xamarin.Android.Design.OnLayoutItemNotFoundHandler itemNotFoundHandler = null)
: base (client, itemNotFoundHandler) {}
[global::Android.Runtime.PreserveAttribute (Conditional=true)]
public Main (
global::Android.Views.View client,
global::Xamarin.Android.Design.OnLayoutItemNotFoundHandler itemNotFoundHandler = null)
: base (client, itemNotFoundHandler) {}
Button __myButton;
public Button myButton => FindView (global::Xamarin.Android.Tests.CodeBehindFew.Resource.Id.myButton, ref __myButton);
CommonSampleLibrary.LogFragment __fragmentWithExplicitManagedType;
public CommonSampleLibrary.LogFragment fragmentWithExplicitManagedType =>
FindFragment (global::Xamarin.Android.Tests.CodeBehindFew.Resource.Id.fragmentWithExplicitManagedType, __fragmentWithExplicitManagedType, ref __fragmentWithExplicitManagedType);
global::Android.App.Fragment __fragmentWithInferredType;
public global::Android.App.Fragment fragmentWithInferredType =>
FindFragment (global::Xamarin.Android.Tests.CodeBehindFew.Resource.Id.fragmentWithInferredType, __fragmentWithInferredType, ref __fragmentWithInferredType);
}
}
Bağlamanın temel türü, Xamarin.Android.Design.LayoutBinding Android için .NET sınıf kitaplığının bir parçası değildir , bunun yerine kaynak biçiminde Android için .NET ile birlikte gönderilir ve bağlamalar her kullanıldığında uygulamanın derlemesine otomatik olarak eklenir.
Oluşturulmuş bağlama türü Activity örneklerinin etrafında oluşturulabilir ve düzen dosyasındaki kimliklere güçlü türde erişim sağlar.
// User-written code
partial class MainActivity : Activity {
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
var binding = new Binding.Main (this);
Button button = binding.myButton;
button.Click += delegate {
button.Text = $"{count++} clicks!";
};
}
}
Bağlama türleri, View örneklerinin etrafında da oluşturulabilir ve Görünüm veya alt öğelerindeki Kaynak Kimliklerine kesin olarak türlenmiş erişime olanak tanır.
var binding = new Binding.Main (some_view);
Eksik Kaynak Kimlikleri
Bağlama türlerindeki özellikler, hâlâ uygulamalarında FindViewById<T>() kullanır. Eğer FindViewById<T>()null döndürürse, varsayılan davranış, özelliğin null döndürmek yerine InvalidOperationException oluşturmasıdır.
Bu varsayılan davranış, oluşturulan bağlamaya örnek oluşturma sırasında bir hata işleyicisi temsilcisi geçirilerek geçersiz kılınabilir:
// User-written code
partial class MainActivity : Activity {
Java.Lang.Object? OnLayoutItemNotFound (int resourceId, Type expectedViewType)
{
// Find and return the View or Fragment identified by `resourceId`
// or `null` if unknown
return null;
}
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
var binding = new Binding.Main (this, OnLayoutItemNotFound);
}
}
OnLayoutItemNotFound() yöntem, View veya Fragment için kaynak kimliği bulunamadığında çağırılır.
İşleyicinin atanmalı veya tercihen işleyiciye geçirilen kimliğe karşılık gelen null veya Viewörneğini döndürmesi InvalidOperationExceptiongerekirFragment. Döndürülen nesne, karşılık gelen Bağlama özelliğinin türüyle eşleşen doğru türde olmalıdır . Döndürülen değer bu türe döndürülür, bu nedenle nesne doğru yazılmıyorsa bir özel durum oluşturulur.
Code-Behind
Code-Behind, düzen dosyasındaki tüm partial için güçlü şekilde yazılmış özellikler içeren bir sınıfın derleme zamanında oluşturulmasını içerir.
Code-Behind, Bağlama mekanizmasının temeli üzerine inşa edilirken, düzen dosyalarının yeni xamarin:classes XML özniteliğini kullanarak, oluşturulacak tam sınıf adlarının ; ile ayrılmış bir listesi olarak Code-Behind üretimine katılmalarını şart koşar.
Android Düzen dosyası Resources\layout\Main.axmlgöz önünde bulundurulduğunda:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools"
xamarin:classes="Example.MainActivity">
<Button android:id="@+id/myButton" />
<fragment
android:id="@+id/fragmentWithExplicitManagedType"
android:name="commonsamplelibrary.LogFragment"
xamarin:managedType="CommonSampleLibrary.LogFragment"
/>
<fragment
android:id="@+id/fragmentWithInferredType"
android:name="CommonSampleLibrary.LogFragment"
/>
</LinearLayout>
Derleme zamanında aşağıdaki tip oluşturulacak:
// Generated code
namespace Example {
partial class MainActivity {
Binding.Main __layout_binding;
public override void SetContentView (global::Android.Views.View view);
void SetContentView (global::Android.Views.View view,
global::Xamarin.Android.Design.LayoutBinding.OnLayoutItemNotFoundHandler onLayoutItemNotFound);
public override void SetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params);
void SetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params,
global::Xamarin.Android.Design.LayoutBinding.OnLayoutItemNotFoundHandler onLayoutItemNotFound);
public override void SetContentView (int layoutResID);
void SetContentView (int layoutResID,
global::Xamarin.Android.Design.LayoutBinding.OnLayoutItemNotFoundHandler onLayoutItemNotFound);
partial void OnSetContentView (global::Android.Views.View view, ref bool callBaseAfterReturn);
partial void OnSetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params, ref bool callBaseAfterReturn);
partial void OnSetContentView (int layoutResID, ref bool callBaseAfterReturn);
public Button myButton => __layout_binding?.myButton;
public CommonSampleLibrary.LogFragment fragmentWithExplicitManagedType => __layout_binding?.fragmentWithExplicitManagedType;
public global::Android.App.Fragment fragmentWithInferredType => __layout_binding?.fragmentWithInferredType;
}
}
Bu, düzen içinde Kaynak Kimliklerinin daha "sezgisel" bir şekilde kullanılmasını sağlar:
// User-written code
partial class MainActivity : Activity {
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
myButton.Click += delegate {
button.Text = $"{count++} clicks!";
};
}
}
Hata işleyicisi OnLayoutItemNotFound, etkinliğin kullandığı herhangi bir SetContentView aşırı yüklemenin son parametresi olarak geçirilebilir.
// User-written code
partial class MainActivity : Activity {
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main, OnLayoutItemNotFound);
}
Java.Lang.Object? OnLayoutItemNotFound (int resourceId, Type expectedViewType)
{
// Find and return the View or Fragment identified by `resourceId`
// or `null` if unknown
return null;
}
}
Code-Behind kısmi sınıflara dayanır, bu nedenle kısmi bir sınıfın tüm bildirimleri partial class içermelidir, aksi takdirde derleme sırasında bir CS0260 C# derleyici hatası oluşur.
Özelleştirme
Oluşturulan Code Behind türü her zamanActivity.SetContentView() öğesini geçersiz kılar ve varsayılan olarak her zamanbase.SetContentView() çağırır, parametreleri iletir. Bu istenmiyorsa, OnSetContentView()partial yöntemlerinden biri geçersiz kılınmalı ve callBaseAfterReturn ayarı false olarak ayarlanmalıdır.
// Generated code
namespace Example
{
partial class MainActivity {
partial void OnSetContentView (global::Android.Views.View view, ref bool callBaseAfterReturn);
partial void OnSetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params, ref bool callBaseAfterReturn);
partial void OnSetContentView (int layoutResID, ref bool callBaseAfterReturn);
}
}
Örnek Oluşturulan Kod
// Generated code
namespace Example
{
partial class MainActivity {
Binding.Main? __layout_binding;
public override void SetContentView (global::Android.Views.View view)
{
__layout_binding = new global::Binding.Main (view);
bool callBase = true;
OnSetContentView (view, ref callBase);
if (callBase) {
base.SetContentView (view);
}
}
void SetContentView (global::Android.Views.View view, global::Xamarin.Android.Design.LayoutBinding.OnLayoutItemNotFoundHandler onLayoutItemNotFound)
{
__layout_binding = new global::Binding.Main (view, onLayoutItemNotFound);
bool callBase = true;
OnSetContentView (view, ref callBase);
if (callBase) {
base.SetContentView (view);
}
}
public override void SetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params)
{
__layout_binding = new global::Binding.Main (view);
bool callBase = true;
OnSetContentView (view, @params, ref callBase);
if (callBase) {
base.SetContentView (view, @params);
}
}
void SetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params, global::Xamarin.Android.Design.LayoutBinding.OnLayoutItemNotFoundHandler onLayoutItemNotFound)
{
__layout_binding = new global::Binding.Main (view, onLayoutItemNotFound);
bool callBase = true;
OnSetContentView (view, @params, ref callBase);
if (callBase) {
base.SetContentView (view, @params);
}
}
public override void SetContentView (int layoutResID)
{
__layout_binding = new global::Binding.Main (this);
bool callBase = true;
OnSetContentView (layoutResID, ref callBase);
if (callBase) {
base.SetContentView (layoutResID);
}
}
void SetContentView (int layoutResID, global::Xamarin.Android.Design.LayoutBinding.OnLayoutItemNotFoundHandler onLayoutItemNotFound)
{
__layout_binding = new global::Binding.Main (this, onLayoutItemNotFound);
bool callBase = true;
OnSetContentView (layoutResID, ref callBase);
if (callBase) {
base.SetContentView (layoutResID);
}
}
partial void OnSetContentView (global::Android.Views.View view, ref bool callBaseAfterReturn);
partial void OnSetContentView (global::Android.Views.View view, global::Android.Views.ViewGroup.LayoutParams @params, ref bool callBaseAfterReturn);
partial void OnSetContentView (int layoutResID, ref bool callBaseAfterReturn);
public Button myButton => __layout_binding?.myButton;
public CommonSampleLibrary.LogFragment fragmentWithExplicitManagedType => __layout_binding?.fragmentWithExplicitManagedType;
public global::Android.App.Fragment fragmentWithInferredType => __layout_binding?.fragmentWithInferredType;
}
}
Düzen XML Öznitelikleri
Birçok yeni Düzen XML özniteliği, xamarin XML ad alanı (xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools") içinde yer alan Bağlama ve Arkaplan Kod davranışını denetler.
Bunlar şunları içerir:
xamarin:classes
xamarin:classes XML özniteliği, hangi türlerin oluşturulacağını belirtmek için Arka Planda Kod'un bir parçası olarak kullanılır.
xamarin:classes XML özniteliği, oluşturulması gereken ; -ayrılmış bir listesini içerir.
xamarin:managedType
xamarin:managedType düzen özniteliği, bağlı kimliği belirli bir yönetilen tür olarak görünür kılmak amacıyla açıkça belirtmek için kullanılır. Belirtilmezse, tür bildirimde bulunan bağlamdan çıkarılır; örneğin <Button/> , bir Android.Widget.Buttonile sonuçlanır ve <fragment/> bir Android.App.Fragmentile sonuçlanır.
xamarin:managedType özniteliği daha açık tür bildirimlerine izin verir.
Yönetilen tür eşlemesi
Pencere öğesi adlarının geldikleri Java paketine göre kullanılması oldukça yaygındır ve aynı sıklıkta, bu tür yönetilen .NET adının yönetilen alanda farklı bir (.NET stili) adı olacaktır. Kod oluşturucu, kodu eşleştirmeye çalışmak için aşağıdakiler gibi çok basit ayarlamalar gerçekleştirebilir:
Tür ad alanı ve adının tüm bileşenlerini büyük harfle başlat. Örneğin
java.package.myButton,Java.Package.MyButtonolurTür ad alanının iki harfli bileşenlerini büyük harfe çevirin. Örneğin
android.os.SomeType,Android.OS.SomeTypeolurBilinen eşlemeleri olan birkaç sabit kodlanmış ad alanını bulun. Liste şu anda aşağıdaki eşlemeleri içerir:
-
android.view->Android.Views -
com.actionbarsherlock->ABSherlock -
com.actionbarsherlock.widget->ABSherlock.Widget -
com.actionbarsherlock.view->ABSherlock.View -
com.actionbarsherlock.app->ABSherlock.App
-
İç tablolarda sabit kodlanmış bir dizi türü arayın. Liste şu anda aşağıdaki türleri içerir:
-
WebView->Android.Webkit.WebView
-
Sabit kodlanmış ad alanı ön eklerinin sayısını çıkarın. Liste şu anda aşağıdaki ön ekleri içerir:
com.google.
Ancak, yukarıdaki girişimler başarısız olursa, eşlenmemiş türe sahip bir pencere öğesi kullanan düzeni değiştirmeniz gerekir; bunun için XML ad alanı bildirimini düzenin kök öğesine ve eşleme gerektiren öğeye xamarin ve xamarin:managedType eklemelisiniz. Örneğin:
<fragment
android:id="@+id/log_fragment"
android:name="commonsamplelibrary.LogFragment"
xamarin:managedType="CommonSampleLibrary.LogFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Yerel tür commonsamplelibrary.LogFragment için CommonSampleLibrary.LogFragment türünü kullanacak.
XML ad alanı bildirimini ve xamarin:managedType özniteliğini eklemekten kaçınmak için türü yönetilen adını kullanarak adlandırabilirsiniz; örneğin üstteki bölüm aşağıdaki gibi yeniden ifade edilebilir:
<fragment
android:name="CommonSampleLibrary.LogFragment"
android:id="@+id/secondary_log_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Parçalar: özel bir durum
Android ekosistemi şu anda pencere öğesinin Fragment iki ayrı uygulamasını destekler:
-
Android.App.FragmentTemel Android sistemiyle birlikte gelen "klasik" Fragment -
AndroidX.Fragment.App.FragmentİçindeXamarin.AndroidX.FragmentNuGet paketi.
Bu sınıflar birbiriyle uyumlu değildir ve bu nedenle düzen dosyalarındaki öğeler için <fragment> bağlama kodu oluşturulurken özel özen gösterilmelidir. Android için .NET, <fragment> öğesinde belirli bir tür (yönetilen veya başka bir şekilde) belirtilmediği takdirde, varsayılan olarak kullanılacak Fragment uygulamasını seçmelidir. Bağlama kodu oluşturucu,
$(AndroidFragmentType) Bu amaç için MSBuild özelliği. Özelliği kullanıcı tarafından geçersiz kılınarak varsayılandan farklı bir tür belirtilebilir. Özellik varsayılan olarak Android.App.Fragment ayarlanır ve AndroidX NuGet paketleri tarafından geçersiz kılınır.
Oluşturulan kod derlenmiyorsa, düzen dosyasının ilgili parçanın yönetilen türü belirtilerek güncellenmesi gerekir.
Arka plan düzeni seçimi ve işlemesi
Seleksiyon
Varsayılan olarak arka planda kod oluşturma devre dışıdır. En az tek bir öğe üzerinde //*/@android:id özniteliği bulunan dizinlerden herhangi birindeki tüm düzenlerde işlemeyi etkinleştirmek için $(AndroidGenerateLayoutBindings) MSBuild özelliğini msbuild komut satırında True olarak ayarlayın.
dotnet build -p:AndroidGenerateLayoutBindings=true MyProject.csproj
veya .csproj dosyanızda:
<PropertyGroup>
<AndroidGenerateLayoutBindings>true</AndroidGenerateLayoutBindings>
</PropertyGroup>
Alternatif olarak, kodu genel olarak devre dışı bırakabilir ve yalnızca belirli dosyalar için etkinleştirebilirsiniz. Belirli .axml bir dosya için Code-Behind etkinleştirmek için, dosyayı Build eylemine sahip olacak şekilde değiştirin
@(AndroidBoundLayout) dosyanızı düzenlemek için AndroidResource ile AndroidBoundLayout değiştirerek .csproj dosyanızı düzenleyin.
<!-- This -->
<AndroidResource Include="Resources\layout\Main.axml" />
<!-- should become this -->
<AndroidBoundLayout Include="Resources\layout\Main.axml" />
Processing
Düzenler isimlerine göre gruplandırılır ve tek bir grubu oluşturan farklıResource\layout* dizinlerdeki benzer adlı şablonlar yer alır. Bu tür gruplar tek bir düzenmiş gibi işlenir. Bu durumda, aynı gruba ait farklı düzenlerde bulunan iki pencere öğesi arasında tür çakışması olması mümkündür. Böyle bir durumda oluşturulan özellik tam pencere öğesi türüne sahip olamaz, bunun yerine "çürümüş" bir pencere öğesi türüne sahip olamaz. Çürüyen aşağıdaki algoritmayı izler:
Çakışan pencere öğelerinin hepsi türev ise
View, özellik türüAndroid.Views.ViewÇakışan türlerin tümü türevse
Fragment, özellik türüAndroid.App.FragmentÇakışan pencere öğeleri hem
Viewhem deFragmentiçeriyorsa, özellik türüglobal::System.Objectolur.
Oluşturulan kod
Oluşturulan kodun düzenleriniz için nasıl göründüğünü merak ediyorsanız, lütfen çözüm dizininizdeki obj\$(Configuration)\generated klasörüne göz atın.