软件编程
位置:首页>> 软件编程>> Android编程>> Android TV 3D卡片无限循环效果

Android TV 3D卡片无限循环效果

作者:小纸箱  发布时间:2022-03-26 04:06:48 

标签:Android,TV,无限循环

TV 3D卡片无限循环效果,供大家参考,具体内容如下

##前言

1、需求:实现3个卡片实现无限循环效果:1-2-3-1-2-3-1…,而且要实现3D效果:中间突出,两侧呈角度显示
2、Viewpager实现方式

(1) LoopViewpager,有兴趣的同学可以去github上看一下。
(2) 通过定义一个item的个数Integer,MAX,然后设置初始位置为:Integer,MAX/2。

以上方式如果简单的加载图片这种方式还可取,由于需求3个界面内部控件比较多,在加上需要实现自定义的的3D效果,使用ViewPager实现难为了小编,于是舍弃只能自己码代码了,欲哭无泪!!!

##思路

自定义View + 属性动画ObjectAnimator
按键事件特殊处理。

##实现方式

1、ObjectAnimator属性动画的知识准备。
2、父不居中自定义ScheduleView,View2, View3


<com.base.module.gvclauncher2.ui.ScheduleView
       android:id="@+id/schedule_view"
       android:layout_width="@dimen/main_card_width"
       android:layout_height="@dimen/main_card_height"
       android:layout_gravity="center_horizontal"
       android:layout_marginTop="@dimen/main_card_margin_top"
       android:focusable="true"
       android:nextFocusLeft="@+id/contacts_view"
       android:nextFocusRight="@+id/call_view">
   </com.base.module.gvclauncher2.ui.ScheduleView>

其中android:layout_gravity=“center_horizontal”,使卡片在界面的正中间,其余两张的卡片也是如此,达到3个View的起始位置一直,这样方便之后的动画旋转。

2.添加自定义ScheduleView


public class ScheduleView extends BasePhoneView {

private static final String TAG = "CallFragment";
   private static final boolean DEBUG = true;

private Context mContext;
   private View mRootView;
   private FrameLayout mMainView;
   private ScheduleContract.View mView;
   private ScheduleContract.Presenter mPresenter;

public ScheduleView(Context context) {
       super(context);
       this.mContext = context;
       initView();
   }

public ScheduleView(Context context, AttributeSet attrs) {
       super(context, attrs);
       this.mContext = context;
       initView();
   }

public ScheduleView(Context context, AttributeSet attrs, int defStyleAttr) {
       super(context, attrs, defStyleAttr);
       this.mContext = context;
       initView();
   }

private void initView() {
       findView();
       initData();
   }

private void findView() {
       mRootView = LayoutInflater.from(mContext).inflate(R.layout.fragment_schedule, this);
       mMainView = (FrameLayout) mRootView.findViewById(R.id.schedule_contains);
       mMainView.setVisibility(View.VISIBLE);
   }

private void initData() {
       mMainView.removeAllViews();
       mView = ScheduleContractFactory.createScheduleView(mContext);
       mMainView.addView((View) mView);
       mPresenter = ScheduleContractFactory.createSchedulePresenter(mContext, mView);
       mPresenter.onCreate();
       //这里只是使用mvp的形式添加view.
   }

@Override
   public void clearAllFocus() {
   //清除所有的焦点
       if (mView != null) {
           mView.clearAllFocus();
       }
   }

@Override
   public void requestFirstFocus() {
   //第一个控件强行指定焦点
       if (mView != null) {
           mView.requestFirstFocus();
       }
   }

@Override
   public void updateListData() {
   //更新列表显示
       if (mPresenter != null) {
           mPresenter.reloadConferenceList();
       }
   }

}

其中fragment_schedule.xml中只有一个简单的FrameLayout. View2 和View3类似。

3. 动画Util

(1) 设置3个卡片的初始位置


public final static float RUN_Y = 22.0f;
public final static float RUN_LARGE_Y = 24.0f;
public final static float RUN_Y_NEGATIVE = -22.0f;
public final static float RUN_LARGE_Y_NEGATIVE = -24.0f;
public final static float RUN_X = 1235.0f;
public final static float RUN_X_NEGATIVE = -1235.0f;
public final static float RUN_LARGE_X = 1366.0f;
public final static float RUN_LARGE_X_NEGATIVE = -1366.0f;

public void initLeftAnimator(View leftView) {
       leftView.setTranslationX(RUN_X_NEGATIVE);//离屏幕中心偏移距离
       leftView.setRotationY(RUN_Y);//旋转角度
       leftView.setAlpha(LEFT_RIGHT_ALPHA);//设置透明度
   }

public void initRightAnimator(View rightView) {
       rightView.setTranslationX(RUN_X);//离屏幕中心偏移距离
       rightView.setRotationY(RUN_Y_NEGATIVE);//旋转角度
       rightView.setAlpha(LEFT_RIGHT_ALPHA);//设置透明度
   }

