Tutorial Rotating Dialer

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von v Ralle v, 19.12.2011.

  1. v Ralle v, 19.12.2011 #1
    v Ralle v

    v Ralle v Threadstarter Android-Lexikon

    Beiträge:
    913
    Erhaltene Danke:
    199
    Registriert seit:
    27.08.2010
    Hallo,

    ich bin schon länger in der Android Welt unterwegs und helfe auch ab und zu hier im Forum. Nun habe ich ein Tutorial für Mobile Tuts geschrieben. Darin zeige ich, wie man recht leicht mit Hilfe des SDKs eine rotierende Animation erzeugen kann (siehe meine Shutdown App in der Signatur).

    Ich hoffe das Tutorial interessiert den ein oder anderen. Über Anregungen und ein Feedback würde ich mich freuen :)

    Android SDK: Creating a Rotating Dialer
     
    DieGoldeneMitte bedankt sich.
  2. DieGoldeneMitte, 20.12.2011 #2
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Super, aber was hast du gegen java.lang.Math.atan2 ? :D
     
  3. v Ralle v, 20.12.2011 #3
    v Ralle v

    v Ralle v Threadstarter Android-Lexikon

    Beiträge:
    913
    Erhaltene Danke:
    199
    Registriert seit:
    27.08.2010
    Im Prinzip nichts ^^ Wie hätte sich die Berechnung vom Winkel verkürzt?
     
  4. DieGoldeneMitte, 20.12.2011 #4
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Erstmal wird daraus das folgende: (Bin deinen Code jetzt nicht soweit durchgegangen, ob man den angle<0 braucht)

    Code:
    private double getAngle(double xTouch, double yTouch) {
      double x = xTouch - (dialerWidth / 2d);
      double y = dialerHeight - yTouch - (dialerHeight / 2d);
      double angle = Math.atan2(y,x) * 180 / Math.PI;
      if( angle<0 ) angle += 2 * Math.PI;
      return angle;
    }
    Und bei dem onFling könnte man vermutlich auch was machen, indem man den Angle vom Event
    ausrechnet und dann guckt, ob der Winkelunterschied >180 (modulo 360) ist. Aber dazu muss ich
    das Tutorial erstmal richtig ausprobieren.

    (habe mal was ähnliches nur ohne Fling gemacht)

    ADD: in deinem Download ist ein Tutorial.apk zu viel drinne. :D
     
    Zuletzt bearbeitet: 20.12.2011
    v Ralle v bedankt sich.
  5. v Ralle v, 20.12.2011 #5
    v Ralle v

    v Ralle v Threadstarter Android-Lexikon

    Beiträge:
    913
    Erhaltene Danke:
    199
    Registriert seit:
    27.08.2010
    Oh das sieht schlanker aus. Muss ich demnächst mal so auprobieren.

    Ich glaube, die haben das Paket selber nochmal zusammengepackt, daher eine .apk zu viel. Sollte aber nicht stören ^^
     
  6. DieGoldeneMitte, 20.12.2011 #6
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Noch ein paar Anmerkungen:


    • Das Bild ist arg groß (1024x0124) - das kann gerade auf einem kleinen Handy (wie meinem Nexus One) zu Abstürzen führen, weil der Speicher ausgeht. 512x512 tuts auch :)
    • Du hast da einige Instanz-Variablen static definiert, das kann zu Problemen führen, wenn das Handy gedreht wird und App neu gestartet wird. Bei mir führte das dazu, dass der Dialer zu "eiern" anfing also nicht in die Mitte gezeichnet wurde.
    • Im onGlobalLayout() (danke, den Listener kanne ich noch garnicht) würde ich die Resourcen neu aufbauen, wenn sich die Werte ändern (also nicht auf ==0 sondern auf !=dialer.get*() prüfen.) dann kann man im Manifest auch orientationChange setzen.
    • natürlich muss man in diesem Fall die Matrix resetten :D
     
  7. v Ralle v, 20.12.2011 #7
    v Ralle v

    v Ralle v Threadstarter Android-Lexikon

    Beiträge:
    913
    Erhaltene Danke:
    199
    Registriert seit:
    27.08.2010
    Du scheinst dich mit dem Tutorial zu beschäftigen, das gefällt mir ^^

    Zu der Grafik: das habe ich im Tutorial begründet :) Damit werden alle Bildschirmgrößen (auch Tablets) abgedeckt und man hat die Grafik nur einmal. Das hilft der Größe der .apk. Es ist wie gesagt nur eine Demo. Hast aber Recht, bei sehr kleinen Geräten kann das zu groß sein und sie können sich ja keine ldpi Datei holen.

    static sind nur die Grafiken und die Matrix, keine andere Variable. Bei denen macht es natürlich auch Sinn (siehe Kommentare im Code). Welche Variablen meinst du denn? Der Dialer eiert in der Mitte des Tutorials, aber nicht am Ende, wird eigentlich auch beschrieben.

    Punkt 3 ist Designsache. Bei einen orientationChange wird auch eine neue Activity erzeugt, daher sind die Membervariablen wieder 0. Ich denke, daher geht die Abfrage auch in Ordnung. Hast aber mit dem Manifest recht. Nur wollte ich es so lassen, weil ich am Anfang auch sage, dass man verschiedene andere Views einbinden kann. Was passiert, wenn sich die Landscape Varianter unterscheidet? Daher habe ich es gleich komplett gemacht.

    Dennoch danke für die Anmerkungen :)
     
  8. DieGoldeneMitte, 20.12.2011 #8
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Nein, bei mir eiert die fertige App. Mit eiern meine ich nicht rückwärts drehen oder sowas, sondern dass sich der Ring zwar um den Mittelpunkt des Bildschirms dreht (und auch um den richtigen Winkel gedreht wird), aber nicht zentriert in die Mitte des Bildschirms gemalt wird.

    Es liegt an dem static vor Matrix. Die aktiven ge post'eten Threads der alten Activity pfuschen in der Matrix der neuen Activity herum. Passiert natürlich nur, wenn man rotiert, während der Fling läuft. (Mach mal ein Log.d("tutorial",this.toString()); im rotateDialer, dann sieht man es).

    Ist klar, ich bin halt mehr von der vorbereitenderen Sorte.
     
    Zuletzt bearbeitet: 20.12.2011
    v Ralle v bedankt sich.
  9. v Ralle v, 20.12.2011 #9
    v Ralle v

    v Ralle v Threadstarter Android-Lexikon

    Beiträge:
    913
    Erhaltene Danke:
    199
    Registriert seit:
    27.08.2010
    Ja, du hast recht mit dem Eiern. So sehr hatte ich es dann doch nicht getestet ^^ Aber wie du bereits angemerkt hast: die Matrix als Membervariable deklarieren. Man könnte aber auch (ohne es getestet zu haben), die onDestroy Methode überschreiben und die allowRotating Variable auf false setzen. Sollte ressourcenschonender sein. Dennoch danke für den Bug, den muss ich in meiner App ausbessern :D

    Wenn du magst, kannst du deine Methode aus der Nachricht auch noch hier posten. Die sieht nämlich wesentlich besser aus als meine :D
     
  10. DieGoldeneMitte, 21.12.2011 #10
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Naja, Matrix ist kein besonderes fettes Objekt, da darf man schon pro Drehung eins erzeugen, wenn gleichzeitig ohnehin 3MB an Pixeldaten neu skaliert :D

    Okay, here we go:

    Code:
        private final static float FLING_SPEED = 0.4;
    
        private class MyGestureDetector extends SimpleOnGestureListener {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        
                double x1 = e1.getX() - (dialerWidth / 2);
                double y1 = dialerHeight - e1.getY() - (dialerHeight / 2);
                
                double x2 = e2.getX() - (dialerWidth / 2);
                double y2 = dialerHeight - e2.getY() - (dialerHeight / 2);
                
                float speed = (float)(Math.sqrt( velocityX * velocityX + velocityY * velocityY ) * FLING_SPEED);
    
                float dir = (float)Math.signum( y1 * x2 - x1 * y2 );
                // Berechnung der Orientierung der Drehung anhand der Determinate von
                // Anfang und Ende des Flings.
                
                dialer.post( new FlingRunnable( dir * speed ));
                
                return true;
            }
        }
    
     

Diese Seite empfehlen