当前位置: 首页 > 科技观察

炫酷的安卓交互动画和视觉效果:高仿音悦台播放页面

时间:2023-03-22 00:36:30 科技观察

新版音悦台APP播放页面交互非常有趣,可以将播放器往下拉,页面透明渐变,然后就可以了到最下面左右拖动关闭播放器,然后点击视频列表,会弹出一个页面,很酷,所以自己实现了这个交互很酷的播放器页面。1、废话不多说,直接演示效果1.1。点击某个视频,然后用手指上下拖动,播放器会做大小和比例的渐变,视频相关信息会做1.2的透明度渐变。只有当播放器在底部时,才可以左右拖动,此时播放器会做一个透明度渐变,拖动一定范围关闭播放器;那么就只能在原位置1.3的一小段距离内往上拖。点击视频列表时,如果最后一个视频在左侧或右侧拖动关闭,会有弹出播放页面的效果;如果是回车键和回车箭头,则没有效果。子视图的处理方式不同。ViewDragHelper非常适合处理触摸事件,然后你需要实现容器onMeasure和onLayout。由于使用了ViewDragHelper,所以在解析代码的时候会遇到一些坑。播放页面是使用新的Activity还是只使用当前Activity的View是个问题。由于播放器收缩到底部时用户可以滑动视频列表,所以我个人认为在当前Activity中放置一个自定义容器就可以了。因此,为了效率,可以使用ViewStub进行懒加载处理。为了演示方便,我就直接用View的形式。3.代码分析3.1.必需的变量3.2。初始化对ViewDragHelper进行初始化,然后post得到两个子View。这里必须只有两个子元素。3.3.ViewDragHelper的回调中有很多事情要做。需要同时设置mFlexView和mFollowView对应的变化效果。mFlexView在释放的时候需要处理关闭或者关闭效果。3.4.下一步是处理测量和定位。measureChildWithMargins的heightUse放在一起;onLayout时position缓存不为空时,直接定位,因为ViewDragHelper正在处理touch事件子元素,做一些翻译。如果某个元素更新了UI,会引起重新布局,比如我的播放器更新的时候TextView会这样,所以在FlexCallback的onViewPositionChanged方法中记录位置,重新布局时恢复位置.宽高,ViewDragHelper还是会挡住mFlexView真正的宽高区域,所以这里要判断手指是否落在mFlexView的可视范围内,然后调整ViewDragHelper3.6的shouldInterceptTouchEvent方法。在computeScroll中,如果mIsClosing为true,即整个关闭翻译完成,通知回调事件3.7。容器已实施。接下来我们继承YytLayout来实现播放器页面的组合控件,然后封装一些常用的方法。这里我们使用大名鼎鼎的Ijkplayer实现的播放器,IjkVideoView的touch事件是自己屏蔽处理的;顺带一提,为了实现播放器Controller跟随拖动缩放的效果,放弃了常用的PopupWindow实现的思路。IjkController是直接加在IjkVideoView上,还是弹窗实现跟播放器太麻烦了/***CreatedbyOubowuon2016/12/2717:32.

*仿音悦台播放页面的具体实现,组合控件的形式*/publicclassYytPlayerextendsYytLayout{privateIjkControllermIjkController;privateIjkVideoViewmIjkVideoView;privateImageViewmIvAvatar;privateTextViewmTvName;privateTextViewmTvTime;privateTextViewmTvTitle;privateTextViewmTvDesc;privateRecyclerViewmYytRecyclerView;privateVideoListAdaptermVideoListAdapter;publicYytPlayer(Contextcontext,AttributeSetattrs){super(context,attrs);init(context,attrs);}privatevoidinit(Contextcontext,AttributeSetattrs){//继承YytLayout,通过merge标签降级实现合控LayoutInflater.from(context).inflate(R.layout.yyt_player,this,true);setOnLayoutStateListener(newOnLayoutStateListener(){@OverridepublicvoidonClose(){setVisibility(View.INVISIBLE);mIjkVideoView.release(true);}});mIjkVideoView=(IjkVideoView)findViewById(R.id.ijk_player_view);finalintscaledTouchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop();mIjkVideoView.setOnTouchListener(newOnTouchListener(){floatmDownX=0;floatmDownY=0;booleanmClickCancel;@OverridepublicbooleanonTouch(Viewv,MotionEventevent){floatx=event.getX();floaty=event.getY();switch(event.getAction()){caseMotionEvent.ACTION_DOWN:mDownX=x;mDownY=y;break;caseMotionEvent.ACTION_MOVE:if(Math.abs(mDownX-x)>scaledTouchSlop||Math.abs(mDownY-y)>scaledTouchSlop){mClickCancel=true;}break;caseMotionEvent.ACTION_UP:if(!mClickCancel&&Math.abs(mDownX-x)<=scaledTouchSlop&&Math.abs(mDownY-y)<=scaledTouchSlop){//点击事件偶尔失效,只好在这里自己解决了if(isHorizo??ntalDragEnable()){expand();}else{mIjkVideoView.toggleMediaControlsVisibility();}}mClickCancel=false;break;caseMotionEvent.ACTION_CANCEL:mClickCancel=false;break;}returntrue;}});mIvAvatar=(ImageView)findViewById(R.id.iv_avatar);mTvName=(TextView)findViewById(R.id.tv_name);mTvTime=(TextView)findViewById(R.id.tv_time);mTvTitle=(TextView)findViewById(R.id.tv_title);mTvDesc=(TextView)findViewById(R.id.tv_desc);mVideoListAdapter=newVideoListAdapter();mVideoListAdapter.setOnItemClickCallback(newOnItemClickCallback(){@OverridepublicvoidonClick(Viewview,intposition){intpos=(Integer)view.getTag();VideoSummarysummary=mVideoListAdapter.getData().get(pos);playVideo(mVideoListAdapter.getData(),summary);}});mYytRecyclerView=(RecyclerView)findViewById(R.id.yyt_recycler_view);GridLayoutManagergridLayoutManager=newGridLayoutManager(context,2,LinearLayoutManager.VERTICAL,false);mYytRecyclerView.setLayoutManager(gridLayoutManager);mYytRecyclerView.setNestedScrollingEnabled(false);mYytRecyclerView。addItemDecoration(newVideoListItemDecoration(context));mYytRecyclerView.setAdapter(mVideoListAdapter);}//播放视频privatevoidplayVideo(Stringpath,Stringname){try{if(mIjkController==null){IjkMediaPlayer.loadLibrariesOnce(null);IjkMediaPlayer.native_playerBeginer("libijkBeginer(".so");mIjkController=newIjkController(mIjkVideoView,名称);mIjkController.setOnViewStateListener(newIjkController.OnViewStateListener(){@OverridepublicvoidonBackPress(){停止();}});mIjkVideoView.setMediaController(mIjkController);mIjkVideoView.setOnPreparedListener(newIMediaPlayer.OnPreparedListener(){@OverridepublicvoidonPrepared(IMediaPlayermp){mIjkVideoView.start();}});mIjkVideoView.setOnPreparedListener(newIMediaPlayer.OnErrorListener(){@OverridepublicbooleanonError(IMediaPlayermp,intwhat,intextra){Toast.makeText(getContext(),"视频播放错误╮(╯Д╰)╭",Toast.LENGTH_SHORT).show();returntrue;}});}else{//重置视频名称mIjkController.setVideoName(name);}//设置TextureView播放器正常缩放mIjkVideoView.setRender(IjkVideoView.RENDER_TEXTURE_VIEW);//因为每次setRender都会移除view然后Add,为了缩放效果,控制器添加到IjkVideoView,所以这里必须重新添加到IjkVideoView的顶部mIjkController.updateControlView();//显示加载栏mIjkController.showProgress();//播放视频mIjkVideoView.setVideoURI(Uri.parse(path));}catch(UnsatisfiedLinkError){e.printStackTrace();Toast.makeText(getContext(),"你的CPU是"+Build.CPU_ABI+",当前播放器使用的编译版本"+BuildConfig.FLAVOR+“不匹配!”,Toast.LENGTH_LONG).show();}}/***显示布局并播放视频**@paramdata视频列表,用于播放页面下方的列表布局*@paramsummary播放视频信息*/publicvoidplayVideo(Listdata,VideoSummarysummary){//获取数据并设置为播放布局的相关信息Glide.with(getContext()).load(summary.mTopicImg).transform(newGlideCircleTransform(getContext())).进入(mIvAvatar);mTvName.setText(summary.mTopicName);mTvTime.setText(summary.mPtime);mTvTitle.setText(Html.fromHtml(summary.mTitle));if(summary.mDescription.isEmpty()){mTvDesc。setText(summary.mTopicDesc);}else{mTvDesc.setText(Html.fromHtml(summary.mDescription));}//设置YytLayout可见并展开setVisibility(View.VISIBLE);expand();mVideoListAdapter.setData(data);mVideoListAdapter。setItemWidth(mYytRecyclerView.getWidth()/2);mVideoListAdapter.notifyDataSetChanged();//播放视频playVideo(summary.mMp4HdUrl==null?summary.mMp4Url:summary.mMp4HdUrl,summary.mTitle);}//开始播放publicvoidstart(){if(mIjkVideoView!=null&&!mIjkVideoView.isPlaying()){mIjkVideoView.start();}}//暂停播放publicvoidpause(){if(mIjkVideoView!=null&&mIjkVideoView.isPlaying()){mIjkVideoView.pause();}}//停止播放publicvoidstop(){setVisibility(View.INVISIBLE);if(mIjkVideoView!=null){mIjkVideoView.release(true);}}publicbooleanisShowing(){returngetVisibility()==VISIBLE;}}4.综上所述,不难说不难,就是各种细节需要想象力。可能需要实现UC浏览器播放器的效果,也很有意思