public void initMidAnimator(View midView) {
       //由于初始位置在xml中设定是在正中间,这里就不重新设置偏移量
       midView.setAlpha(MIDDLE_ALPHA);
   }

public void midToLeftAnimator(final View runView, boolean anim) {
       ObjectAnimator animatorX = ObjectAnimator.ofFloat(runView, "translationX", 0, RUN_X_NEGATIVE); //中间的起始位置未0
       ObjectAnimator animatorZ = ObjectAnimator.ofFloat(runView, "rotationY", 0, RUN_Y);
       ObjectAnimator animator3 = ObjectAnimator.ofFloat(runView, "alpha", MIDDLE_ALPHA, LEFT_RIGHT_ALPHA);
       mMidToLeftAnimator = new AnimatorSet();
       mMidToLeftAnimator.play(animatorX).with(animatorZ).with(animator3);
       //anim设置是否需要动画执行时间
       if (anim) {
           mMidToLeftAnimator.setDuration(DURATION);
       } else {
           mMidToLeftAnimator.setDuration(0);
       }
       mMidToLeftAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
               mIsScrolling = true;
           }

@Override
           public void onAnimationEnd(Animator animation) {
               //mIsScrolling来判断动画是否完成,来控制下一次动画是否需要执行
               mIsScrolling = false;
           }

@Override
           public void onAnimationCancel(Animator animation) {

}

@Override
           public void onAnimationRepeat(Animator animation) {

}
       });
       mMidToLeftAnimator.start();
   }

public void midToRightAnimator(final View runView, boolean anim) {
       ObjectAnimator animatorX = ObjectAnimator.ofFloat(runView, "translationX", 0, RUN_X);
       ObjectAnimator animatorZ = ObjectAnimator.ofFloat(runView, "rotationY", 0, RUN_Y_NEGATIVE);
       ObjectAnimator animator3 = ObjectAnimator.ofFloat(runView, "alpha", MIDDLE_ALPHA, LEFT_RIGHT_ALPHA);
       mMidToRightAnimator = new AnimatorSet();
       mMidToRightAnimator.play(animatorX).with(animatorZ).with(animator3);
       if (anim) {
           mMidToRightAnimator.setDuration(DURATION);
       } else {
           mMidToRightAnimator.setDuration(0);
       }
       mMidToRightAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
               mIsScrolling = true;
           }

@Override
           public void onAnimationEnd(Animator animation) {
               mIsScrolling = false;
           }

@Override
           public void onAnimationCancel(Animator animation) {

}

@Override
           public void onAnimationRepeat(Animator animation) {

}
       });
       mMidToRightAnimator.start();
   }

public void rightToMidAnimator(final View runView, boolean anim) {
       ObjectAnimator animatorX = ObjectAnimator.ofFloat(runView, "translationX", RUN_X, 0);
       ObjectAnimator animatorZ = ObjectAnimator.ofFloat(runView, "rotationY", RUN_Y_NEGATIVE, 0);
       ObjectAnimator animator3 = ObjectAnimator.ofFloat(runView, "alpha", LEFT_RIGHT_ALPHA, MIDDLE_ALPHA);
       mRightToMidAnimator = new AnimatorSet();
       mRightToMidAnimator.play(animatorX).with(animatorZ).with(animator3);
       if (anim) {
           mRightToMidAnimator.setDuration(DURATION);
       } else {
           mRightToMidAnimator.setDuration(0);
       }
       mRightToMidAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
               mIsScrolling = true;
           }

@Override
           public void onAnimationEnd(Animator animation) {
               mIsScrolling = false;
           }

@Override
           public void onAnimationCancel(Animator animation) {

}

@Override
           public void onAnimationRepeat(Animator animation) {

}
       });
       mRightToMidAnimator.start();
   }

public void leftToMidAnimator(final View runView, boolean anim) {
       ObjectAnimator animatorX = ObjectAnimator.ofFloat(runView, "translationX", RUN_X_NEGATIVE, 0);
       ObjectAnimator animatorZ = ObjectAnimator.ofFloat(runView, "rotationY", RUN_Y, 0);
       ObjectAnimator animator3 = ObjectAnimator.ofFloat(runView, "alpha", LEFT_RIGHT_ALPHA, MIDDLE_ALPHA);
       mLeftToMidAnimator = new AnimatorSet();
       mLeftToMidAnimator.play(animatorX).with(animatorZ).with(animator3);
       if (anim) {
           mLeftToMidAnimator.setDuration(DURATION);
       } else {
           mLeftToMidAnimator.setDuration(0);
       }
       mLeftToMidAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
               mIsScrolling = true;
           }

@Override
           public void onAnimationEnd(Animator animation) {
               mIsScrolling = false;
           }

@Override
           public void onAnimationCancel(Animator animation) {

}

@Override
           public void onAnimationRepeat(Animator animation) {

}
       });
       mLeftToMidAnimator.start();
   }

