SAMSUNG_06202 M SAMSUNG_06202 M SAMSUNG_06202 M Advertisement

Naučte sa vyvíjať aplikácie pre Android za 14 dní – grafika I

0

Grafika je jedným z najdôležitejších dizajnových aj výrazových prostriedkov mobilných aplikácií. Moderné zariadenia využívajúce platformu Android disponujú výkonnými procesormi, hardvérovo akcelerovanou grafikou a displejmi s vysokým rozlíšením, takže ani náročná 2D a 3D grafika pre ne nepredstavuje problém

Na vykreslenie grafiky má Android aplikácia niekoľko možností na zobrazenie statických, alebo dynamicky sa meniacich grafických prvkov.

Grafické prvky je možné vykresľovať buď cez View, alebo Canvas. Vykresľovanie grafických objektov prostredníctvom objektu View je jednoduchšie, no menej flexibilné. Využíva sa vtedy, ak sa nakreslené grafické prvky aktualizujú zriedkavo, prípadne vôbec. Vykresľovanie s využitím objektu Canvas je  zložitejšie, no oveľa flexibilnejšie a výkonnejšie.  Dá sa využiť aj pre častú aktualizáciu grafických prvkov.

Ako vyplýva z názvu zložky Drawable, je určená pre objekty, ktoré je možné vykresliť, teda obrázky, tvary a podobne.

Statickú grafiku definovanú v XML súboroch môžete vytvárať pomocou tried ColorDrawable, BitmapDrawable, ShapeDrawable a GradientDrawable.  XML súbory s definíciou statickej grafiky je potrebné umiestniť do zložky res/drawable. Súbory sa identifikujú pomocou ich názvu pred príponou xml. Tento názov musí byť tvorený malými písmenami. Aby bolo možné pokryť čo najviac rozlíšení displeja využívajú sa spravidla zložky so špecifikáciou rozlíšenia v modifikátore, ktorý je súčasť názvu.

  • res/drawable-hdpi
  • res/drawable-ldpi
  • res/drawable-mdpi
  • res/drawable-xhdpi
  • res/drawable-xxhdpi

Obrázok v XML návrhovom kóde

V prvom triviálnom príklade ukážeme zobrazenie obrázka. Príklad má dve varianty. V prvej zobrazíme obrázok pomocou prvku View definovaného v XML súbore. V druhej variante zobrazíme obrázok pomocou Java kódu. Vytvorte aplikáciu typu Empty activity a zmeňte typ vizuálneho kontejnera na LinearLayout

Pre zobrazenie obrázku pridáme v návrhovom zobrazení do vizuálneho kontejnera RelativeLayout prvok ImageView. 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="350dp"
        android:layout_height="350dp"
        android:layout_centerInParent="true"
        android:contentDescription="Logo Android 7.0"
        android:src="@drawable/logo_nextech" />
</LinearLayout>

Obrázok pridajte do zložky res/drawable. Môžete ho tam presunúť zo súborového manažéra (Prieskumník, Finder...)

Zobrazenie obrázku programovo

Vytvorte aplikáciu typu Empty activity a zmeňte typ vizuálneho kontejnera na RelativeLayout Pomocou metódy setContentView() definujeme pripojenie na XML definičný súbor, ktorý však v tomto prípade obsahuje len kontajnerový prvok RelativeLayout a nič v ňom. Aby bolo možné do RelativeLayout pridávať prvky programovo, musíte mu priradiť identifikátor napríklad android:id="@+id/activity_main"

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/activity_main"
    tools:context=".MainActivity">
 
</RelativeLayout>

Pre prvok ImageView nastavíme bitmapový obrázok, ktorý  sa bude vykresľovať. V našom prípade je uložený vo formáte png. Kód pokračuje nastavením vlastností – tých istých ako sme nastavovali v XML definícii.

Výška a šírka obrázku nebude uložená priamo v kóde, ale v súbore dimens.xml v zložke res\values. Je to odporúčaný postup, ak by ste sa rozhodli neskôr zmeniť veľkosť zobrazeného obrázku nemusíte zasahovať do Java kódu.

<resources>
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="image_width">400dp</dimen>
    <dimen name="image_height">4000dp</dimen>
</resources>

Výška, šírka a informácia o vycentrovaní obrázku sa nastavia cez objekt RelativeLayout.LayoutParams. Napokon pridáme objekt View do vizuálneho kontejnera RelativeLayout.

package com.example.grafika2;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.RelativeLayout;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RelativeLayout relativeLayout = (RelativeLayout)
                findViewById(R.id.activity_main);
 
        ImageView imgView = new ImageView(getApplicationContext());
        imgView.setImageDrawable(getResources().getDrawable(R.drawable.pie_logo));
 
        int width = (int) getResources().getDimension(R.dimen.image_width);
        int height = (int) getResources().getDimension(R.dimen.image_height);
 
        RelativeLayout.LayoutParams params =
                new RelativeLayout.LayoutParams(width, height);
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        imgView.setLayoutParams(params);
        relativeLayout.addView(imgView);
 
    }
}

Zobrazenie obrázku z internetu

