android高仿今日頭條小視訊轉場切換效果
阿新 • • 發佈:2018-11-01
可以先看看今日頭條效果
功能分析
點選列表上的一個item
,該item
會放大,最後直接全屏播放小視訊,剛開始看上去,以為是個共享元素的轉場動畫
,
後來想到,共享元素
要在android 5.0以上支援,而今日頭條顯然不會只支援5.0版本以上
筆者想到的一種方案就是進入Activity之後,在onCreate
的生命週期回撥,,計算縮放的動畫引數,思路如下
1.點選列表上的
item
,獲取該view
的螢幕位置資訊,立即傳入進入目標比如VideoPlayAcitvity
中
2.在VideoPlayAcitvity
的onCreate
生命週期方法中獲取點選的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(); }
手勢滑動
手勢滑動主要也是攔截觸控事件,計算移動的距離,根據手指移動的距離,等比的縮放指定的容器
目前實現較為簡單,待後續會更新