Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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í.

Multi-touch a další nové funkce kreslení v Javě pro Android

V minulém Android tutoriálu jsme si naprogramovali jednoduché kreslení prstem. Dnes máme slíbeno, že aplikaci vylepšíme.

Multi-touch

Protože jsme nároční, přidáme si jednoduše možnost multi-touche, tedy kreslení více prsty najednou. Pomocí následujícího kódu si zjistíme kolik prstů je na displeji:

final int pointersCount = event.getPointerCount();

V onTouchEvent() je poté jen projedeme cyklem a přiřazujeme jejich pozice:

for (int p = 0; p < pointersCount; p++) {
    xPos = event.getX(p);
    yPos = event.getY(p);
    ...
}

Kompletní kód metody si ukážeme za moment.

Vykreslení tečky

Možná jste si již všimli, že když pouze klepneme prstem, nevykreslí se tečka, jak bychom možná očekávali. Pojďme to napravit. Vykreslení tečky jednoduše přidáme do ACTION_DOWN přidáním pohybu o jeden pixel:

path.lineTo(xPos + 1, yPos + 1);

Celý aktualizovaný kód metody onTouchEvent() je nyní následující:

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Inicializace proměnných pro ukládání pozice dotyku
    float xPos;
    float yPos;
    // Počet prstů, kterými se dotýkáme obrazovky. Maximum je (asi v závislosti na zařízení) limitováno na 4
    final int pointersCount = event.getPointerCount();

    // Projede všechny pointery - umožňuje multi-touch
    for (int p = 0; p < pointersCount; p++) {
        xPos = event.getX(p);
        yPos = event.getY(p);
        // Zpracování akcí
        switch (event.getAction()) {
            // Při dotyku, se vyresetuje výchozí pozice
            case MotionEvent.ACTION_DOWN:
                path.moveTo(xPos, yPos);
                path.lineTo(xPos + 1, yPos + 1);
                break;

            // Při pohybu nebo opuštění obrazovky
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                // Nastaví se současné souřadnice
                path.lineTo(xPos, yPos);
                break;
        }
    }

    // Překreslení
    invalidate();

    return true;
}

Čištění plátna

Teď už se s tím dá pěkně vyhrát :) Nyní si vytvoříme metodu na čištění plátna. Nazvěme ji clearCanvas(). Jednoduše vymažeme souřadnice cesty a překreslíme:

public void clearCanvas() {
    path.reset();
    invalidate();
}

Nyní aplikaci naučíme používat menu. Nejprve přidáme do string.xml řetězce "Ukončit" a "Vyčistit", které pojmenujeme např. exit a clear s prefixem menu_. Pak si rozklepneme složku menu/ a v ní jediný XML soubor. Odmažeme stávající položky a přidáme si vlastní. Klepnutím na add přidáme item.

Napravo v "properties" pak nastavíme jen ID a Titulek. Id pouze přejmenujeme na něco v podobném duchu, abychom se v tom vyznali:

@+id/clear
@+id/exit

A do title vybereme daný string:

@string/menu_clear
@string/menu_exit

Uspořádání lze měnit pomocí tlačítek UP/DOWN.

