Help us understand the problem. What is going on with this article?

Viewのanimateメソッドで動きのあるアプリへ!

More than 3 years have passed since last update.

もう本当にAnmationを簡単に実装したい時は、これに限ると思ってます!

スケールを大きくする

// Scale Focusが当たった時やTapした時など
// XとYの大きさが100msかけて大きくなる
textView.animate().scaleX(2f).scaleY(2f).setDuration(1000);

ふわっと出す

// Splash向け 1200msかけて透明度が0になる 1が透明度なし 0が透明です
// 0.8fが80パーセントの透明度
textView.animate().alpha(0f).setDuration(1200);

SwipeRefreshLayoutを引っ張り更新の際にとかやると綺麗

// Viewの更新がかかった後など
listView.setAlpha(0f);
listView.animate().alpha(1f).setDuration(300);

移動

// 500msかけてxとyが100ピクセル移動する
textView.animate().x(100).y(100).setDuration(500);

回転する

// Rotation トーグルを回転させる時の動きなどに! 1000msかけて1回転する
// 180なら半回転
textView.animate().rotation(360).setDuration(1000);

Animationが始まった時や終わった時のリスナーをつける

// scaleがXとY二倍になった後
textView.animate().scaleX(2f).scaleY(2f).setDuration(1000).setListener(new Animator.AnimatorListener() {
  @Override
  public void onAnimationStart(Animator animator) {
  }

  @Override
  public void onAnimationEnd(Animator animator) {
    textView.animate().scaleX(1f).scaleY(1f).setDuration(2000);
  }

  @Override
  public void onAnimationCancel(Animator animator) {
  }

  @Override
  public void onAnimationRepeat(Animator animator) {
  }
});

実際にアプリに組み込んでみるとこんな感じ

タップすると動画プレイヤーを大きくする・小さくするをします
scaleX scaleY x y setDuration alpha を使っています
Youtubeみたい!
※ 動画の再生には、ExoPlayerを使っています
emu.gif

ソースはこちら

import android.content.pm.ActivityInfo;
import android.databinding.DataBindingUtil;
import android.graphics.SurfaceTexture;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.view.TextureView;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.webkit.WebView;

import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveVideoTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;

import java.util.Timer;
import java.util.TimerTask;

import jp.logiclogic.recycler_in_exoplayer.R;
import jp.logiclogic.recycler_in_exoplayer.databinding.ExoPlayerAnimationLayoutBinding;

/**
 * Created by ueno-yuuhei on 2016/11/12.
 */
public class ExoPlayerAnimationActivity extends FragmentActivity implements TextureView.SurfaceTextureListener {
    private ExoPlayerAnimationLayoutBinding binding; // DataBinging
    private SimpleExoPlayer simpleExoPlayer; // ExoPlayer
    private Timer playerTimer; // プレイヤー監視

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.exo_player_animation_layout);

        // 横固定
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        // ステータスバー非表示
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // ナビゲーションバー非表示
        View decor = getWindow().getDecorView();
        if (Build.VERSION.SDK_INT > 18) {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        } else if (Build.VERSION.SDK_INT > 15) {
            decor.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
        } else if (Build.VERSION.SDK_INT > 13) {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
        } else {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
        }

        // ViewTreeObserverでプレイヤー領域の大きさを確保してから右下にAnimation
        binding.textureViewArea.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (binding.textureViewArea.getWidth() > 0 && binding.textureViewArea.getWidth() > 0) {
                    binding.textureViewArea.animate()
                            .scaleX(0.3f)
                            .scaleY(0.3f)
                            .x((float) (binding.textureViewArea.getWidth() / 3))
                            .y((float) (binding.textureViewArea.getHeight() / 3))
                            .setDuration(100);
                    binding.playerTime.animate().setDuration(100).alpha(0f);
                    binding.textureViewArea.setTag(true);
                    if (Build.VERSION.SDK_INT >= 16) {
                        binding.textureViewArea.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        binding.textureViewArea.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                }
            }
        });
        binding.textureView.setSurfaceTextureListener(this);
        binding.textureViewArea.setTag(true);

        // プレイヤー領域をTapしたらAnimationで右下に動くように
        binding.textureViewArea.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                boolean toggle = (Boolean) view.getTag();
                if (toggle) {
                    binding.textureViewArea.animate().scaleX(1f).scaleY(1f).x(0).y(0).setDuration(100);
                    binding.playerTime.animate().setDuration(100).alpha(1f);
                } else {
                    binding.textureViewArea.animate().scaleX(0.3f).scaleY(0.3f)
                            .x((float) (binding.textureViewArea.getWidth() / 3))
                            .y((float) (binding.textureViewArea.getHeight() / 3))
                            .setDuration(100);
                    binding.playerTime.animate().setDuration(100).alpha(0f);
                }
                view.setTag(!toggle);
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (simpleExoPlayer != null) {
            starPlayerTimer();
            simpleExoPlayer.setPlayWhenReady(true);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopPlayerTimer();

        if (simpleExoPlayer != null) {
            simpleExoPlayer.setPlayWhenReady(false);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    // 秒数をセット
    private void starPlayerTimer() {
        stopPlayerTimer();
        playerTimer = new Timer();
        playerTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                binding.playerTime.post(new Runnable() {
                    @Override
                    public void run() {
                        int duration = (int) (simpleExoPlayer.getDuration() / 1000);
                        int current = (int) (simpleExoPlayer.getCurrentPosition() / 1000);
                        String time = getMinuteSecond(current) + " / " + getMinuteSecond(duration);
                        binding.playerTime.setText(time);
                        binding.imageTime.setText(time);
                    }
                });
            }
        }, 1000, 1000);
    }

    private String getMinuteSecond(int totalSecond) {
        int minute = totalSecond / 60;
        int second = totalSecond % 60;
        return String.format("%02d", minute) + ":" + String.format("%02d", second);
    }

    private void stopPlayerTimer() {
        if (playerTimer != null) {
            playerTimer.purge();
            playerTimer.cancel();
            playerTimer = null;
        }
    }

    // ------ ExoPlayer ------
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
        Handler mainHandler = new Handler();
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory);
        LoadControl loadControl = new DefaultLoadControl();
        simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), trackSelector, loadControl);
        simpleExoPlayer.setVideoTextureView(binding.textureView);

        DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
                com.google.android.exoplayer2.util.Util.getUserAgent(this, new WebView(getApplicationContext()).getSettings().getUserAgentString()), defaultBandwidthMeter);
        simpleExoPlayer.prepare(getHlsMediaSource("http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8", dataSourceFactory, mainHandler));
        simpleExoPlayer.setPlayWhenReady(true);
        starPlayerTimer();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

    }

    private HlsMediaSource getHlsMediaSource(String videoUrl, DataSource.Factory dataSourceFactory, Handler mainHandler) {
        return new HlsMediaSource(Uri.parse(videoUrl),
                dataSourceFactory,
                mainHandler, null);
    }
    // ------ ExoPlayer ------
}

レイアウトファイル

<layout>

    <FrameLayout 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"
        android:background="#222"
        tools:context=".activity.ExoPlayerActivity">

        <TextView
            android:id="@+id/image_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top|right"
            android:layout_margin="16dp"
            android:textColor="#FFF"
            android:textSize="16sp" />

        <FrameLayout
            android:id="@+id/texture_view_area"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextureView
                android:id="@+id/texture_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <TextView
                android:id="@+id/player_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|right"
                android:layout_margin="16dp"
                android:textColor="#FFF"
                android:textSize="16sp" />
        </FrameLayout>
    </FrameLayout>

</layout>
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした