Slide 1

Slide 1 text

Android School Warsztat 07 Adam Jodłowski

Slide 2

Slide 2 text

2 Animowane grafiki ● potrzebujemy osobne grafiki dla każdej klatki oraz XML w /res/drawable ● odtwarzanie animacji ImageView iv = (ImageView) findViewById(R.id.imageView); iv.setImageDrawable(getResources().getDrawable(R.drawable.my_animation)); AnimationDrawable anim = (AnimationDrawable) iv.getDrawable(); ... anim.start();

Slide 3

Slide 3 text

3 Animacje przejść ● zaprezentowane zostanie klasyczne API, nowa wersja oparta jest na Animator i została przeportowana w projekcie NineOldAndroids dla starszych platform ● możemy w prosty sposób animować obiekty (pod)typu View, klatki animacji są interpolowane na podstawie definicji przekształceń, najczęściej z plików XML Animation anim = AnimationUtils.loadAnimation(ctx, R.anim.myanim); view.startAnimation(anim); ● przykład zmiany przezroczystości ● aby reagować na zmiany stanu animacji, warto zaimplementować android.view.animation.Animation.AnimationListener

Slide 4

Slide 4 text

4 Animacje przejść ● przykład skalowania widoków ● sekwencje w węźle układamy korzystając z właściwości startOffset i duration ● przykład obrotu ● przykład przesunięcia ● wszystkie animacje w formie XML można również tworzyć w sposób programowy

Slide 5

Slide 5 text

5 Animacje programowe ● przykład tworzenia animacji przejść w sposób programowy private Animation inFromLeftAnimation() { Animation anim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -1.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f); anim.setDuration(300); anim.setInterpolator(new AccelerateInterpolator()); return anim; } private Animation outToRightAnimation() { Animation anim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, +1.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f); anim.setDuration(300); anim.setInterpolator(new AccelerateInterpolator()); return anim; } . . .

Slide 6

Slide 6 text

6 Interpolatory ● interpolatory określają tempo i efekty przejść, rozróżniamy m.in. AccelerateInterpolator, AnticipateInterpolator, BounceInterpolator, CycleInterpolator, OvershootInterpolator ● aplikujemy je jako właściwości w XML dla węzła android:interpolator="@android:anim/bounce_interpolator" ● możemy tworzyć również własne interpolatory oraz modyfikować istniejące . . . . .

Slide 7

Slide 7 text

7 Zapoznaj się z różnymi rodzajami animacji i przekształceń komponentów wizualnych.

Slide 8

Slide 8 text

8 ViewFlipper ● komponent zawierający widoki podrzędne, które wyświetla pojedynczo i opcjonalnie animuje przejścia między nimi setInAnimation(ctx, android.R.anim.slide_in_left); setOutAnimation(ctx, android.R.anim.slide_out_right); showNext(); showPrevious(); setDisplayedChild(index); setFlipInterval(5000); setAutoStart(true); startFlipping(); stopFlipping(); ● umieszczamy komponent w layoucie danego ekranu a w jego środku widoki, które mają być animowane

Slide 9

Slide 9 text

9 Przetestuj komponent ViewFlipper.

Slide 10

Slide 10 text

10 Reakcja na dotyk ● każdy widok może zarejestrować metodę zwrotną, wywoływaną w reakcji na dotyk ImageView iv = (ImageView) findViewById(R.id.imageView1); iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.d("AS", "ACTION=" + event.getAction()); Log.d("AS", "X=" + event.getX()); Log.d("AS", "Y=" + event.getY()); return true; } }); . .

Slide 11

Slide 11 text