Zobrazovanie obrázkov je jednou z najčastejšie implementovaných funkcií v mobilných aplikáciách, či už sú to aplikácie s ponukou tovaru, aplikácie zobrazujúce fotografie a podobne. Ako takýto obrázok na vhodnom mieste a vhodným spôsobom zobraziť v Android aplikácií

Našou úlohou je zobrazenie obrázka z webu. Uloženie obrázkov na webovom serveri nie je námetom tejto publikácie, preto predpokladáme, že obrázok už na webe uložený je. Pre cvičnú aplikáciu postačí získať URL adresu ľubovoľného obrázku z ľubovoľnej webovej stránky. Aktivujte na obrázok v prehliadači kontextové menu, položku Vlastnosti. Zo zobrazeného dialógu skopírujte URL adresu a použite ju v príklade.

Pre aplikáciu musíte nastaviť oprávnenie pristupovať na internet v súbore AndroidManifest.xml. Ak na tento krok zabudnete, budete sa pri spustení aplikácie zbytočne čudovať, prečo aplikácia nefunguje napriek tomu, že jej kód vyzerá úplne v poriadku. Do manifestu pridajte riadok so sekciou uses-permission

<uses-permission android:name="android.permission.INTERNET" />

Používateľské rozhrania miniaplikácie tvorí jediný prvok ImageView.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:contentDescription="obrázok z internetu"/>
</RelativeLayout>

Načítanie čohokoľvek z webu môže trvať dlhšie a v našom prípade môže nastať u niektorého používateľa  aplikácie kombinácia pomalého internetového pripojenia a obrázkov s vysokým rozlíšením , preto sa takéto záležitosti neriešia v hlavnom vlákne ale v asynchrónnej triede NacitajObrazok v metóde doInBackground() na pozadí aby počas nahrávania obrázka nebolo blokované používateľské rozhranie.

Po úspešnom načítaní sa obrázok priradí k prvku ImageView v metóde onPostExecute()

package com.example.grafika3;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ImageView;
 
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
 
public class MainActivity extends AppCompatActivity {
 
    public static final String sURL = "https://pngimg.com/uploads/android_logo/android_logo_PNG20.png";
    ImageView imageView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        imageView = (ImageView) findViewById(R.id.imageView1);
        WebovyObrazek uloha = new WebovyObrazek ();
        uloha.execute(new String[] { sURL });
    }
 
    private class WebovyObrazek extends AsyncTask<String, Void, Bitmap> {
        @Override
        protected Bitmap doInBackground(String... urls) {
            Bitmap bmp = null;
            for (String url : urls) {
                bmp = nacitajObrazok(url);
            }
            return bmp;
        }
 
        @Override
        protected void onPostExecute(Bitmap result){
            imageView.setImageBitmap(result);
        }
 
        private Bitmap nacitajObrazok(String url){
            Bitmap bmp = null;
            InputStream stream = null;
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inSampleSize = 1;
 
            try {
                stream = vytvorStream(url);
                bmp = BitmapFactory.decodeStream(stream, null, bmOptions);
                stream.close();
            }
            catch (IOException e1) {
                e1.printStackTrace();
            }
            return bmp;
        }
 
 
        private InputStream vytvorStream(String urlString) throws IOException {
            InputStream stream = null;
            URL url = new URL(urlString);
            URLConnection connection = url.openConnection();
 
            try {
                HttpURLConnection httpCon = (HttpURLConnection) connection;
                httpCon.setRequestMethod("GET");
                httpCon.connect();
 
                if (httpCon.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    stream = httpCon.getInputStream();
                }
            } catch (Exception ex){
                ex.printStackTrace();
            }
            return stream;
        }
    }
 
}

Základné grafické  tvary - staticky

Základné grafické tvary sú reprezentované triedami odvodenými od triedy Shape. Určite využijete PathShape pre vykreslenie segmentov a kriviek, RectShape pre vykreslenie obdĺžnikov, a OvalShape pre vykreslenie kruhov a elíps. 

Postup vytvorenia „XML grafiky“ je jednoduchý. Do adresára drawable umiestnite XML súbor a vhodne ho pomenujte. V našom jednoduchom príklade chceme vykresliť zaoblené orámovanie displeja, preto sme vybrali názvy rect1.xml a rect2.xml. Koreňovým (root) elementom bude shape. V súboroch sú definované grafické prvky, v tomto prípade prvok rectangle (obdĺžnik) farebný so zaoblenými rohmi. Uvádzame len obsah definičného súboru prvého obdĺžnika, druhý sa líši len farbou plochy a orámovania:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
    <solid 
      android:color="#0000ff"/>
    <stroke
      android:width="5dp" 
      android:color="#00FF00"/>
    <corners 
      android:radius="30dp" />
</shape>

V definičnom XML súbore hlavnej aktivity vložíme grafické prvky do layoutu ako ImageView.

?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
 
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:padding="20dp"
        android:src="@drawable/rect1" />
 
    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="45dp"
        android:padding="20dp"
        android:src="@drawable/rect2" />
</RelativeLayout>

