[文章] 仿网易云开屏动画 1.效果图这是原版效果:下面是仿制的效果2.实现分析开屏动画里面有一个向上滑动的箭头,引导用户去广告页,主要是一个平移动画和透明度变化,基本元素是一个箭头,不断从底下弹出,到达某个位置后消失。所以我们要实现的是一个自定义的ViewGroup,这里我们选择RelativeLayout代码实现packagecom.ttyh.customviewimportandroid.animation.Animatorimportandroid.animation.AnimatorListenerAdapterimportandroid.animation.AnimatorSetimportandroid.animation.ObjectAnimatorimportandroid.annotation.SuppressLintimportandroid.content.Contextimportandroid.graphics.drawable.Drawableimportandroid.os.Handlerimportandroid.os.Looperimportandroid.util.AttributeSetimportandroid.view.GestureDetectorimportandroid.view.MotionEventimportandroid.view.Viewimportandroid.view.ViewGroupimportandroid.view.animation.LinearInterpolatorimportandroid.widget.ImageViewimportandroid.widget.RelativeLayoutimportandroidx.core.content.res.ResourcesCompatimportcom.ttyh.notificationtest.Rimportjava.util.*/***@authorCreatebyQinBiao*@description:*@create_date:2022/9/2-11:20*@Modified_time:2022/9/2-11:20*/classArrowLayout:RelativeLayout,GestureDetector.OnGestureListener{privatevarparams:ViewGroup.LayoutParams?=nullprivatelateinitvargestureDetector:GestureDetector//处理滑动事件的接口privatevarflingListener:(()->Unit)?=nullprivatevarisInItFlag=falseprivatevaricon=ResourcesCompat.getDrawable(resources,R.drawable.ic_arrow_up,null)//默认箭头图片constructor(context:Context,attrs:AttributeSet):super(context,attrs){background=ResourcesCompat.getDrawable(resources,R.drawable.bg_background,null)//默认背景图片initListener()}/***初始化手势监听器**/privatefuninitListener(){gestureDetector=GestureDetector(context,this)}privatefuninitView(){valwidth=(icon?.intrinsicWidth?.div(4))?:0valheight=icon?.intrinsicHeight?.div(4)?:0//将箭头imageView添加到布局的底部中央位置params=LayoutParams(width,height).apply{addRule(CENTER_HORIZONTAL,TRUE)addRule(ALIGN_PARENT_BOTTOM,TRUE)}isInItFlag=true}//设置背景图片funsetBackGround(mBackground:Drawable){background=mBackground}//设置箭头funsetIcon(drawable:Drawable){icon=drawable}privatefunaddArrowView(){//如果没有初始化过箭头图片的位置,初始化if(!isInItFlag){initView()}valiv=ImageView(context).apply{layoutParams=paramssetImageDrawable(icon)}//添加箭头图片的Imageview到布局中addView(iv)//开启动画valalphaOne=ObjectAnimator.ofFloat(iv,"alpha",0.3f,1f,0.7f)alphaOne.interpolator=LinearInterpolator()valtranslateOne=ObjectAnimator.ofFloat(iv,"translationY",0f,-200f)translateOne.interpolator=LinearInterpolator()valanimatorSet=AnimatorSet().apply{play(translateOne).with(alphaOne)duration=1500}animatorSet.start()//动画监听animatorSet.addListener(object:AnimatorListenerAdapter(){overridefunonAnimationEnd(animation:Animator?){super.onAnimationEnd(animation)iv.visibility=View.GONEremoveView(iv)//移除箭头}overridefunonAnimationRepeat(animation:Animator?){super.onAnimationRepeat(animation)}overridefunonAnimationStart(animation:Animator?){super.onAnimationStart(animation)}})}/*@params:duration多长时间间隔发射一个箭头*/funsetArrowDuration(duration:Long){vallooper=Looper.getMainLooper()valhandler=Handler(looper)valtimer=Timer()valtask=object:TimerTask(){overridefunrun(){handler.postDelayed({addArrowView()},0)}}timer.schedule(task,0,duration)}overridefunonInterceptTouchEvent(ev:MotionEvent?):Boolean{returntrue}overridefunonDown(e:MotionEvent?):Boolean{returntrue}overridefunonShowPress(e:MotionEvent?){}overridefunonSingleTapUp(e:MotionEvent?):Boolean{returnfalse}overridefunonScroll(e1:MotionEvent?,e2:MotionEvent?,distanceX:Float,distanceY:Float):Boolean{returnfalse}overridefunonLongPress(e:MotionEvent?){}overridefunonFling(e1:MotionEvent?,e2:MotionEvent?,velocityX:Float,velocityY:Float):Boolean{flingListener?.invoke()returnfalse}@SuppressLint("ClickableViewAccessibility")overridefunonTouchEvent(event:MotionEvent?):Boolean{returngestureDetector.onTouchEvent(event)}}4.使用<?xmlversion="1.0"encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.ttyh.animator.AdActivity"><com.ttyh.customview.ArrowLayoutandroid:id="@+id/ad"android:layout_width="match_parent"android:layout_height="match_parent"/></androidx.constraintlayout.widget.ConstraintLayout>在Activity或者Fragment中开启动画classAdActivity:AppCompatActivity(){privatelateinitvarbinding:ActivityAdBindingoverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)binding=ActivityAdBinding.inflate(layoutInflater)//设置弹射箭头的时间间隔,并且开始动画binding.ad.setArrowDuration(500)setContentView(binding.root)}}实现拦截手势的接口binding.ad.flingListener={//拦截滑动手势后,要做的事,比如说启动淘宝、京东}5期间遇到的问题自定义view时,无法拦截到手势的滑动手势,只能拦截到短按、长按等手势,解决方法:在实现手势拦截方法时,重写onDown(e:MotionEvent?):Boolean方法,表示消费掉该手势,然后就能拦截到滑动手势了