مقدمه

امروزه سیستم عامل اندروید ( Android ) جای خود را به خوبی در بین تمام سیستم عامل های موبایل باز کرده و بسیاری از افراد از این سیتستم عامل استفاده میکنند. این که امروزه تعداد زیادی از افراد از این سیستم عامل استفاده می کنند باعث می شود تا بسیاری از افراد شروع به نوشتن برنامه برای سیستم عامل اندروید کنند تا بتوانند سهمی از این بازار بسیار قوی و پرتقاضا داشته باشند. همانگونه که میدانید برنامه نویسی در اندروید با استفاده از زبان برنامه نویسی جاوا و در درون محیط اندروید استودیو انجام میپذیرد. در این مقاله میخواهیم به آموزش ساخت انیمیشن در اندروید استودیو بپردازیم و ببینیم که ساخت انیمیشن در اندروید استودیو به چه شکل بوده و نحوه انجام آن چگونه است. تا بتوانیم در ساخت نرم افزار های خود از آن استفاده کرده و انیمیشن های مورد نیاز خود را در درون برنامه خود وارد کنیم. در این آموزش ما از ویژگی Animation API استفاده کرده و نحوه کار آن را باهم خواهیم دید.

ساخت انیمیشن در اندروید استودیو

استفاده از انیمیشن ها

در حقیقت اندروید امکان تغییر ویژگی های یک شی را در یک بازه زمانی مشخص و خاص از طریق Animation API به توسعه دهندگان میدهد. باید گفت که ابر کلاس ( super class ) API انیمیشن، کلاس Animator است که با استفاده از آن می توان خواص یک شی ( object ) را مشخص نمود. همچنین شما میتوانید به سادگی یک کلاس AnimatorListener را در درون برنامه خود استفاده کنید. این کلاس می تواند به سادگی قبل و بعد از انیمیشن برای شما کارهایی از قبیل اضافه یا کم کردن و… را انجام دهد.

متد animate() برروی یک شی View میتواند باعث ایجاد انیمیشن های روانتر گردد که نحوه انجام آن را با یک مثال در پاییت خواهیم دید.

myView.animate().translationX(400);



// if an animation is slow you can try to activate a hardware layer which

// uses a cache

// watch-out: this might not always result in a correct animation



myView.animate().translationX(400).withLayer();

 

شما همچنین میتوانید یک Action را رجیستر کرده تا بتواند در قبل یا بعد از انیمیشن شما اجرا شود. برای مثال در کد زیر ما این کار را انجام داده ایم.

// StartActionmyView.animate().translationX(100).withStartAction(new Runnable(){    public void run(){        viewer.setTranslationX(100-myView.getWidth());        // do something    }}); // EndActionmyView.animate().alpha(0).withEndAction(new Runnable(){    public void run(){        // rRemove the view from the parent layout        parent.removeView(myView);    }});

 

در برخی مواقع ما نیاز داریم تا سرعت انیمیشن خود را تغییر دهیم. برای این کار ما به سادگی میتوانیم از ()setInterpolator استفاده کرده و یک شی TimeInterpolator به همراه انیمیشن خود بسازیم. باید گفت که استاندارد این تغییر سرعت یا رنج سرعت به صورت خطی است اما اندروید تعداد بسیار کمی از این شی های پیشفرض برای خطی نبودن روند کاهش یا افزایش سرعت انیمیشن دارد.

اندروید در حقیقت توانایی شناخت هر نوع از انیمیشن را ندارد. برای اینکه بتوانید انیمیشن دلخواه خود را به اندروید معرفی کنید میتوانید از تابع setEvaluator و ایجاد یک شی TypeEvaluator استفاده کنید.

کلاس  LayoutTransition

این کلاس اجازه استفاده از تنظیمات انیمیشن در Layout نرم افزار شما را می دهد. این تابع به صورت سلسله مراتبی تمام محتویات را انیمیت میکند.

package com.example.android.layoutanimation; import android.animation.LayoutTransition;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.View;import android.view.ViewGroup;import android.widget.Button; public class MainActivity extends Activity {     private ViewGroup viewGroup;     @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        LayoutTransition l = new LayoutTransition();        l.enableTransitionType(LayoutTransition.CHANGING);        viewGroup = (ViewGroup) findViewById(R.id.container);        viewGroup.setLayoutTransition(l);     }     public void onClick(View view) {        viewGroup.addView(new Button(this));    }     @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.activity_main, menu);        return true;    }}

 

انیمیشن در میان جابجایی فعالیت ها