11 Rozpoznawanie gestów, GestureDetector ● przesłaniamy metodę aktywności i rozpoznajemy dotyk @Override public boolean onTouchEvent(MotionEvent touchevent) { switch (touchevent.getAction()) { case MotionEvent.ACTION_DOWN: startX = touchevent.getX(); break; case MotionEvent.ACTION_UP: if (startX < touchevent.getX()) ... if (startX > touchevent.getX()) ... break; case MotionEvent.ACTION_MOVE: touchevent.getX(); ... touchevent.getY(); ... break; } return false; } ● GestureDetector wykrywa za nas najpopularniejsze proste gesty, używamy do tego interfejsu SimpleOnGestureListener onDown(); onSingleTapConfirmed(); onDoubleTap(); onLongPress(); onScroll(); onFling(); ● ScaleGestureDetector wykrywa gesty wielodotykowe służące do skalowania widoków

Slide 12

Slide 12 text

12 Przykład rozpoznawania gestów ● tworzymy obiekt własnego detektora gestów i używamy go w aktywności lub konkretnym widoku GestureDetector myGestureDetector = new GestureDetector(new MyGestureDetector()); @Override public boolean onTouchEvent(MotionEvent me) { return myGestureDetector.onTouchEvent(me); } ● przykład implementacji detektora class MyGestureDetector extends SimpleOnGestureListener { private static final int MIN_DISTANCE = 120; private static final int MAX_DISTANCE = 250; private static final int VELOCITY = 200; @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (Math.abs(e1.getY() - e2.getY()) > MAX_DISTANCE) return false; if (e1.getX() - e2.getX() > MIN_DISTANCE && Math.abs(velocityX) > VELOCITY) { flipper.setInAnimation(inFromRightAnimation()); flipper.setOutAnimation(outToLeftAnimation()); flipper.showNext(); } else if (e2.getX() - e1.getX() > MIN_DISTANCE && Math.abs(velocityX) > VELOCITY) { flipper.setInAnimation(inFromLeftAnimation()); flipper.setOutAnimation(outToRightAnimation()); flipper.showPrevious(); } return super.onFling(e1, e2, velocityX, velocityY); } ... }

Slide 13

Slide 13 text

13 Przetestuj możliwości wykrywania dotyku.

Slide 14

Slide 14 text

14 Sensory ● urządzenia mogą posiadać wiele czujników, m.in. światła bliskości temperatury ciśnienia przyspieszenia pola magnetycznego ● możemy zgłosić w manifeście wymaganie posiadania czujnika przez urządzenie ● symulowanie odczytów w emulatorze zapewnia projekt Sensor Simulator

Slide 15

Slide 15 text

15 Inicjalizacja i odczyt wartości ● musimy pobrać usługę SensorManagera i zainicjować interesujący nas sensor SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE); Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL); // rejestracja ... sensorManager.unregisterListener(this, lightSensor); // wyrejestrowanie ● częstotliwość odczytów może być regulowana dodatkowymi parametrami, jak SENSOR_DELAY_UI, SENSOR_DELAY_GAME, SENSOR_DELAY_FASTEST ● implementujemy interfejs SensorEventListener @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { Log.d("AS", "dokladnosc sensora " + sensor.getName() + " wynosi: " + accuracy); } @Override public void onSensorChanged(SensorEvent event) { String values = ""; for (float v : event.values) values += v + ", "; Log.d("AS", "odczyt " + event.sensor.getName() + ": " + values); }

Slide 16

Slide 16 text

16 Możliwości API sensorów ● odczyty z sensorów udostępniają wartości pomocnicze wykorzystywany prąd w mA maksymalną przyjmowaną wartość rozdzielczość czujnika nazwę producenta, typ i wersję ● korzystamy z pakietu android.hardware ● najczęściej wykorzystujemy akcelerometr, spoczywający telefon powinien zwrócić odczyty (0, 0, 9.81) w osiach X, Y i Z, podaje on siły działające na urządzenie uwzględniając grawitację ● orientację ekranu odczytujemy z Display.getRotation()/getOrientation()*

Slide 17

Slide 17 text

17 Przetestuj możliwości odczytu wartości sensorów.

Slide 18

Slide 18 text

18 Zadanie domowe: Stwórz aplikację wykorzystującą poznane techniki animacji i rozpoznawania dotyku.