Android ImageView Animation

  • 13 Antworten
  • Neuester Beitrag
Diskutiere Android ImageView Animation im Android App Entwicklung im Bereich Betriebssysteme & Apps.
M

motoboy92

Neues Mitglied
Hallo,

ich möchte ein ImageView rotieren lassen.

Code:
AnimatorSet wheelSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.wheel_spin);
      //  wheelSet.setTarget(wheel);
      //  wheelSet.start();
Soweit funktioniert auch alles.

Ich möchte aber die Werte nicht in einer XML definieren, sondern diese Werte variabel einstellen, sodass ich sie währen des drehens ändern kann.

Hab ihr eine Idee ?

Viele Grüße
 
Jaiel

Jaiel

Dauergast
Hast du die API schon mal durchgeguckt? mit dieser Methode kannst du es soweit ich gesehen habe nur aus xml ressourcen die animation laden.
Es geht also nciht damit zur Zeit.

du musst dir für die Animation etwas anderes euinfallen alssen.
 
M

motoboy92

Neues Mitglied
Danke für deine Antwort.

Fällt dir gerade ein, wie ich das machen kann ?

über

Code:
imageview.setRotation(angle)
kann ich ja das bild drehen mit einer variable..aber eben keine animation ..also ein flüssiges drehen
 
Jaiel

Jaiel

Dauergast
Könntest du dann näher erläutern was genau deine Anforderungen sind?
 
M

motoboy92

Neues Mitglied
Natürlich.



Ich möchte eine Art GaugeView wie im Bild erstellen.

Ich habe ein ImageView Zeiger und dieses ImageView möchte ich Anhand von Werten flüssig drehen.
 
Jaiel

Jaiel

Dauergast
Ok

Warum möchtest du dafür die gesamte View drehen? Und nicht einfach nur den Zeiger als Bitmap auf dem Canvas der Imageview?
 
Kardroid

Kardroid

Stammgast
Hi, das ist mal eine spannende Frage.
In welchen Zeitabständen bekommst du denn die Werte?

Vielleicht kann man dann ein Algorithmus bauen, welcher die Strecke in einer gewissen Zeit "abfährt".
Also ein Wert jede Sekunde und der Zeiger soll innerhalb einer Sekunde auch den Zielwert erreichen.
Dann könnte man den Neuen Wert minus den alten Wert nehmen, und dann die Strecke dazwischen auf 1 Sekunde berechnen und dann alle 100 Millisekunden den Zeiger um 1/10 des Wertes weiterdrehen lassen.

Wichtig wären hier die Zeitabstände der Werte.
 
M

motoboy92

Neues Mitglied
Jaiel schrieb:
Ok

Warum möchtest du dafür die gesamte View drehen? Und nicht einfach nur den Zeiger als Bitmap auf dem Canvas der Imageview?

Ich dachte ich komme irgendwie drum herum, es über ein Bitmap des Zeigers zu machen. Es gab ja schon die vielversprechende Funktion der Animation und
auf dieser wollte ich aufbauen.

Kardroid schrieb:
Hi, das ist mal eine spannende Frage.
In welchen Zeitabständen bekommst du denn die Werte?

Vielleicht kann man dann ein Algorithmus bauen, welcher die Strecke in einer gewissen Zeit "abfährt".
Also ein Wert jede Sekunde und der Zeiger soll innerhalb einer Sekunde auch den Zielwert erreichen.
Dann könnte man den Neuen Wert minus den alten Wert nehmen, und dann die Strecke dazwischen auf 1 Sekunde berechnen und dann alle 100 Millisekunden den Zeiger um 1/10 des Wertes weiterdrehen lassen.

Wichtig wären hier die Zeitabstände der Werte.
Ich hatte mir alle 500ms überlegt, aber mit 1sec kann ich auch noch leben.
Man kann diesen Algorithmus ja später immernoch anpassen.
 
Jaiel

Jaiel

Dauergast
Oder man dreht es sobald der Wert sich ändert einfach auf die position. Ich weiß nciht wie sich da die Werte ändern werden ob schlagartig von 0 auf 100% oder nciht.

Wie dem auch sei du kannst den Canvas und seine Methoden dafür benutzen.

Einfach den Drehpunkt aussuchen udn vor dem Zeichnen des Zeigers das gesamte Canvas drehen, zeichnen , zurückdrehen.Eine (Zeichen)MAtrix sollte dabei helfen
 
Zuletzt bearbeitet:
Kardroid

Kardroid

Stammgast
Hi,

ich habe mal ein Testprojekt erstellt und ein Video gedreht, und daraus dann ein GIF gemacht.
Bei dem GIF sieht man es nicht so gut, aber der Zeiger bewegt sich "smooth" und nicht so abgehakt.

Ist es das, wie du es dir vorgestellt hast?
Mein Code ist zwar nicht memoryfreundlich, aber dafür wird schon mit Values gearbeitet und die Umrechnung in Grad passiert automatisch.
Ein Wert von 100 wird auch mit dem Zeiger auf 100 gezeigt ein Wert von 50 ist genau in der Mitte etc.

Mit dem ersten Button lassen sich Random Values generieren und anzeigen.
Der zweite Button lässt eine Progress von 100 bis 0 durchlaufen
Und der dritte Button mach 10 Sekunden lang Randomvalues.
Dabei habe ich die Animationsgewindigkeit auf 900ms gesetzt, so gibt es keine Sprünge.

 