V takomto jednoduchom ilustračnom príklade nemusíte aplikáciu ani spúšťať, stačí sa prepnúť v definičnom XML súbore hlavnej aktivity do návrhového zobrazenia a presvedčiť sa, že sa na ploche aktivity zobrazili dva čiastočne sa prekrývajúce obdĺžniky orámované čiarou inej farby so zaoblenými rohmi.

Základné grafické  tvary - dynamicky

Zatiaľ čo statická grafika definovaná v XML kóde sa hodí skôr na vykresľovanie pozadia, na vykresľovanie dynamickej grafiky, či už jednoduchých hier, diagramov, schém procesov a podobne sa používa aplikačný kód.  V druhej časti príkladu teda vykreslíme grafické tvary programovo. Aby bola nejaká zmena a predstavili sme viac tvarov, namiesto obdĺžnikov vykreslíme farebné kruhy, čiže objekty OvalShape. XML definičný súbor layoutu hlavnej aktivity obsahuje len kontajnerový prvok RelativeLayout. Aby bolo možné do neho pridávať prvky, musíte mať priradený identifikátor.

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/kontejner"
 
    tools:context=".MainActivity">
 
</RelativeLayout>

 

V súbore dimens.xml v zložke res\values je definovaná výška a šírka obrázkov.

<resources>
    <dimen name="image_width">300dp</dimen>
    <dimen name="image_height">300dp</dimen>
    <dimen name="padding">3dp</dimen>
</resources>

Celé dejstvo vykreslenia obidvoch prvkov sa odohráva v kóde hlavnej aktivity 

package com.example.grafika5;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.graphics.Color;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.RelativeLayout;
 
public class MainActivity extends AppCompatActivity {
    int alpha = 127;
 
    @Override
    public void onCreate(Bundle savedInstanceState)  {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        int width = (int) getResources().getDimension(R.dimen.image_width);
        int height = (int) getResources().getDimension(R.dimen.image_height);
        int padding = (int) getResources().getDimension(R.dimen.padding);
 
        RelativeLayout rl = (RelativeLayout) findViewById(R.id.kontejner);
 
        //prvny modry kruh...
        ShapeDrawable blueShape = new ShapeDrawable(new OvalShape());
        blueShape.getPaint().setColor(Color.BLUE);
        blueShape.setIntrinsicHeight(height);
        blueShape.setIntrinsicWidth(width);
        blueShape.setAlpha(alpha);
 
        //... do ImageView
        ImageView blueView = new ImageView(getApplicationContext());
        blueView.setImageDrawable(blueShape);
        blueView.setPadding(padding, padding, padding, padding);
 
        // ... do RelativeLayout
        RelativeLayout.LayoutParams blueParams =
                new RelativeLayout.LayoutParams(height, width);
        blueParams.addRule(RelativeLayout.CENTER_VERTICAL);
        blueParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        blueView.setLayoutParams(blueParams);
        rl.addView(blueView);
 
        // druhy zeleny kruh ...
        ShapeDrawable greenShape = new ShapeDrawable(new OvalShape());
        greenShape.getPaint().setColor(Color.GREEN);
        greenShape.setIntrinsicHeight(height);
        greenShape.setIntrinsicWidth(width);
        greenShape.setAlpha(alpha);
 
        // ... do ImageView
        ImageView greenView = new ImageView(getApplicationContext());
        greenView.setImageDrawable(greenShape);
        greenView.setPadding(padding, padding, padding, padding);
 
        // ... do RelativeLayout
        RelativeLayout.LayoutParams greenParams =
                new RelativeLayout.LayoutParams(height, width);
        greenParams.addRule(RelativeLayout.CENTER_VERTICAL);
        greenParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
 
        greenView.setLayoutParams(greenParams);
 
        rl.addView(greenView);
    }
}

V kóde získame referenciu na kontejner RelativeLayout umožňujúci relatívne usporiadanie prvkov. V procedúre onCreate() sa postupne vytvoria dva objekty OvalShape, vrátane nastavenia farby výšky a šírky. Aby sme ilustrovali možnosť prekrývania a s ním spojeného miešania farieb v mieste kde sa obrazce prekrývajú zadefinujeme aj parameter alpha - transparentnosť. Hodnotu transparentnosti nastavíme na 127, čiže približne polovičnú priesvitnosť.  

Rekapitulácia seriálu

1 deň – Prvá aplikácia 

2 deň – Možnosti emulátorov 

3 deň - Zorientujte sa v projekte aplikácie

4 deň – Princípy dizajnu a škálovania

5 deň – Uporiadanie prvkov používateľského rozhrania

6 deň – Obsluha udalostí

7 deň – Aplikácia s dvomi aktivitami  

8 deň – Spustenie na reálnom zariadení

9 deň – Intenty, alebo kto to urobí

10 deň – Dotyky a gestá

11 deň - Dotyky a gestá II  

12 deň  - Zmena orientácie displeja

Luboslav Lacko

Všetky autorove články
Vývoj Android Android Studio Android aplikácie

Pridať komentár

Mohlo by vás zaujímať

Mohlo by vás zaujímať