1. 程式人生 > >android高仿今日頭條小視訊轉場切換效果

android高仿今日頭條小視訊轉場切換效果

可以先看看今日頭條效果

功能分析

點選列表上的一個item,該item會放大,最後直接全屏播放小視訊,剛開始看上去,以為是個共享元素的轉場動畫
後來想到,共享元素要在android 5.0以上支援,而今日頭條顯然不會只支援5.0版本以上

筆者想到的一種方案就是進入Activity之後,在onCreate的生命週期回撥,,計算縮放的動畫引數,思路如下

1.點選列表上的item,獲取該view的螢幕位置資訊,立即傳入進入目標比如VideoPlayAcitvity
2.在VideoPlayAcitvityonCreate生命週期方法中獲取點選的view相關位置資訊,進行動畫播放

看上去也不難,但實際有幾個問題,第一步需要設定VideoPlayAcitvity透明,並且去掉轉場動畫

功能使用

transitionController = new TransitionController.Builder()
        .with(findViewById(R.id.main_root_layer))
        //今日頭條預設引數
        .setInterpolator(PathInterpolatorCompat.create(0.32F, 0.94F, 0.6F, 1.0F))
        .duration(320)
        .build();
transitionController.transitionEnter(targetAnimBean, new TransitionCallback() {
    @Override
    public void onTransitionStop() {
        //顯示小視訊介面評論等控制元件
    }
});

來看看實際效果:

功能實現

給出部分關鍵的邏輯

/**
 * 進入和退出的動畫
 * @param enterAnimation 是否入場動畫
 * @param animatorListener 監聽動畫回撥
 */
private void transitionStart(boolean enterAnimation, Animator.AnimatorListener animatorListener) {
    //標識我們點選的View在螢幕中可見的高度
    int visibleHeight = transitionParam.bottom - transitionParam.top;

    //計算縮放的寬和高起點,需要和外部的控制元件寬高看起來一致才比較細膩
    float scaleXStart = (float) transitionParam.width / targetWidth;
    float scaleYStart = (float) transitionParam.height / targetHeight;

    animView.setPivotX(0);
    animView.setPivotY(0);

    int startTransX = transitionParam.left;
    int startTransY;
    if (transitionParam.bottom == targetHeight) {
        //滑動到螢幕底部去了,這時候以點選的控制元件頂部為位移起始點
        startTransY = transitionParam.top;
    } else if (visibleHeight < transitionParam.height) {
        //滑動到螢幕頂部去了
        startTransY = transitionParam.bottom - transitionParam.height;
    } else {
        startTransY = transitionParam.top;
    }

    if (enterAnimation) {
        //顯示動畫設定移動的起始位置,關閉動畫只指定目標位移位置
        animView.setTranslationX(startTransX);
        animView.setTranslationY(startTransY);
    }

    //設定縮放點
    animView.setScaleX(enterAnimation ? scaleXStart : 1.0F);
    animView.setScaleY(enterAnimation ? scaleYStart : 1.0F);

    viewAnimator = animView.animate();
    //頭條引數
    viewAnimator.setInterpolator(timeInterpolator);
    animView.setVisibility(View.VISIBLE);
    viewAnimator.setDuration(duration)
            .setListener(animatorListener)
            .scaleX(enterAnimation ? 1.0F : scaleXStart)
            .scaleY(enterAnimation ? 1.0F : scaleYStart)
            .translationX(enterAnimation ? 0.0F : startTransX)
            .translationY(enterAnimation ? 0.0F : startTransY)
            .start();
}

手勢滑動

手勢滑動主要也是攔截觸控事件,計算移動的距離,根據手指移動的距離,等比的縮放指定的容器
目前實現較為簡單,待後續會更新

原文地址:
https://juejin.im/post/5bc6ef9af265da0af1616dd3

專案地址