در حقیقت انیمیشن ها را می توان در ویو ها و یا transition بین فعالیت ها قرار داد. کلاس ActivityOptions به ما کمک می کند تا بتوانیم انیمیشن ها را معرفی کنیم.

public void onClick(View view) {    Intent intent = new Intent(this, SecondActivity.class);    ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0,            0, view.getWidth(), view.getHeight());    startActivity(intent, options.toBundle());}

 

مثال های استفاده از API انیمیشن

تا اینجا با تعدادی از کلاس ها آشنا شده و برای هرکدام از آن ها مثالی را مشاهده کردیم. حال نوبت این است که مثال هایی را برای استفاده از API انیمیشن باهم ببینیم. در ابتدا یک پکیج Top Level به نام com.vogella.android.animation.views ایجاد کرده و سپس یک فعالیت یا Activity با نام AnimationExampleActivity ایجاد میکنیم. فایل Layout ما باید activity_main.xml نام داشته باشد و آن را به شکل کد زیر تغییر می دهیم.

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/layout"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >     <LinearLayout        android:id="@+id/test"        android:layout_width="wrap_content"        android:layout_height="wrap_content" >         <Button            android:id="@+id/Button01"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="startAnimation"            android:text="Rotate" />         <Button            android:id="@+id/Button04"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="startAnimation"            android:text="Group" >        </Button>         <Button            android:id="@+id/Button03"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="startAnimation"            android:text="Fade" />         <Button            android:id="@+id/Button02"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="startAnimation"            android:text="Animate" />     </LinearLayout>     <ImageView        android:id="@+id/imageView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"        android:src="@drawable/icon" />     <TextView        android:id="@+id/textView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_above="@+id/imageView1"        android:layout_alignRight="@+id/imageView1"        android:layout_marginBottom="30dp"        android:text="Large Text"        android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>

Menu resource پایین را ایجاد می کنیم.

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" >     <item        android:id="@+id/item1"        android:showAsAction="ifRoom"        android:title="Game">    </item> </menu>

حال activity خود را به شکل لیست زیر عوض می کنیم.

package com.vogella.android.animation.views; import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.app.Activity;import android.content.Intent;import android.graphics.Paint;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.ImageView;import android.widget.TextView; public class AnimationExampleActivity extends Activity {     /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);     }     public void startAnimation(View view) {        float dest = 0;        ImageView aniView = (ImageView) findViewById(R.id.imageView1);        switch (view.getId()) {         case R.id.Button01:            dest = 360;            if (aniView.getRotation() == 360) {                System.out.println(aniView.getAlpha());                dest = 0;            }            ObjectAnimator animation1 = ObjectAnimator.ofFloat(aniView,                    "rotation", dest);            animation1.setDuration(2000);            animation1.start();            // Show how to load an animation from XML            // Animation animation1 = AnimationUtils.loadAnimation(this,            // R.anim.myanimation);            // animation1.setAnimationListener(this);            // animatedView1.startAnimation(animation1);            break;         case R.id.Button02:            // shows how to define a animation via code            // also use an Interpolator (BounceInterpolator)            Paint paint = new Paint();            TextView aniTextView = (TextView) findViewById(R.id.textView1);            float measureTextCenter = paint.measureText(aniTextView.getText()                    .toString());            dest = 0 - measureTextCenter;            if (aniTextView.getX() < 0) {                dest = 0;            }            ObjectAnimator animation2 = ObjectAnimator.ofFloat(aniTextView,                    "x", dest);            animation2.setDuration(2000);            animation2.start();            break;         case R.id.Button03:            // demonstrate fading and adding an AnimationListener             dest = 1;            if (aniView.getAlpha() > 0) {                dest = 0;            }            ObjectAnimator animation3 = ObjectAnimator.ofFloat(aniView,                    "alpha", dest);            animation3.setDuration(2000);            animation3.start();            break;         case R.id.Button04:             ObjectAnimator fadeOut = ObjectAnimator.ofFloat(aniView, "alpha",                    0f);            fadeOut.setDuration(2000);            ObjectAnimator mover = ObjectAnimator.ofFloat(aniView,                    "translationX", -500f, 0f);            mover.setDuration(2000);            ObjectAnimator fadeIn = ObjectAnimator.ofFloat(aniView, "alpha",                    0f, 1f);            fadeIn.setDuration(2000);            AnimatorSet animatorSet = new AnimatorSet();             animatorSet.play(mover).with(fadeIn).after(fadeOut);            animatorSet.start();            break;         default:            break;        }     }     @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.mymenu, menu);        return super.onCreateOptionsMenu(menu);    }     @Override    public boolean onOptionsItemSelected(MenuItem item) {        Intent intent = new Intent(this, HitActivity.class);        startActivity(intent);        return true;    }}

پس از انجام این کار به شکل زیر یک فایل Layout با فرمت XML ایجاد کرده و با نام target نام گذاری میکنیم.

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:orientation="vertical"              android:layout_width="match_parent"              android:layout_height="match_parent">     <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/button1"/> </LinearLayout>

 

حال فعالیت HitActivity را ایجاد میکنیم.

package com.vogella.android.animation.views; import java.util.Random; import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button; public class HitActivity extends Activity {    private ObjectAnimator animation1;    private ObjectAnimator animation2;    private Button button;    private Random randon;    private int width;    private int height;    private AnimatorSet set;     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.target);        width = getWindowManager().getDefaultDisplay().getWidth();        height = getWindowManager().getDefaultDisplay().getHeight();        randon = new Random();         set = createAnimation();        set.start();        set.addListener(new AnimatorListenerAdapter() {             @Override            public void onAnimationEnd(Animator animation) {                int nextX = randon.nextInt(width);                int nextY = randon.nextInt(height);                animation1 = ObjectAnimator.ofFloat(button, "x", button.getX(),                        nextX);                animation1.setDuration(1400);                animation2 = ObjectAnimator.ofFloat(button, "y", button.getY(),                        nextY);                animation2.setDuration(1400);                set.playTogether(animation1, animation2);                set.start();            }        });    }     public void onClick(View view) {        String string = button.getText().toString();        int hitTarget = Integer.valueOf(string) + 1;        button.setText(String.valueOf(hitTarget));    }     private AnimatorSet createAnimation() {        int nextX = randon.nextInt(width);        int nextY = randon.nextInt(height);        button = (Button) findViewById(R.id.button1);        animation1 = ObjectAnimator.ofFloat(button, "x", nextX);        animation1.setDuration(1400);        animation2 = ObjectAnimator.ofFloat(button, "y", nextY);        animation2.setDuration(1400);        AnimatorSet set = new AnimatorSet();        set.playTogether(animation1, animation2);        return set;    }}

 