Pokud nyní klepneme na tlačítko MENU na telefonu v naší aplikaci, tak se nám zobrazí menu. Teď jej zaktivníme. Do hlavní třídy přidáme metodu onOptionsItemSelected() a do ní následující kód:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // získání ID vybrané položky
        switch (item.getItemId()) {
            // Ukončení aplikace
            case R.id.exit:
                this.finish();
                return true;

            // Vyčištění plátna
            case R.id.clear:
                myCanvas.clearCanvas();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

Když aplikaci vyzkoušíme, lze již malovat, hrát si s prsty a mazat plátno.

Možnost výběru barvy a tloušťky

Ještě si uděláme možnost výběru barvy a tloušťky, se kterou budeme kreslit. Do MyCanvas přidáme následující dvě metody, které tyto vlastnosti nastavují:

public void setPenColor(int color) {
    paint.setColor(color);
    invalidate();
}

public void setPenWidth(float width) {
    paint.setStrokeWidth(width);
    invalidate();
}

Přidáme texty a položky do menu. V metodě onOptionsItemSelected() v hlavní třídě si je pak zaktivníme:

case R.id.pen_width:
    final CharSequence[] sizes = {"1", "3", "5", "10", "15", "20"};

    AlertDialog.Builder sizePickerDialog = new AlertDialog.Builder(this);
    sizePickerDialog.setTitle("Vyber tloušťku:");
    sizePickerDialog.setItems(sizes, new DialogInterface.OnClickListener() {
        // Po zvolení se zobrazí informace o vybrané položce a zavolá se příslušná metoda, která nastaví vybranou vlastnost
        public void onClick(DialogInterface dialog, int item) {
            Toast.makeText(getApplicationContext(), "Vybrána tloušťka: " + sizes[item] + "px", Toast.LENGTH_SHORT).show();
            myCanvas.setPenWidth(Float.valueOf((String) sizes[item]));
        }
    });
    AlertDialog pickSize = sizePickerDialog.create();
    pickSize.show();
    return true;
case R.id.pen_color:
    final Map<String, Integer> colorList = new HashMap<>();
    colorList.put("Černá", Color.BLACK);
    colorList.put("Červená", Color.RED);
    colorList.put("Žlutá", Color.YELLOW);
    colorList.put("Zelená", Color.GREEN);
    colorList.put("Modrá", Color.BLUE);
    colorList.put("Fialová", Color.MAGENTA);
    colorList.put("Šedá", Color.GRAY);

    final CharSequence[] colors = colorList.keySet().toArray(new CharSequence[colorList.size()]);

    // Vytvoření dialogu
    AlertDialog.Builder colorPickerDialog = new AlertDialog.Builder(this);
    colorPickerDialog.setTitle("Vyber barvičku:");
    colorPickerDialog.setItems(colors, new DialogInterface.OnClickListener() {
        // Po zvolení se zobrazí informace o vybrané položce a zavolá se příslušná metoda, která nastaví vybranou vlastnost
        public void onClick(DialogInterface dialog, int item) {
            Toast.makeText(getApplicationContext(), "Vybraná barvička: " + colors[item], Toast.LENGTH_SHORT).show();
            myCanvas.setPenColor(colorList.get(colors[item]));
        }
    });
    AlertDialog pickColor = colorPickerDialog.create();
    pickColor.show();
    return true;

Ještě bych rád zmínil, že pokud něco odlazujete a chcete kontrolovat hodnoty nebo prostě si něco vypsat, můžete vypisovat do debug konzole označené jako LogCat pomocí:

Log.d(tag, msg);

Parametr tag označuje čeho se zápis týká a msg je poté samotná zpráva. Obojí se vypíše do okénka LogCat:

Výsledná Java aplikace pro kreslení prstem pro Android - Základy vývoje Android aplikací v Javě

Nyní nám aplikace splňuje naše minimální nároky a můžeme si hrát, črtat, kreslit atp.

Určitě si sami zkuste aplikaci doplnit například o změnu pozadí. Zkuste si dát maximální SDK (AndroidManifest.xml) a přidat NumericPicker či ColorPicker. Zkuste popřemýšlet jak vyřešit vracení se o kroky zpět. Jak to udělat, aby se při změně barvy nezměnily všechny čáry. Abychom při natočení mobilu neztratili data. Přidat možnost kreslení kružnic, čtverců... Ukládání a mnohé další.


 

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 17x (769.24 kB)
Aplikace je včetně zdrojových kódů

 

Předchozí článek
Kvíz - Základy vývoje Android aplikací v Javě
Všechny články v sekci
Základy vývoje Android aplikací v Javě
Článek pro vás napsal Petr Štechmüller
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity