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, ...