IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

2. diel - Vlastné Android komponent - Dokončenie textového poľa

V minulej lekcii, Vlastné Android komponent - Vytvorenie a usadenie do layoutu , sme vytvorenú komponent usadili do layoutu.

V tejto lekcii nadviažeme tým, že si ukážeme použitie atribútov vlastnej textovej komponenty v praxi.

Dokončenie vlastného textového poľa

Budeme pokračovať v našom postupe, čakajú nás parametre komponenty.

Použitia vytvorených parametrov a nastavení komponenty

Najprv poďme dostať parametre z XML rozloženie do triedy reprezentujúci vlastnej View.

Načítanie parametrov

V triede CustomInput sme si zatiaľ ukázali len konštruktory. Ako už bolo spomenuté, tieto parametre získame v konstruktoru z parametra attrs. Teraz si napíšeme metódu, ktorá sa postará o spracovaní našich vlastných atribútov prevzatých z XML:

String text = null;                    // Text zadávacího pole
String titleText = null;               // Text nad zadávacím polem
String errText = null;                 // Text chybové hlášky
String requiredText = null;            // Textový řetězec, který zadaný text musí obsahovat
int requiredNumberOfCharacters = 0;    // Minimální počet zadaných znaků

private void applyAttributeSet(AttributeSet attrs) {
    if (attrs == null) return;

    TypedArray ta = getContext().getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.CustomInput,
            0,
            0);

    if (ta == null) return;

    try {
        text = ta.getString(R.styleable.CustomInput_ciText);
        titleText = ta.getString(R.styleable.CustomInput_ciTitleText);
        errText = ta.getString(R.styleable.CustomInput_ciErrText);
        requiredText = ta.getString(R.styleable.CustomInput_ciRequiredText);
        requiredNumberOfCharacters = ta.getInteger(
                R.styleable.CustomInput_ciRequiredNumberOfCharacters,
                0);
    } finally {
        ta.recycle();
    }
}

Na začiatku metódy vytvárame inštanciu TypedArray, z ktorej následne získavame samotnej atribúty a ukladáme ich do pripravených premenných. Všimnite si, akým spôsobom získavame jednotlivé parametre - jedná sa o názov vzniknutý zloženinou dvoch "slov" oddelených podčiarknikom (napr. CustomInput_ciText). Tento názov teda obsahuje:

  • Atribút name v hlavičke v súbore attrs.xml (<declare-styleable name="CustomInput">)
  • Názov parametra (deklarovaný v attrs.xml)
Zavolanie metódy

Volanie vytvorené metódy applyAttributeSet(AttributeSet attrs) pridáme do všetkých konstruktoru, ktoré sú používané pri konfigurácii objektu v XML rozvrhnutie, teda do všetkých konstruktoru okrem toho prvého a to takto:

applyAttributeSet(attrs);

Spracovanie parametrov

Parametre máme z XML načítané v triede v premenných, teraz je potreba pomocou získaných atribútov inicializovať našu komponent. V tejto súvislosti si napíšeme metódu init().

V tejto metóde nastavíme všetkým prvkom požadované parametre. Nastavíme tak text v hlavičke, text chybové hlášky, prípadne aj predvolený text komponenty EditText. Nasleduje nastavenie Listener pre EditText. Listener bude strážiť zmeny obsahu EditText a za behu bude kontrolovať splnenie zadaných podmienok. Ak Listener usúdi, že zadaný text nezodpovedá nastaveným požiadavkám, zobrazí červený text s chybovým hlásením.

Kód metódy je nasledovné:

View rootView;
TextView labelTitleText;
TextView labelErrText;
EditText etInput;

private void init() {
    // Získání XML rozvržení vlastního View
    rootView = inflate(getContext(), R.layout.my_input, this);

    // Proměnné pro objekty vlastního View, se kterému chceme pracovat
    labelTitleText = rootView.findViewById(R.id.labelTitleText);
    labelErrText = rootView.findViewById(R.id.labelErrText);
    etInput = rootView.findViewById(R.id.etInput);

    if (titleText != null) {
        labelTitleText.setText(titleText);
    } else {
        labelTitleText.setText("");
    }

    if (errText != null) {
        labelErrText.setText(errText);
    } else {
        labelErrText.setText("");
    }

    // "Odposlouchávač" změn textu
    etInput.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        @Override
        public void afterTextChanged(Editable editable) {
            String inputText = editable.toString().toLowerCase();
            boolean showError = false;

            if (inputText.equals("")) {
                hideErrText();
                return;
            }

            if (requiredText != null) {
                if (!requiredText.equals("")) {
                    if (!inputText.contains(requiredText)) {
                        showError = true;
                    }
                }
            }

            if (requiredNumberOfCharacters > 0) {
                if (inputText.length() < requiredNumberOfCharacters) {
                    showError = true;
                }
            }

            if (showError) {
                showErrText();
            } else {
                hideErrText();
            }
        }
    });
}
Zavolanie metódy

