Xamarin Forms Maps: Nagyításra szánt gombok eltűntetése

Androidon default megjelennek a Xamarin.Forms.Maps.Map használata esetén a nagyításra szánt + és – gombok, illetve a felhasználó aktuális pozíciójára mozgató gomb.
Ezeknek eltűntetéséhez egy CustomMapRenderer-t kell létrehozni, és az Androidos rendererben be kell állítani a térképen, hogy ne jelenlítse meg ezeket a plusz gombokat.

Xamarin Forms kód:

public class CustomMap : Map
    {
        public CustomMap(MapSpan region) : base(region)
        {
        }
    }

Xamarin.Android kód:

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]

namespace SampleApp.Droid.Renderers
{
    public class CustomMapRenderer : MapRenderer
    {
		protected override void OnMapReady(GoogleMap map)
		{
			base.OnMapReady(map);
			// Nagyításhoz gombok 
			map.UiSettings.ZoomControlsEnabled = false;
			// Saját helyzet gombok
			map.UiSettings.MyLocationButtonEnabled = false;
		}
    }
}

Word Capitalisation Xamarin Forms Entryben

Amennyiben azt szeretnénk, hogy minden szóköz leütése után automatikusan nagybetűvel kezdje a szavakat a készülék-billentyűzet abban az esetben el kell nevezni az Entry-t, jelen esetben az Entryből származtatott UserControlt.

<blackandyellowdesign:UnderlinedEntryWithLabelOnRight
                    x:Name="FullNameEntry"
                    Placeholder="{markupextensions:Multilanguage TranslationKey=PlaceholderRegisterViewName}"
                    Text="{Binding Path=FullName}" />

Így hivatkozható CodeBehindban FullNameEntry-ként.

A konstruktorban (vagy tetszőleges helyre, valamilyen trigger esetén) pedig be kell állítani a Keyboard tulajdonságát, a Keyboard osztály statikus “Create” metódusának meghívásával.

        FullNameEntry.Keyboard = Keyboard.Create(KeyboardFlags.CapitalizeWord);

Xamarin Forms: Ismerkedés a CustomUserControllokkal

Aki a Xamarin fejlesztésben kipróbálta magát, az könnyen találkozhatott azzal a problémával hogy valamit nem tud megvalósítani, mert nem ad rá a rendszer kész usercontrolt.

Prológus:


Nem rég azzal a problémával szembesültem, hogy a Xamarin Formsban elérhető ListView-nak a ContextActions menüjének láthatósága nem szabályozható. A ContextActions menu egy ListView elem hosszan nyomására jelenik meg. Ez tulajdonképpen egy lista MenuItem objektumokból. Ennek segítségével indíthatunk Commandokat a kiválasztott ListView elemét továbbadva. Azonban felmerülhet olyan igény, hogy szabályozhatóvá tehessük a hosszan nyomásra előtűnő menünk láthatóságát. Erre sajnos nincs lehetőségünk, csak különféle workaroundokkal. Rengeteg utánakeresés után arra jutottam, hogy a DataTemplate gyerekének, a ViewCell-nek az IsEnabled tulajdonsága tulajdonképpen letiltja a hosszan nyomást. Ez működött, adatköthettem a ViewModel-ben szereplő UI mód tulajdonságra, így a ContextMenü már csak akkor jelent meg, ha a UI mód szerkesztés módra volt állítva, megtekintés módon természetesen nem voltak elérhetőek a ContextMenüben szereplő adatmanipuláló gombok. És ekkor jött az igény. Mégpedig az, hogy szerkesztés módban jöjjenek elő az adatmanipuláló gombok, emellett megtekintés módban az elemre kattintva hajtódjon végre egy másik parancs. Erre gondoltam azt, hogy a SelectedItem tulajdonságnak Setter ága tökéletes lessz számomra. Mivel a ViewCell IsEnabledje megtekintés módban false volt, ezért a SelectedItem sem állítódott rajta. Az igény viszont az, hogy megtekintés módban csak a ContextMenü ne legyen elérhető, a lista elemre való kattintás viszont igen. Csak időközben felmerült még egy probléma: Ameddig a lista tartalmát nem frissítettem, addig a ContextMenü egy gombjára kattintva a Commandnak átadott paraméter null volt, és nem a ListView hosszan nyomott eleme. Ezek együttese igencsak nagy problémának tűnt számomra. Aztán rászántam magam a megoldására: A turbósított usercontrol fejlesztésére.

