Marek Chrenko & Tomáš Vondráček 1 Představení • Marek Chrenko & Tomáš Vondráček • Android developers ve společnosti Inmite. 2 Kam smeruje mobilný svet? 3 Internet of Things • inteligentné domy • autá bez vodiča • RFID náramky 4 Kontextové aplikácie • dopĺňajú realitu • silné využitie senzorov • špecifické UI (napr. hlasová navigácia) • jednoducho dostupné 5 Wearables • smartfón? such oldschool • hodinky, náramky, oculus rift • airbond od Inmite • Google Glass 6 Google Glass 7 Google Glass • snažia sa určiť smer vo wearables • aktuálne developer preview • OS Android 4.x • spolupracujú s Android a iOS zariadeniami 8 Technické okienko • CPU 1.2 GHz, dual-core • RAM 1 GB • 16 GB Flash • displej 640x360 • zvuk skrz kosti pri uchu • 5MPix fotoaparát s HD videom • wifi, bluetooth, microUSB 9 Používanie • demo hlasového vstupu a pohybu v systéme 10 Vývoj 11 • Android SDK od API 15 • Mirror API (REST) • natívne GDK Mirror API 12 • REST prístup, Glass API backend • komunikácia cez JSON • karty sú hlavná UI zložka • všetko ide do timeline • demo Statické karty 13 Statické karty 14 POST /mirror/v1/timeline HTTP/1.1 Host: www.googleapis.com Authorization: Bearer {auth token} Content-Type: application/json Content-Length: 26 ! { "text": "Hello world" } Mirror API toho vie viac 15 • vytvárať menu items • zdieľať karty • interagovať s kartami • bundlovať karty • je Google cloud based Glass Development Kit 16 • beží priamo na Glass HW • od API level 19 • rozširuje Android SDK o Cards, Voice (triggers), Gesture Detector • interakcia s používateľom v reálnom čase • funguje offline • prístup k HW Aplikačné prvky GDK 17 • live cards • immersions • UI Widgety a preddefinované štýly • prístup k senzorom Demo • trochu bankovej teórie • a viac hernej zábavy • viac info - David Vávra / destil.cz 18 Marek Chrenko & Tomáš Vondráček Android UI 25.4.2014 19 Agenda • View hierarchy • Layouts • ListView • Canvas • Custom View • Animace • Styly 20 View hierarchy 21 View hierarchy 22 23 24 View • základní stavební blok • View vs ViewGroup • každé View má layoutParams pro svého parenta 25 Layouts (ViewGroup) • Definují strukturu UI • Mohou se vnořovat, ale čím hlubší hierarchie, tím pomalejší měření a layout 26 Views • v xml
 
 
 • v kódu
 TextView txt = new TextView(context); txt.setText(R.string.text) txt.setLayoutParams(new LayoutParams(
 LayoutParams.MATCH_PARENT,
 LayoutParams.WRAP_CONTENT)); 27 Views • view vytvořené v xml se“nahustí”do hierarchie
 LayoutInflater inflater = LayoutInflater.from(ctx) View v = inflater.inflate(R.layout.fragment_commits, container, false); 28 Views • na jednotlivá view se přistupuje přes ID
 TextView title = view.findViewById(R.id.title); 29 View hierarchy • perform traversal (asynchronní) • measure • layout • draw 30 Layouts • Základní layouty z frameworku: • FrameLayout, LinearLayout, RelativeLayout, TableLayout, GridLayout • Vlastní layout • AdapterView • ListView, GridView 31 FrameLayout • Nejjednodušší • Nejefektivnější ! • layout_margin • layout_gravity 32 FrameLayout ! ! ! 33 LinearLayout • Horizontální nebo vertikální ! • layout_weight - potomci mohou mít váhu • layout_gravity • layout_margin 34 LinearLayout 35 LinearLayout ! 36 RelativeLayout • Jednotlivá View jsou pozicována vůči sobě nebo vůči předkovi • Umožňuje vytvořit plochou hierarchii 37 RelativeLayout 38 RelativeLayout ! ! 39 ListView & GridView • vytvářejí kolekci View na základě dat z adaptéru • recyklace View • vždy je vytvořeno pouze tolik view kolik je zobrazeno (+ 1 či 2) 40 ListView & GridView 41 ListView 42 ListView 43 • nasledovné postupy platia aj pre GridView • zobrazujú veľké počty záznamov • náročné na CPU/pamať - pri akciách ako scroll a fling • použitie adaptérov ListView 44 • view sú ťažké objekty (1-2 kb) • recyklujú sa • naplnenie view obsahom sa deje v getView(position, convertView, parent) getView so sekaním 45 public View getView(int position, View convertView, ViewGroup parent) { ! View item = mInflater.inflate(R.layout.list_item_icon_text, null);! ! ((TextView) item.findViewById(R.id.text)).setText(DATA[position]); ! ((ImageView) item.findViewById(R.id.icon)).setImageBitmap( ! (position & 1) == 1 ? mIcon1 : mIcon2);! return item; ! } getView klasicky 46 public View getView(int position, View convertView, ViewGroup parent) { ! if (convertView == null) { ! ! convertView = mInflater.inflate(R.layout.item, parent, false); ! ! } ! ! ((TextView)convertView.findViewById(R.id.text))! .setText(DATA[position]); ! ! ((ImageView) convertView.findViewById(R.id.icon))! .setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);! ! return convertView; ! } getView plynulo 47 public View getView(int position, View convertView, ViewGroup parent) { ! ViewHolder holder;! if (convertView == null) { ! ! convertView = mInflater.! ! ! ! ! inflate(R.layout.list_item_icon_text, parent, false);! holder = new ViewHolder(); ! holder.text = (TextView) convertView.findViewById(R.id.text); ! holder.icon = (ImageView) convertView.findViewById(R.id.icon); ! convertView.setTag(holder); } ! else { ! holder = (ViewHolder) convertView.getTag(); ! } ! ! holder.text.setText(DATA[position]); ! holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2); ! return convertView; ! } Adaptér 48 • nerobiť si lokálnu view cache! • nesnažiť sa vybabrať s ListView • nemeniť štruktúru convertView - to sa vracia typu, ktorý určí komponenta a je vždy správny • notifyDataSetChanged() • notifyDataSetInvalidated() Typy View 49 • vstavané typy (jednoduché texty) • ak chceme viac typov view, preťažíme getViewTypeCount(), getItemViewType(position) Typy View 50 @Override! public int getViewTypeCount() {! ! return super.getViewTypeCount() + 1; // activate view type! } @Override! public int getItemViewType(int position) {! ! if (getItem(position) instanceof CardTO) {! ! ! return VIEW_TYPE_ACTIVATE;! ! }! ! return super.getItemViewType(position);! } Properties 51 • enabled / disabled položky • single / multiple choice mode • hasStableIds() = = true ako optimalizácia Header & Footer view 52 • skrolujú s položkami listview • Quick Return pattern Problémy 53 • čierny list počas skrolovania - nastaviť cacheColorHint na transparentnú farbu • nevkladať listview do scrollview a naopak • potrebujeme listview? nestačí layout generovať? CustomView 54 • možnosť odlíšenia od davu • zapúzdrenie kódu • optimalizácia • prístup k protected metódam • demo: ClipboardEditText Život View 55 • pridanie / odobranie z window • meranie, pozicovanie a vykreslenie • perzistencia stavu pridanie / odobranie 56 • po volani ViewGroup.addView • zavolá sa onAttachedToWindow() • idealne miesto na nastavenie listenerov, zresetovanie stavu • pri odoberaní - onDetachFromWindow() • o svojich zmenách view informuje okolie cez rozhrania a callbacky (nemá onCreate,..) odmeraj, rozlož, nakresli 57 • všetky view sa dokážu odmerať (pevné šírky, príp. LayoutParams) • requestLayout() sa stará o prepočet layoutu rekurzívne, preto treba držať plochý view strom • onMeasure() rozhoduje o veľkosti view a jeho potomkov - musí volať setMeasuredDimension() pred návratom • následne sa prevedie layout - paddingy,… a uchovaj stav 58 • pri rotácií obrazovky dochádza k zahodeniu views a znovuvytvoreniu UI • onSaveInstanceState(), onRestoreInstanceState() • vytvoriť potomka triedy BaseSavedState Canvas • přímé kreslení pomocí primitiv • můžeme přes něj vykreslit obsah View nebo si můžeme kreslit do bitmapy • umožňuje základní transformace • translace, rotace, scale 59 Canvas - pojmy • Canvas - malíř, pamatuje si draw calls • Bitmap - pixely, na které se aplikují draw calls • Paint - štětec, určuje barvu a styl 60 Canvas primitiva • drawText(), • drawBitmap(), • drawLine(), • drawPath() • drawRect(), • … 61 Canvas - stav • uložení/obnovení stavu pro aplikování transformací 62 Canvas - stav canvas.save(); canvas.translate(textX, 0); ! canvas.drawText(text, x, y, mPaint); canvas.restore(); 63 Canvas - tip Bitmap bmp = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); ! Canvas canvas = new Canvas(bmp); view.draw(canvas); 64 Canvas - tip Bitmap bmp = Bitmap.createBitmap(view.getWidth()/4, view.getHeight()/4, Bitmap.Config.ARGB_8888); ! Canvas canvas = new Canvas(bmp); canvas.setScale(0.25, 0.25) view.draw(canvas); 65 Animace • “Anima”= duše 66 Souřadný systém 67 Property animation • Animace čehokoli na jakémkoli objektu. • Včetně vlastních objektů a vlastních property. 68 Property animation: • Animator: tiká • Interpolator: y = f(t) • y začíná na 0, končí na 1 • Evaluator: x0 + y * (x1 - x0) 69 Property animation • ObjectAnimator • Typicky volá nad view: • setRotationX, setRotationY • setTranslationX, setTranslationY • setScaleX, setScaleY • setAlpha 70 Property animation ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.ROTATION_X, 0f, 180f); animator.setDuration(1000L); animator.start(); 71 Property animation view.animate() .rotationX(180f) .setDuration(1000L); 72 Property animation view.animate() .rotationX(180f) .translationY(100f) .alpha(0.5f) .scaleY(0f) .setDuration(1000L); 73 Property animation view.animate() .rotationX(180f) .setDuration(1000L) .withLayer(); 74 Tipy a triky • LayoutTransition • LayoutAnimationController • ViewPager Transformer • Window Animation 75 Layout Transition • v xml: android:animateLayoutChanges=”true” • final LayoutTransition transition = new LayoutTransition();
 view.setLayoutTransition(transition); 76 Layout Animation Controller • Animace itemů ListView/GridView. • Využívá api level 1 animace. 77 Layout Animation controller Animation anim = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_bottom_top); ! LayoutAnimationController c = new LayoutAnimationController(anim); ! getListView().setLayoutAnimation(c); 78 ViewPager Transformer • Transformace každé stránky podle současné pozice. • ViewPager.setPageTransformer(...) 79 Window animation ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight()); ! Intent intent = new Intent(getActivity(), MyActivity.class); startActivity(intent, options.toBundle()); 80 Window animation overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 81 Styly a témata • Style • sada vlastností které určují vzhled a formát okna nebo konkrétního view • Theme • styl aplikovaný na celou aplikaci 82 Inline vs Style vs Theme • Level 0 - inline • Level 1 - style • Level 2 - theme 83 Inline vs Style vs Theme • Level 0 - inline 84 layout.xml Inline vs Style vs Theme • Level 1 - style 85 Styles.xml layout.xml Inline vs Style vs Theme • Level 2 - theme 86 layout.xml themes.xml Výhody • Šetří čas • Neopakuje se stále stejný kód • Oddělení vzhledu od struktury UI • je vyměnitelný 87 Přepínání témat • Plné využití themes jak jsme si ukázali • Navíc: • Vlastní view • Ikonky • Různé styly pro text 88 Attribute • V layout.xml nepřiřadíme přímo style, ale attribute • Hodnotu attributu nastavíme v tématu • Attribute se vyhodnotí v runtimu podle aktuálního tématu 89 Attribute 90 attrs.xml Attribute 91 theme.xml Attribute 92 theme.xml Attribute 93 layout.xml Přepínání témat 94 public abstract class BaseActivity extends Activity { ! private SkinManager mManager; private int mCurrentThemeId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... ! final int themeId = this.mManager.getSelectedThemeId(); mCurrentThemeId = themeId; this.setTheme(themeId); } ! ... ! } Přepínání témat 95 @Override protected void onResume() { if (mCurrentThemeId != mManager.getSelectedThemeId()) { Log.d(Utils.TAG, "new theme selected, restarting activity"); Intent starterIntent = this.getIntent(); starterIntent.setAction(null); ! startActivity(starterIntent); finish(); super.onResume(); return; } } Přepínání témat 96 Díky. Otázky? 97