Volanie metódy init() takisto vložíme do konstruktoru našej komponenty. Na rozdiel od predchádzajúcej metódy metóda init() bude volaná vo všetkých konstruktoru. Poďme si pre úplnosť radšej ukázať, ako konštruktory vyzerajú:

public CustomInput(Context context) {
    super(context);
    init();
}

public CustomInput(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    applyAttributeSet(attrs);
    init();
}

public CustomInput(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    applyAttributeSet(attrs);
    init();
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CustomInput(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    applyAttributeSet(attrs);
    init();
}

Práca s komponentom

Teraz sa pozrieme na to, ako vyzerá práca s vlastnou komponentom, ktorá bola vložená do XML. Pôjde o prácu z Java kódu aplikácie:

// Získání reference na objekt v XML
customInput1 = findViewById(R.id.myCustomInput1);

// Programové nastavení atributů.
customInput1.setTitleText("Title");
customInput1.setErrText("Error text");
customInput1.setRequiredText("required text");

Vytvorenie komponenty programovo

Ešte si ukážeme, ako náš objekt vytvoriť programovo, teda bez vkladanie do XML aplikácie:

newCustomInput = new CustomInput(context);
newCustomInput.setTitleText("Ahoj! Napiš alespoň dva znaky!");
newCustomInput.setErrText("Toto je málo...");
newCustomInput.setRequiredNumberOfCharacters(2);

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT);

params.setMargins(dipToPx(10), dipToPx(10), dipToPx(10), dipToPx(10));
newCustomInput.setLayoutParams(params);
layout.addView(newCustomInput);

Pri nastavovaní margine nového objektu sme použili metódu dipToPx(). Pretože v triede nášho objektu View pracujeme so základnou rozmerovú jednotkou (pixel) a v kóde chceme pracovať s jednotkou dip, je nutné zaistiť prevod hodnoty dip na pixel, čo zaistí táto metóda:

public int dipToPx(float dpValue) {
    final float scale = getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
}

Uloženie stavu vlastného View

Predpokladám, že vám nie je úplne cudzí problematika ukladanie stavu aplikácie, napríklad, počas otočenie telefónu (tabletu). Ukladanie stavu vlastného View je veľmi podobné. Platí pravidlo, že systém Android automaticky ukladá stav defaultných View. Ale iba ak majú nastavené ID. Keď ukážkovej zadávacie pole vložíme do nejakého projektu, spustíme aplikáciu a zadáme do neho nejaký text, bude si EditText, ktorý je súčasťou zadávacieho poľa, obsah pamätať aj po otočení telefónu. Pokiaľ ale vytvoríme viac inštancií vytvoreného View do jedného layoutu, nastane problém.

Tejto problematike budeme venovať samostatný článok, pretože informácií je pomerne veľa. Tu problém otočenie zmieňujem pre tých, ktorí sa hneď pustí do testovania a do popísanej situácie sa dostanú. Nie je to teda chyba:-)

Vysvetlenie nájdete na konci tohto kurzu, v samostatných článkoch, v ktorých si túto problematiku podrobne vysvetlíme a naučíme sa ovládať uchovávanie stavu objektov, ktoré sú potomkami triedy View.

V budúcej lekcii, Spinner - Príprava pre vytvorenie obrázkových položiek , si pripravíme XML a vlastné Java triedu pre Spinner s obrázkami položiek.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 6x (18.05 MB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Vlastné Android komponent - Vytvorenie a usadenie do layoutu
Všetky články v sekcii
Vlastné View pre Android aplikácie
Preskočiť článok
(neodporúčame)
Spinner - Príprava pre vytvorenie obrázkových položiek
Článok pre vás napísal Pavel
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje programování v Javě, hlavně pro Android. Mezi jeho další zájmy patří Arduino, Minecraft.
Aktivity