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

  • 28
    いいね
  • 0
    コメント

もう本当に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>
この投稿は Android Advent Calendar 20161日目の記事です。