Projekt Android App (Xamarin), nazwa: Kolory Blank App Android 7.1 (Nougat) 1. Plik activity_main.axml 2. Plik MainActivity.cs using Android.App; using Android.Widget; using Android.OS; using Android.Support.V7.App; using Android.Graphics; //<------ namespace Kolory { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { //pola private TextView etykieta_panel; //Label, pełni też rolę panela private SeekBar seekBarR, seekBarG, seekBarB; //TrackBar protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); etykieta_panel = (TextView)FindViewById(Resource.Id.etykieta_panel); seekBarR = (SeekBar)FindViewById(Resource.Id.seekBarR); seekBarG = (SeekBar)FindViewById(Resource.Id.seekBarG); seekBarB = (SeekBar)FindViewById(Resource.Id.seekBarB); seekBarR.ProgressChanged += SeekBar_ProgressChanged; seekBarG.ProgressChanged += SeekBar_ProgressChanged; seekBarB.ProgressChanged += SeekBar_ProgressChanged; } private void SeekBar_ProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e) { int r = seekBarR.Progress; int g = seekBarG.Progress; int b = seekBarB.Progress; etykieta_panel.SetBackgroundColor(Color.Argb(255, r, g, b)); etykieta_panel.Text = "Składowe koloru: " + r.ToString("X2").ToUpper() + " " + g.ToString("X2").ToUpper() + " " + b.ToString("X2").ToUpper() + " ", TextView.BufferType.Normal); int jasnosc = (r + g + b) / 3; if (jasnosc > 127) etykieta_panel.SetTextColor(Color.Black); //zamiast tej konstrukcji użyć operator warunkowy (studenci) else etykieta_panel.SetTextColor(Color.White); } } } * Zamiast metody etykieta_panel.SetText można też użyć własności etykieta_Panel.Text = "Składowe.... ** Skompiluj, uruchom i przetestuj 4. Zmieńmy tło suwaków tak, żeby każdy miał kolor odpowiadający składowej którą zmienia. Użyjemy do tego liniowego gradientu. W metodzie MainActivity.onCreate umieśćmy polecenia: //konfigurowanie suwaków z poziomu kodu float promien = 8; float[] zewnetrznePromienie = new float[] { promien, promien, promien, promien, promien, promien, promien, promien }; RoundRectShape rrs = new RoundRectShape(zewnetrznePromienie, null, null); ShapeDrawable sdR = new ShapeDrawable(rrs); sdR.Paint.SetShader(new LinearGradient(0, 0, 200, 0, Color.Black, Color.Red, Shader.TileMode.Clamp)); seekBarR.ProgressDrawable = sdR; ShapeDrawable sdG = new ShapeDrawable(rrs); sdG.Paint.SetShader(new LinearGradient(0, 0, 200, 0, Color.Black, Color.Green, Shader.TileMode.Clamp)); seekBarG.ProgressDrawable = sdG; ShapeDrawable sdB = new ShapeDrawable(rrs); sdB.Paint.SetShader(new LinearGradient(0, 0, 200, 0, Color.Black, Color.Blue, Shader.TileMode.Clamp)); seekBarB.ProgressDrawable = sdB; ** Skompiluj, uruchom i przetestuj 5. Ostatnim elementem będzie rozwijana lista (Spinner) a. Do activity_main.xml dodajmy: * Jeżeli trzeba, w TextView zmieniamy wysokość android:layout_height="150dip", żeby nową kontrolkę było widać b. Jego własność prompt to łańcuch, który musi być zdefiniowany w pliku Resources/values/strings.xml: Kolory Ponadto tworzymy plik Resources/values/tablica_kolorow.xml, w którym umieszczamy tablicę łańcuchów: Wskazany przez suwaki Czarny Biały Czerwony Zielony Niebieski Turkusowy Purpurowy Żółty Szary c. W pliku MainActivity.java, w klasie MainActivity zdefiniujmy pola private Spinner spinner; //ComboBox private bool czyUstawicSpinnerNaSuwaki = true; Drugie pole będzie regulowało uaktualnianiem suwaków i rozwijanej listy. Poruszenie suwaków spowoduje ustawienie listy na "Wskazany przez suwaki". d. W metodzie MainActivity.onCreate dodajmy polecenia: //rozwijana lista spinner = (Spinner)FindViewById(Resource.Id.spinner); ArrayAdapter adapter = ArrayAdapter.CreateFromResource( this, Resource.Array.kolory, Android.Resource.Layout.SimpleSpinnerItem); adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem); spinner.Adapter = adapter; spinner.ItemSelected += Spinner_ItemSelected; spinner.SetSelection(9); e. Zdarzenie kliknięcia elementu rozwijanej listy: private void Spinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e) { czyUstawicSpinnerNaSuwaki = false; switch (e.Position) { case 0: break; case 1: //czarny seekBarR.Progress = 0; seekBarG.Progress = 0; seekBarB.Progress = 0; break; case 2: //biały seekBarR.Progress = 255; seekBarG.Progress = 255; seekBarB.Progress = 255; break; case 3: //czerwony seekBarR.Progress = 255; seekBarG.Progress = 0; seekBarB.Progress = 0; break; case 4: //zielony seekBarR.Progress = 0; seekBarG.Progress = 255; seekBarB.Progress = 0; break; case 5: //niebieski seekBarR.Progress = 0; seekBarG.Progress = 0; seekBarB.Progress = 255; break; case 6: //turkusowy seekBarR.Progress = 0; seekBarG.Progress = 255; seekBarB.Progress = 255; break; case 7: //purpurowy seekBarR.Progress = 255; seekBarG.Progress = 0; seekBarB.Progress = 255; break; case 8: //żółty seekBarR.Progress = 255; seekBarG.Progress = 255; seekBarB.Progress = 0; break; case 9: //szary seekBarR.Progress = 127; seekBarG.Progress = 127; seekBarB.Progress = 127; break; } czyUstawicSpinnerNaSuwaki = true; } f. I wreszcie do metody SeekBar_ProgressChanged dodajmy (na samym końcu) polecenie: if (czyUstawicSpinnerNaSuwaki) spinner.SetSelection(0); -------------------------------------------------------------------------- Ustawienia - trwałe przechowywanie stanu aplikacji Zob. plik: activity_lifecycle.png 1. W klasie MainActivity przygotuj dwie metody pomocnicze: #region Ustawienia private void zapiszStan() { ISharedPreferencesEditor edytorUstawien = PreferenceManager.GetDefaultSharedPreferences(this).Edit(); edytorUstawien.PutInt("SkladowaR", seekBarR.Progress); edytorUstawien.PutInt("SkladowaG", seekBarG.Progress); edytorUstawien.PutInt("SkladowaB", seekBarB.Progress); edytorUstawien.Commit(); } private bool odtworzStan() { ISharedPreferences ustawienia = PreferenceManager.GetDefaultSharedPreferences(this); seekBarR.Progress = ustawienia.GetInt("SkladowaR", 0); seekBarG.Progress = ustawienia.GetInt("SkladowaG", 0); seekBarB.Progress = ustawienia.GetInt("SkladowaB", 0); return ustawienia.Contains("SkladowaR") && ustawienia.Contains("SkladowaG") && ustawienia.Contains("SkladowaB"); } #endregion 2. Nadpisz metodę onPause klasy bazowej Activity: protected override void OnPause() { base.OnPause(); zapiszStan(); } 3. Na końcu metody onCreate dodaj wywołanie metody odtworzStan: if (!odtworzStan()) spinner.SetSelection(9); -------------------------------------------------------------------------- Lokalizacja aplikacji poprzez zasoby 1. Na wstępie zmieńmy trochę metodę seekBarChangeListener.onProgressChanged (dodajemy HSV) private void SeekBar_ProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e) { int r = seekBarR.Progress; int g = seekBarG.Progress; int b = seekBarB.Progress; float[] hsvComponents = { 0f, 0f, 0f }; Color.RGBToHSV(r, g, b, hsvComponents); string rgb = r.ToString("X2").ToUpper() + " " + g.ToString("X2").ToUpper() + " " + b.ToString("X2").ToUpper() + " "; string hsv = (Java.Lang.Math.Round(100 * hsvComponents[0]) / 100f).ToString() + " " + (Java.Lang.Math.Round(100 * hsvComponents[1]) / 100f).ToString() + " " + (Java.Lang.Math.Round(100 * hsvComponents[2]) / 100f).ToString(); etykieta_panel.SetBackgroundColor(Color.Argb(255, r, g, b)); etykieta_panel.SetText( "Składowe koloru: \nRGB: " + rgb + "\nHSV: " + hsv, TextView.BufferType.Normal); int jasnosc = (r + g + b) / 3; if (jasnosc > 127) etykieta_panel.SetTextColor(Color.Black); else etykieta_panel.SetTextColor(Color.White); if (czyUstawicSpinnerNaSuwaki) spinner.SetSelection(0); } 2. Porządkujemy layout: a. W Resources/layout/activity_main.xml: zamiast TextView, android:text wskazanego bezpośrednio używamy referencji do łańcuchu umieszczonego w zasobach: b. W konsekwencji do Resources/values/strings.xml dodajemy wpis o nazwie etykieta oraz inne, których użyjemy, a przy okazji "spalszczamy" pozostałe wpisy: Kolory Ustawienia Kolory Składowe koloru 3. Aby skorzystać z zasobów nie tylko w kodzie XML (statycznie), ale również z poziomu kodu Java (dynamicznie) zmieniamy kod metody SeekBar_ProgressChanged, a dokładnie metody zmieniającej etykietę: etykieta_panel.SetText( this.GetString(Resource.String.etykieta) + ": " + "\nRGB: " + rgb + "\nHSV: " + hsv, TextView.BufferType.Normal); ** Uruchom i przetestuj aplikację 4. Właściwą lokalizację przeprowadzamy powielając katalog res/values. a. Zmieńmy nazwę katalogu value na values-pl (klawisz F2). b. Tworzymy katalog values i kopiujemy do niego pliki strings.xml i tablica_kolorow.xml (kopiowanie z klawiszem Ctrl) c. Przenosimy do niego też trzy pozostałe pliki: colors.xml, styles.xml i ic_launcher_background.xml d. Edytujemy pliki z katalogu values (nie values-pl) umieszczając w nim angielskie tłumaczenia: strings.xml Colors Settings Colors Color components tablica_kolorow.xml: Choosen with spinners Black White Red Green Blue Cyan Magenta Yellow Gray values - katalog domyślny, używany jeżeli nie znajdziemy katalogu values-KOD (pl,en,fr,de, itd.) odpowiedniego dla języka domyślnego systemu. * Zmiana języka domyślnego w emulatorze (w systemie Android): Stary Android (polski): Naciskamy klawisz "Menu" Z menu wybieramy "Ustawienia" Z listy wybieramy "Język i klawiatury" "Wybierz język" Następnie możemy wybrać jeden z języków (krajów). Nowy Android: Ustawienia, Languages & Input, Languages, Add Language, itd. Ustawienia, Języki i metody wprowadzania, Języki, Dodaj język, ...