Megoldás:
Először azt szerettem volna megoldani, hogy ne a SelectedItem setter ágában kelljen végrehajtanom azt a logikát, amit akkor kell futtatnom, amikor a felhasználó rányom egy elemre. Továbbá a SelectedItem nem változik meg, ha a felhasználó ugyanarra az elemre nyom a listában. Leszármaztattam egy “ExtendedListView-t” a ListView osztályból. Új controlom konstruktorában feliratkoztam az ősosztály ItemTapped eseményére. Létrehoztam egy Bindolható Propertyt, ami várja azt a parancsot, amelyet végre kell majd hajtania. Az ItemTapped eseménykezelőjében pedig a szükséges vizsgálatok után megfuttatom a Commandot. Ezzel a felhasználó kétszer is rányomhat ugyanarra az elemre.

A másik nehezebb dolog a ContextActions menü eltüntetése volt. Tudtam, ha a ContextActions listája üres, hosszan nyomására nem jelenik meg semmi. Ha legalább egy elem van benne, akkor már megjelenik. Leszármaztam egy ViewCell objektumból. Létrehoztam egy ContextActionsEnabled bindolható tulajdonságot. Ennek a tulajdonságnak változására iratkoztam fel egy eseménykezelővel. Létrehoztam egy privát field-et, ami MenuItem-eket tárol. Sajnos nem találtam a Xamarinban a WPF-hez hasonló Initalized eseményt, így nem tudtam arra feliratkozni, hogy a Control beállítódott. Ez azért volt probléma, mert a tervem az volt, hogy XAML-ben definiálom hogy milyen MenuItemek vannak a ContextActionsben, majd amint a Control befejezte a beállítódását, eltárolom a MenuItemeket, a privát fieldemben. Így csak a ContextActionsEnabled változására kellett volna egy eseménykezelést írnom. Amennyiben a ContextActionsEnabled true értéket kap, abban az esetben beleteszem az ősosztály ContextActions tulajdonságába a fieldemben tárolt MenuItemeket, amennyiben false értéket kap, abban az esetben pedig eltávolítom az összeset ami benne van (az ősosztály ContextActions tulajdonságában). Mivel nem volt Initalized esemény, kénytelen voltam a ContextActionsEnabled megváltozásának eseménykezelőjébe beletenni azt, hogy első alkalommal tárolja el a field-be az eredeti XAML-ben definiált értékeket. Ez azt eredméynezi, hogy ha előbb definiáljuk XAML-ben a ContextActionsEnabled Propertyt, mint magát a ContextActions-t, nem fog működni. Erre még jó lenne egy jobb megoldást hallani. Ha van rá ötleted, kérlek jelezd azt kommentben!


Nem jártam utána, de miután a ViewCell IsEnabledjéről lekerült a Bindolás, a ContextMenü commandjai már soha többé nem kaptak null értéket.

Xamarin Forms: XAML hibák feltárása

Aki ismerkedett a Xamarin Forms-szal, bizonyára észrevette, hogy a XAML fájl futásidőben értékelődik ki. Ez fejlesztés közben hatalmas hátrányt jelent a fejlesztő számára, hiszen egy hibásan megírt XAML fájl csak a debug folyamat közben bukik ki.

A szintaktikailag hibás fájl

Emiatt szükség volt egy megoldásra, annak érdekében, hogy a fordítási időben kapjunk hibát a szintaktikailag nem helyes kódról.

A XAML Compilation azonnal köztes nyelvre fordítja a felületet leíró fájlokat. Erről a továbbiakban itt olvashatsz: https://developer.xamarin.com/guides/xamarin-forms/xaml/xamlc/

[assembly: XamlCompilation (XamlCompilationOptions.Compile)]

Valami nem klappol!

Az attribútum használata az app.xaml.cs-ben a namespace-en attribútumként:

 

(Archived post from: 2017.08.12)

 

Xamarin Forms: Nem fordul az újonnan létrehozott solution androidos projektje

Prológus:

A cégnél elsők között lehettem, akik a Xamarin fejlesztés rejtelmeibe áshatták bele magukat. Hogy megelőzzek más fejlesztőknek akár órás fejfájásokat, írásba öntöm tapasztalataimat.

Tézis:
Az újonnan létrehozott Xamarin Forms Solution Androidos projektjének futtatásánál a hasonló hibaüzenetekkel találkozhatunk:

Hibaüzenetek a friss projektnél

A Solution NuGet Csomagjait vizsgáljuk meg először.

Vegyük szemügyre a Xamarin.Forms nevű csomagot, egész pontosan annak a Dependencies résznél található csomagok verzió igényeit.

Xamarin Forms package Dependencies

Láthatjuk, hogy (például) a Xamarin.Android.Support.Design csomag verziószámának meg kell egyezni a 23.3.0 verzióval. Gyanakodhatunk arra, hogy eltérő csomag verziók vannak telepítve. A Xamarin.Android.Support.Design csomag nevére kattintva pedig meggyőződhetünk erről.

A nem megfelelő csomag van telepítve

Frissítsük a NuGet package-t a helyes verzióra. Ellenőrizzük az összes csomagot, majd futtassuk az Androidos projektet.

 

(Archive post from 2017.08.12)