public void rightToLeftAnimator(View runView, boolean anim) {
       ObjectAnimator animator1 = ObjectAnimator.ofFloat(runView, "translationX", RUN_X, RUN_LARGE_X);
       ObjectAnimator animator2 = ObjectAnimator.ofFloat(runView, "rotationY", RUN_Y_NEGATIVE, RUN_LARGE_Y_NEGATIVE);
       ObjectAnimator animator3 = ObjectAnimator.ofFloat(runView, "alpha", LEFT_RIGHT_ALPHA, 0.0f);

//继续往右偏移
       ObjectAnimator animator4 = ObjectAnimator.ofFloat(runView, "translationX", RUN_LARGE_X, RUN_X_NEGATIVE);
       ObjectAnimator animator5 = ObjectAnimator.ofFloat(runView, "rotationY", RUN_LARGE_Y_NEGATIVE, RUN_LARGE_Y);
       //中途隐藏不显示
       ObjectAnimator animator6 = ObjectAnimator.ofFloat(runView, "alpha", 0.0f, 0.0f);

ObjectAnimator animator7 = ObjectAnimator.ofFloat(runView, "translationX", RUN_X_NEGATIVE, RUN_X_NEGATIVE);
       //往左偏移显示在左边位置
       ObjectAnimator animator8 = ObjectAnimator.ofFloat(runView, "rotationY", RUN_LARGE_Y, RUN_Y);
       ObjectAnimator animator9 = ObjectAnimator.ofFloat(runView, "alpha", LEFT_RIGHT_ALPHA, LEFT_RIGHT_ALPHA);

//给分段动画设置时间
       if (anim) {
           animator1.setDuration(170);
           animator4.setDuration(60);
           animator7.setDuration(170);
       } else {
           animator1.setDuration(0);
           animator4.setDuration(0);
           animator7.setDuration(0);
       }
//with:同时执行,after(动画1):在动画1之后执行,befor(动画1):在动画1之前执行。
//请注意以下的after(animator1)。表示动画4.5.6在动画1,2,3执行完毕之后同时执行
       mRightToLeftAnimator = new AnimatorSet();
       mRightToLeftAnimator.play(animator1).with(animator2).with(animator3);
       mRightToLeftAnimator.play(animator4).with(animator5).with(animator6).after(animator1);
       mRightToLeftAnimator.play(animator7).with(animator8).with(animator9).after(animator4);
       mRightToLeftAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
               mIsScrolling = true;
           }

@Override
           public void onAnimationEnd(Animator animation) {
               //mIsScrolling = false;
           }

@Override
           public void onAnimationCancel(Animator animation) {

}

@Override
           public void onAnimationRepeat(Animator animation) {

}
       });
       mRightToLeftAnimator.start();
   }

public void leftToRightAnimator(View runView, boolean anim) {
       ObjectAnimator animator1 = ObjectAnimator.ofFloat(runView, "translationX", RUN_X_NEGATIVE, RUN_LARGE_X_NEGATIVE);
       ObjectAnimator animator2 = ObjectAnimator.ofFloat(runView, "rotationY", RUN_Y, RUN_LARGE_Y);
       ObjectAnimator animator3 = ObjectAnimator.ofFloat(runView, "alpha", LEFT_RIGHT_ALPHA, 0.0f);

ObjectAnimator animator4 = ObjectAnimator.ofFloat(runView, "translationX", RUN_LARGE_X_NEGATIVE, RUN_X);
       ObjectAnimator animator5 = ObjectAnimator.ofFloat(runView, "rotationY", RUN_LARGE_Y, RUN_LARGE_Y_NEGATIVE);
       ObjectAnimator animator6 = ObjectAnimator.ofFloat(runView, "alpha", 0.0f, 0.0f);

ObjectAnimator animator7 = ObjectAnimator.ofFloat(runView, "translationX", RUN_X, RUN_X);
       ObjectAnimator animator8 = ObjectAnimator.ofFloat(runView, "rotationY", RUN_LARGE_Y_NEGATIVE, RUN_Y_NEGATIVE);
       ObjectAnimator animator9 = ObjectAnimator.ofFloat(runView, "alpha", LEFT_RIGHT_ALPHA, LEFT_RIGHT_ALPHA);

if (anim) {
           animator1.setDuration(170);
           animator4.setDuration(60);
           animator7.setDuration(170);
       } else {
           animator1.setDuration(0);
           animator4.setDuration(0);
           animator7.setDuration(0);
       }

mLeftToRightAnimator = new AnimatorSet();
       mLeftToRightAnimator.play(animator1).with(animator2).with(animator3);
       mLeftToRightAnimator.play(animator4).with(animator5).with(animator6).after(animator1);
       mLeftToRightAnimator.play(animator7).with(animator8).with(animator9).after(animator4);
       mLeftToRightAnimator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
               mIsScrolling = true;
           }

@Override
           public void onAnimationEnd(Animator animation) {
               //mIsScrolling = false;
           }

@Override
           public void onAnimationCancel(Animator animation) {

}

@Override
           public void onAnimationRepeat(Animator animation) {

}
       });
       mLeftToRightAnimator.start();
}

来源:https://blog.csdn.net/nihenmeila/article/details/121037187

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com