حال اگر این برنامه را اجرا کنید و دکمه های مختلف را بزنید انیمیشن باید توسط نوار ابزار اجرا شود.

فعالیت انیمیشن ها در اندروید با share views

اندروید اینقابلیت را قرار داده است تا علاوه بر داشتن انیمیشن در میان فعالیت ها بتوانیم shared views نیز در بین این فعالیت ها داشته باشیم. برای اینکار ابتدا یک پکیج top level به نام com.vogella.android.activityanimationwithsharedviews را صدا میزنیم. حال دو فعالیت مختلف که شامل imageview باشند و ویژگی android:transitionName داشته باشند را می سازیم.

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".MainActivity">



    <ImageView

        android:id="@+id/sharedimage"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:scaleType="centerCrop"

        android:src="@drawable/ic_sharedimage"

        />



</LinearLayout>

activity_second.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context="com.vogella.android.activityanimationwithsharedviews.SecondActivity">



    <ImageView

        android:id="@+id/sharedimage"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:src="@drawable/ic_sharedimage"

        android:layout_alignParentBottom="true"

        android:layout_alignParentEnd="true" />



    <TextView

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/hello_world"

        android:id="@+id/textView" />



    <Button

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="New Button"

        android:id="@+id/button"

        android:transitionName="sharedImage"

        android:layout_below="@+id/textView"

        android:layout_alignParentStart="true"

        android:layout_marginTop="54dp" />



</RelativeLayout>

 

حال کد فعالیت خود را تنظیم یا adjust میکنیم.

package com.vogella.android.activityanimationwithsharedviews;



import android.app.Activity;

import android.app.ActivityOptions;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.widget.ImageView;



public class MainActivity extends Activity {



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        final ImageView sharedImage = (ImageView) findViewById(R.id.sharedimage);

        sharedImage.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View view) {

                //This is where the magic happens.

                // makeSceneTransitionAnimation takes a context, view,

                // a name for the target view.

                ActivityOptions options =

                        ActivityOptions.

                        makeSceneTransitionAnimation(MainActivity.this, sharedImage, "sharedImage");

                Intent intent = new Intent(MainActivity.this, SecondActivity.class);

                startActivity(intent, options.toBundle());

            }

        });



    }



}

package com.vogella.android.activityanimationwithsharedviews;



import android.app.Activity;

import android.os.Bundle;



public class SecondActivity extends Activity {



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_second);

    }

}

حال اگر نرم افزار خود را اجرا کنید و روی imageview کلیک کنید که در این جا یک دکمه است، میبینید که با یک ویژگی مشترک  android:transitionName  به view انیمیت شده است.