Anhänge

M

motoboy92

Neues Mitglied
Ja, so habe ich mir das vorgestellt.

Die Original Gauge macht das ja mit Canvas und zeichnet immer neu...
Wie machst du das ?
 
Kardroid

Kardroid

Stammgast
Ich mache das mit einem Drehen der ImageView wie du es am Anfang angefragt hast.
XML:
HTML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/meter">

    <ImageView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/background"/>

    <ImageView
        android:id="@+id/nadel"
        android:layout_marginTop="46dp"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/nadel2"/>

    </RelativeLayout>

    <Button
        android:id="@+id/randomnumber"
        android:layout_below="@id/meter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="set random value"
        android:onClick="setRandomValue"
        />

    <Button
        android:id="@+id/progress"
        android:layout_below="@id/randomnumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="set progress values"
        android:onClick="setProgressValues"
        />

    <Button
        android:id="@+id/tentimesrandom"
        android:layout_below="@id/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="set 10 times random"
        android:onClick="setTenTimesValues"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:layout_alignParentBottom="true"
        android:id="@+id/textview"
        android:textSize="20dp"
        android:layout_marginLeft="10dp"
        android:layout_marginBottom="10dp"/>



</RelativeLayout>
JavaCode:
Code:
package de.kardroids.testprojekt;

import android.app.Activity;
import android.app.ListActivity;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Random;


public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);



    }

    float oldRotation = 0.0f;
    public void setRandomValue(View view) {

        Random ran = new Random();
        int randomNumber = ran.nextInt(100);

        final ImageView myImageView = (ImageView)findViewById(R.id.nadel);

        AnimationSet animSet = new AnimationSet(true);
        animSet.setInterpolator(new DecelerateInterpolator());
        animSet.setFillAfter(true);
        animSet.setFillEnabled(true);

        TextView textView = (TextView) findViewById(R.id.textview);

        float rotationOldValue = myImageView.getRotation()/2.4f;
        float newRotationValue = randomNumber - rotationOldValue;

        final float rotationNumber = newRotationValue*2.4f;

        textView.setText("value: " + newRotationValue + " degree: " + rotationNumber);

        final RotateAnimation animRotate = new RotateAnimation(oldRotation, rotationNumber,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);

        animRotate.setDuration(1500);
        animRotate.setFillAfter(true);

        animRotate.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                oldRotation = rotationNumber;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        animSet.addAnimation(animRotate);

        myImageView.startAnimation(animSet);

    }


    public void setProgressValues(View view) {

        CountDownTimer myCountdownTimer =    new CountDownTimer(12000, 1000) {

            public void onTick(long millisUntilFinished) {

                final ImageView myImageView = (ImageView)findViewById(R.id.nadel);

                AnimationSet animSet = new AnimationSet(true);
                animSet.setInterpolator(new DecelerateInterpolator());
                animSet.setFillAfter(true);
                animSet.setFillEnabled(true);


                TextView textView = (TextView) findViewById(R.id.textview);

                final float rotationNumber = (millisUntilFinished-2000)/100*2.4f;

                textView.setText("value: " + (millisUntilFinished-2000)*10 + " degree: " + rotationNumber);


                final RotateAnimation animRotate = new RotateAnimation(oldRotation, rotationNumber,
                        RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                        RotateAnimation.RELATIVE_TO_SELF, 0.5f);

                animRotate.setDuration(900);
                animRotate.setFillAfter(true);

                animRotate.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        oldRotation = rotationNumber;
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });

                animSet.addAnimation(animRotate);

                myImageView.startAnimation(animSet);

                //mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
                // Kick off your AsyncTask here.
            }

            public void onFinish() {
                //mTextField.setText("done!");
                // the 30 seconds is up now so do make any checks you need here.
            }
        }.start();






    }

    public void setTenTimesValues(View view) {

        CountDownTimer myCountdownTimer =    new CountDownTimer(12000, 1000) {

            public void onTick(long millisUntilFinished) {

                final ImageView myImageView = (ImageView)findViewById(R.id.nadel);

                AnimationSet animSet = new AnimationSet(true);
                animSet.setInterpolator(new DecelerateInterpolator());
                animSet.setFillAfter(true);
                animSet.setFillEnabled(true);


                TextView textView = (TextView) findViewById(R.id.textview);

                Random ran = new Random();
                int randomNumber = ran.nextInt(100);

                final float rotationNumber = randomNumber*2.4f;

                textView.setText("value: " + randomNumber*10 + " degree: " + rotationNumber);

                final RotateAnimation animRotate = new RotateAnimation(oldRotation, rotationNumber,
                        RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                        RotateAnimation.RELATIVE_TO_SELF, 0.5f);

                animRotate.setDuration(900);
                animRotate.setFillAfter(true);

                animRotate.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        oldRotation = rotationNumber;
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });

                animSet.addAnimation(animRotate);

                myImageView.startAnimation(animSet);

                //mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
                // Kick off your AsyncTask here.
            }

            public void onFinish() {
                //mTextField.setText("done!");
                // the 30 seconds is up now so do make any checks you need here.
            }
        }.start();

    }
}
Wie gesagt, das ist eher ein POC als wirklich produktiver Code.
Du kannst dir ja daraus deine Lösung ableiten.
 
M

motoboy92

Neues Mitglied
Vielen Dank!

Vielen Dank!