Image
30.6.2016 0 Comments

Vývoj pre Android – Grafika / 11. časť

Späť na úvod >> Späť na seriál

Grafika je jeden 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 či dokonca 3D grafika nespôsobujú problém.

Na vykreslenie grafiky má androidová aplikácia niekoľko možností na zobrazenie statických alebo dynamicky sa meniacich grafických prvkov. 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 na častú aktualizáciu grafických prvkov.

Vykresľovanie na Canvas

Ak chcete kresliť zložitejšiu grafiku, prípadne grafiku, ktorá sa často aktualizuje, využijete s výhodou kreslenie na Canvas. Objekt Canvas znamená v praxi presne to, čo jeho preklad do slovenčiny - maliarske plátno, ktoré slúži ako podklad na vykresľovanie objektov do súradnicového systému.

Canvas umožňuje pokročilejšie vykresľovanie, môžete nastaviť rôzne farby a štýly, hrúbku čiar, veľkosť textu. Môžete nastaviť rôzne metódy grafickej optimalizácie, napríklad antialiasing na vyhladenie obrazu, aby sa odstránili zubaté šikmé čiary, a podobne. Na naznačené účely budete používať metódy setStrokeWidth(), setTextSize(), setColor() či setAntiAlias(). Najčastejšie budete v súvislosti s kreslením na Canvas využívať metódy drawText(), drawPoints(), drawColor(), drawOval() a drawBitmap().

Vykresľovanie na Canvas budeme demonštrovať na triviálnom príklade, v ktorom vykreslíme obdĺžnik, čiaru a text.

Najskôr vytvoríme triedu Kreslenie.

public class Kreslenie extends View
{
public Kreslenie(Context context){super(context);}
@SuppressLint("DrawAllocation") @Override
protected void onDraw(Canvas canvas)
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawRect(10, 10, 300, 150, paint);
paint.setColor(Color.BLUE);
paint.setTextSize((float) 30.0);
canvas.drawText("Grafický výpis textu", 10, 200, paint);
canvas.drawLine(10, 230, 190, 230, paint);
}
}

V kóde hlavnej aktivity nastavíme túto triedu ako kontextové View na vykresľovanie v metóde SetContentView(). Z uvedeného vyplýva, že návrh XML hlavnej aktivity sa vôbec nepoužije.

public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new Kresleni(this));
}
}

Vykreslenie jednoduchých grafických tvarov na Canvas

Kreslenie dotykom na Canvas

Pri prístrojoch s dotykovým displejom sa námet na ďalšiu grafickú aplikáciu plnú dynamiky ponúka sám - kreslenie prstom po obrazovke. Na tento cieľ trochu prerobíme triedu Kreslenie z predchádzajúceho príkladu.

Princíp je jednoduchý. V obslužnej procedúre onTouchEvent budeme snímať ako udalosti dotyky (MotionEvent.ACTION_DOWN) a pohyby prsta (MotionEvent.ACTION_MOVE) a ukladať súradnice, kde ste sa displeja dotkli, do poľa. Na zjednodušenie budeme serializovať, to znamená ukladať súradnice x a y sériovo do jednorozmerného poľa. Následne vykreslíme čiaru ako spojnicu medzi dvoma poslednými bodmi. Všimnite si nastavenie hrúbky čiary.

Najskôr pridajte referencie na snímanie pohybu po dotykovej obrazovke a pole objektov na uloženie súradníc.

android.view.MotionEvent;
import java.util.ArrayList;

Po identifikácii udalosti dotyku alebo posunu prsta sa explicitne vyvolá udalosť invalidate(). V obsluhe tejto udalosti sa zavolá metóda onDraw na prekreslenie obrazovky.

public class Kreslenie extends View
{
public Kreslenie(Context context)
{
super(context);
}
ArrayList<Float> pt = new ArrayList<Float>();
@Override
public boolean onTouchEvent(MotionEvent event)
{
int e = event.getAction();
if (e == MotionEvent.ACTION_DOWN || e == MotionEvent.ACTION_MOVE)
{
pt.add(event.getX()); pt.add(event.getY());
invalidate();
}
return true;
}
@Override
protected void onDraw(Canvas canvas)
{
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(4);
for(int i =2; i < pt.size(); i+=2)
{
canvas.drawLine(pt.get(i-2), pt.get(i-1),
pt.get(i), pt.get(i+1) , paint);
}
}
}

AndroidVyvoj2.jpg

Príklad aplikácie na kreslenie prstom

Dynamické vykresľovanie na Canvas s využitím View

Vykresľovanie na Canvas môžete realizovať cez View alebo triedu odvodenú od View ako v predchádzajúcich príkladoch. To v prípade, ak aktualizácie grafiky budú menej časté. Pri často aktualizovanej grafike je lepšie použiť špecializovanú triedu SurfaceView.

Námetom príkladu bude pohyb figúrky po ploche. Vzhľadom na to, že vykresľovanie cez View sa hodí pre menej často aktualizovanú grafiku, mohli by sme takto realizovať napríklad jednoduchú hru ako šachy. V reálnej aplikácii by sa figúrka pohybovala po ploche znázorňujúcej hernú scénu, napríklad po šachovnici.

Skôr než pristúpite k tvorbe kódu na vykresľovanie, treba realizovať dva prípravné kroky:

  • Do adresára drawable vložte obrázok nejakej figúrky. Obrázok ľahko získate cez Google v sekcii obrázky.
  • V súbore dimens.xml v zložke res\values definujte výšku a šírku obrázka.
<resources>
<dimen name="image_width">50dp</dimen>
<dimen name="image_height">50dp</dimen>
</resources>

Vykresľovanie sa realizuje v kóde Java hlavnej aktivity. Figúrka mení svoju polohu v sekundových intervaloch.

V metóde onCreate() vytvoríme inštanciu objektu Bitmap na zobrazenie obrázka z resourceov.

Vytvoríme triedu HraView, odvodenú od View, a pridáme ju do layoutu hlavnej aktivity.

rl.addView(hraView);

Všimnite si v konštruktore triedy HraView spôsob získania informácie o rozlíšení obrazovky v horizontálnom aj vertikálnom smere.

Pohyb figúrky bude realizovaný ako postupné vykresľovanie, pričom jednotlivé iterácie sa realizujú v threade. V každej fáze pohybu je predtým vykreslený obrázok vymazaný a nakreslený na novej pozícii. Na jednoduchosť meníme súradnice vykresľovania pripočítaním konštanty. Figúrka sa, samozrejme, vykreslí iba v prípade, ak jej súradnice nie sú mimo zobrazovacej plochy. Taktovanie po sekundách sa vykonáva pomocou metódy

Thread.sleep(1000);

Na vykresľovanie sa využíva prekrytá metóda onDraw() a v nej canvas.drawBitmap().

Kompletný kód hlavnej aktivity:

public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.kontejner);
final Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.et);
final HraView hraView = new HraView(getApplicationContext(),bmp);
rl.addView(hraView);
new Thread(new Runnable()
{
@Override
public void run()
{
while (hraView.posun())
{
hraView.postInvalidate();
try {Thread.sleep(1000);}
catch (InterruptedException e)
{Log.i("KreslenieCanvas", "CHYBA Sleep");}
}
}
}).start();
}
private class Poloha
{
float sX, sY;
public Poloha(float x, float y)
{
sX = x; sY = y;
}
synchronized Poloha posun(Poloha dxdy)
{
return new Poloha(sX + dxdy.sX , sY + dxdy.sY);
}
synchronized Poloha dajSuradnice()
{
return new Poloha(sX, sY);
}
}
private class HraView extends View
{
final private Bitmap mBmp;
private Poloha mAktualna;
final private Poloha mDelta;
final private DisplayMetrics mMetrika;
final private int mWidth;
final private int mHeight;
final private int mOld, mNew;
final private Paint mPainter = new Paint();
public HraView(Context context, Bitmap bitmap)
{
super(context);
mOld = (int) getResources().getDimension(R.dimen.image_height);
this.mBmp = Bitmap.createScaledBitmap(bitmap,mOld,mOld, false);
mNew = mOld + 10;
mMetrika = new DisplayMetrics();
MainActivity.this.getWindowManager().getDefaultDisplay()
.getMetrics(mMetrika);
mWidth = mMetrika.widthPixels;
mHeight = mMetrika.heightPixels;
float x = 10; float y = 10;
mAktualna = new Poloha(x, y);
float dy = y+1;
float dx = x+1;
mDelta = new Poloha(dx, dy);
mPainter.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas)
{
Poloha pp = mAktualna.dajSuradnice();
canvas.drawBitmap(mBmp, pp.sX, pp.sY, mPainter);
}
protected boolean posun()
{
mAktualna = mAktualna.posun(mDelta);
if (mAktualnA.sY < 0 - mNew
|| mAktualna.sY > mHeight + mNew
|| mAktualna.sX < 0 - mNew
|| mAktualna.sX > mWidth + mNew)
return false;
else return true;
}
}
}

AndroidVyvoj3.jpg

Dynamické vykresľovanie

V nasledujúcom pokračovaní sa budeme venovať animácii.

 

Autor: Marek Sopko

Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

ITPro

Red Hat a Veracomp: Open source a cloudy

09.12.2016 12:05

Cieľom ďalšej z radu spoločných akcií firiem Red Hat a Veracomp Slovakia v Bratislave bola prezentácia produktov, služieb a stratégií týkajúcich sa najhorúcejších tém IT podpory biznisu s využitím naj ...

ITPro

Právne okienko

08.12.2016 12:02

1. Ako postupovať, ak obchodník nechce uznať reklamáciu tovaru objednaného z e-shopu? V takomto prípade môžu nastať v zásade dve situácie. Ak zákazník reklamuje tovar do 12 mesiacov od jeho kúpy, mož ...

ITPro

Red Hat Forum 2016: Otvorená digitálna transformácia

09.12.2016 11:51

Podujatím v Prahe pre región CENE (stredná a severná Európa) rezonovala komunitná atmosféra a snaha o spoluprácu podľa pravidla „každý s každým“. IT musí priniesť do digitálneho biznisu novú kultúru a ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá