Android视频播放器实现小窗口和全屏状态切换

Android视频播放器实现小窗口和全屏状态切换

实在是不好意思,楼下评论的兄弟久等了,这文章一直没写第一是没时间,第二是自己准备也不充足,最近才看了好几个Android视频播放器的开源项目,才对视频播放器的大小切换有点了解,就我目前的了解,视频播放器的大小屏切换基本有三个方案可选,下面我分别简单地讲一下,至于具体的实现我会给出github的链接,大家直接去看源代码。

一、让播放器悬浮在Activity中

所谓让视频播放器悬浮在activity中,就是播放器在内存里面,需要显示的时候就设置一个锚点view,当时小窗口的时候播放器就跟随这个锚点view滚动和重绘,我看到过这样的实现,可以说想法很好,看起来也很完美,下面看一下其大概的源代码:

    /**
     * 设置锚
     *
     * @param anchor    锚点view
     * @param activity  所在的activity
     */
    public void setAnchorView(View anchor, Activity activity) {
        if (anchor == null || activity == null) {
            return;
        }

        if (this.anchorView != null) {
            ViewTreeObserver observerTmp = anchorView.getViewTreeObserver();
            try {
                observerTmp.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
                observerTmp.removeOnScrollChangedListener(mOnScrollChangedListener);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        this.anchorView = anchor;
        this.activity = activity;

        final ViewTreeObserver observer = anchorView.getViewTreeObserver();
        try {
            /**注册滚动和绘制监听器**/
            observer.addOnScrollChangedListener(mOnScrollChangedListener);
            observer.addOnGlobalLayoutListener(mOnGlobalLayoutListener);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Activity act = this.activity;
        if (act != null) {
            FrameLayout content = (FrameLayout) act.findViewById(android.R.id.content);
            if (content.getTag() != null) {
                return;
            }
            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(anchorView.getMeasuredWidth(), anchorView.getMeasuredHeight());
            int[] location = new int[2];
            anchorView.getLocationInWindow(location);
            lp.leftMargin = location[0];
            lp.topMargin = location[1];
            /**在activity中添加播放器**/
            content.addView(this, content.getChildCount(), lp);
            content.setTag(true);
        }

    }

可以看到,这个方式很巧妙,但是,但是,这种方法也有致命的缺点,我们注册了滚动和绘制监听来控制我们的播放器,一旦我们把播放器放在scrollView或者recyclerView中,那就要教你做人了,播放器的晃动非常厉害,由于我们是注册的监听器来确定播放器的位置,这样我们在滚动控件中,视频播放器的位置跟滚动的位置总是慢一拍,导致在滚动控件在播放器有严重的果冻效果,体验很不好,如果可以优化器滚动效果那么这个方法还是很好的。我看到的是使用了surfaceview来播放视频,不知道使用textureview会不会减轻这个果冻效果,不放在滚动控件中只是放大和缩小这种方法还是不错的。

这第一种方法就目前来看不是很推荐!

二、大小屏切换创建两个播放器设置同一个TextureView

开源项目:JieCaoVideoPlayer

JieCaoVideoPlayer
这种方法小屏切换到大屏是创建了两个播放器,或者说是创建了两个TextureView的容器,从小到大的时候在Activity中创建了一个全屏的播放器容器,并把当前的视频渲染器(TextureView)和监听器都给赋值过去了,由于使用了TextureView,所以在滚动控件中使用也不会用果冻效果,可以说是正真意义的完美的播放器全屏方案。大小切换由于TextureView的容器换了,所以中间会有很短时间的黑屏,但是可以忽略:

    /**
     * 小屏窗口切换为全屏播放
     */
    public void startWindowFullscreen() {
        Log.i(TAG, "startWindowFullscreen " + " [" + this.hashCode() + "] ");

        hideSupportActionBar(getContext());
        /**activity的content layout**/
        ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext())).findViewById(Window.ID_ANDROID_CONTENT);
        /**通过id找到播放器自己本身**/
        View old = vp.findViewById(FULLSCREEN_ID);
        /**如果在设置全屏之前activity的content layout中本来就存在播放器就先移除**/
        if (old != null) {
            vp.removeView(old);
        }
        if (textureViewContainer.getChildCount() > 0) {
            textureViewContainer.removeAllViews();
        }
        try {
            Constructor<JCVideoPlayer> constructor = (Constructor<JCVideoPlayer>) JCVideoPlayer.this.getClass().getConstructor(Context.class);
            JCVideoPlayer jcVideoPlayer = constructor.newInstance(getContext());
            jcVideoPlayer.setId(FULLSCREEN_ID);
            /**获取屏幕的宽高**/
            WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
            int w = wm.getDefaultDisplay().getWidth();
            int h = wm.getDefaultDisplay().getHeight();
            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(h, w);
            lp.setMargins((w - h) / 2, -(w - h) / 2, 0, 0);
            vp.addView(jcVideoPlayer, lp);
            jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects);
            jcVideoPlayer.setUiWitStateAndScreen(currentState);
            /**小窗口和全屏的切换是创建了两个播放器,之间的衔接全靠这个方法**/
            jcVideoPlayer.addTextureView();
            jcVideoPlayer.setRotation(90);

            final Animation ra = AnimationUtils.loadAnimation(getContext(), R.anim.start_fullscreen);
            jcVideoPlayer.setAnimation(ra);
            /**监听器的替换**/
            JCVideoPlayerManager.setLastListener(this);
            JCVideoPlayerManager.setListener(jcVideoPlayer);


        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这第二种方法比较推荐,但是你要很懂播放器,对源代码很熟悉,由于是直接对ijkMediaplayer进行的封装,中间还会对视频的播放监听器进行切换,所以还是有点复杂的,这方法可以做到真正的全屏,无视是否有ActionBar什么的,直接全屏。如果你觉得自己能力不错,那就赶紧把这个方法get去吧。

三、在Activity中留一个全屏的ViewGroup来放置播放器

开源项目:SuperPlayer

SuperPlayer

这方法需要在Activity中预留一个放置播放器的宽高都match_parent的ViewGroup,大小切换就是把播放器添加到本来的小容器和添加到全屏的ViewGroup中来回切换,对于播放器的监听器也不用过多干预,是比较通俗易懂简单的方法:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (player != null) {
            /**
             * 在activity中监听到横竖屏变化时调用播放器的监听方法来实现播放器大小切换
             */
            player.onConfigurationChanged(newConfig);
            if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                fullScreen.setVisibility(View.GONE);
                fullScreen.removeAllViews();
                superRecyclerView.setVisibility(View.VISIBLE);
                if (postion <= mLayoutManager.findLastVisibleItemPosition()
                        && postion >= mLayoutManager.findFirstVisibleItemPosition()) {
                    View view = superRecyclerView.findViewHolderForAdapterPosition(postion).itemView;
                    FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.adapter_super_video);
                    frameLayout.removeAllViews();
                    ViewGroup last = (ViewGroup) player.getParent();//找到videoitemview的父类,然后remove
                    if (last != null) {
                        last.removeAllViews();
                    }
                    frameLayout.addView(player);
                }
                int mShowFlags =
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
                fullScreen.setSystemUiVisibility(mShowFlags);
            } else {
                ViewGroup viewGroup = (ViewGroup) player.getParent();
                if (viewGroup == null)
                    return;
                viewGroup.removeAllViews();
                fullScreen.addView(player);
                fullScreen.setVisibility(View.VISIBLE);
                int mHideFlags =
                        View.SYSTEM_UI_FLAG_LOW_PROFILE
                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_IMMERSIVE
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        ;
                fullScreen.setSystemUiVisibility(mHideFlags);
            }
        } else {
            fullScreen.setVisibility(View.GONE);
        }
    }

这个方法是主动来切换activity的横竖屏来通知播放器和activity来对大小屏的切换里做出处理,当然你也可以不用onConfigurationChanged方法来间接处理,自己写一个方法来处理,并旋转播放器90度也是可以的,但是这种方法要对activity的ActionBar做处理,要是有ActionBar就需要hide。

四、 在Activity和Fragment中实现大小屏切换

开源项目:MDPlayer

在Activity中使用:

在Activity中使用

在Fragment的RecyclerView中使用:

在Fragment的RecyclerView中使用

这是我自己参考第三种方法实现的,我增加了再Fragment、Activity和RecyclerView中放大缩小播放器,基本涵盖了我们遇到的所有场景了。有第三种方法是在Activity中预留容器,所以要是有ActionBar的Activity在放大播放器后,ActionBar并不会主动隐藏,需要我们主动hide和show ActionBar:

    /**
     * 隐藏ActionBar
     */
    private void hideActionBar(){
        if(mainActivity.getSupportActionBar() != null)
            mainActivity.getSupportActionBar().hide();
    }

    /**
     * 显示ActionBar
     */
    private void showActionBar(){
        if(mainActivity.getSupportActionBar() != null)
            mainActivity.getSupportActionBar().show();
    }

要是在Fragment中使用,就要在Fragment中找到Activity中预留的容器:

 /***
         *  全屏播放器放在MainActivity中
         */
        fullScreen = (RelativeLayout) mainActivity.findViewById(R.id.full_screen);

在fragment和Activity中使用都要在方法中做出相应操作,下面是在Fragment中使用:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (mdPlayer != null) {
            /**
             * 在activity中监听到横竖屏变化时调用播放器的监听方法来实现播放器大小切换
             */
            mdPlayer.onConfigurationChanged(newConfig);
            if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                showActionBar();
                fullScreen.setVisibility(View.GONE);
                fullScreen.removeAllViews();
                videoRecyclerView.setVisibility(View.VISIBLE);
                if (postion <= mLayoutManager.findLastVisibleItemPosition()
                        && postion >= mLayoutManager.findFirstVisibleItemPosition()) {
                    View view = videoRecyclerView.findViewHolderForAdapterPosition(postion).itemView;
                    FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.adapter_super_video);
                    frameLayout.removeAllViews();
                    ViewGroup last = (ViewGroup) mdPlayer.getParent();//找到videoitemview的父类,然后remove
                    if (last != null) {
                        last.removeAllViews();
                    }
                    frameLayout.addView(mdPlayer);
                }
                int mShowFlags =
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
                fullScreen.setSystemUiVisibility(mShowFlags);
            } else {
                ViewGroup viewGroup = (ViewGroup) mdPlayer.getParent();
                if (viewGroup == null)
                    return;
                hideActionBar();
                viewGroup.removeAllViews();
                fullScreen.addView(mdPlayer);
                fullScreen.setVisibility(View.VISIBLE);
                int mHideFlags =
                        View.SYSTEM_UI_FLAG_LOW_PROFILE
                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_IMMERSIVE
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        ;
                fullScreen.setSystemUiVisibility(mHideFlags);
            }
        } else {
            fullScreen.setVisibility(View.GONE);
        }
        super.onConfigurationChanged(newConfig);
    }
  • 20
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 42
    评论
### 回答1: Android播放器切换全屏是一种常见的操作,能够提供更好的观看体验。在Android开发中,要实现播放器的全屏切换,可以通过以下步骤进行: 1. 首先,需要在播放器的布局文件中添加一个用于全屏显示的组件,例如一个FrameLayout,并设置其宽度和高度为match_parent。 2. 在播放器的Activity或Fragment中,监听并处理全屏切换的事件。一般可以通过点击一个全屏按钮或者设备屏幕旋转来触发全屏切换。 3. 当触发全屏切换时,需要进行一些操作,首先是隐藏系统状态栏和导航栏,可以通过设置Activity的Window属性来实现。例如,在Activity的onCreate()方法中可以添加如下代码: ``` getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ``` 4. 接下来,需要调整播放器的宽度和高度,以充满整个屏幕。可以通过设置播放器容器的LayoutParams来实现,例如: ``` FrameLayout frameLayout = findViewById(R.id.player_container); frameLayout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ``` 5. 调整完播放器的尺寸后,还需要调整播放器的布局,使其能够适应全屏显示。这可能涉及到改变视频的缩放模式、调整控制面板的位置等等,具体操作可以根据需求进行调整。 通过上述步骤,就可以实现Android播放器的全屏切换。当切换全屏时,用户能够更好地享受视频内容,提供了更好的观看体验。同时,在退出全屏时,需要还原回原始的布局和尺寸设置,以保持应用的稳定性和一致性。 ### 回答2: Android 播放器切换全屏是指在播放视频时,将播放器界面自动切换全屏模式,以便用户可全屏观看视频。在Android开发中,实现播放器切换全屏通常需要以下步骤: 1. 首先,需要在布局文件中创建一个用于播放视频的VideoView组件,并设置其宽高为match_parent以占满整个屏幕。 2. 在Activity或Fragment中,需要实现全屏切换的逻辑。一种常见的方式是监听屏幕方向变化,并在全屏与非全屏之间进行切换。 3. 在监听屏幕方向变化时,可以通过重载Activity或Fragment的onConfigurationChanged方法来响应屏幕方向变化事件。当屏幕方向变为横屏时,将播放器的布局参数设置为全屏,同时隐藏其他UI元素(例如标题栏、导航栏等)。当屏幕方向变为竖屏时,恢复播放器的原始布局参数,并显示其他UI元素。 4. 在切换全屏时,还需要调用Activity或Fragment的setRequestedOrientation方法来设置屏幕方向,以保证播放器可以正确显示。 5. 在全屏切换过程中,还可以添加一些动画效果,使切换过程平滑。 6. 最后,为了确保播放器能够正常播放全屏视频,还需要注意一些细节,例如在全屏切换时暂停播放、切换屏幕方向时重新加载视频等。 综上所述,Android 播放器切换全屏可以通过监听屏幕方向变化,调整播放器布局参数以及设置屏幕方向等步骤来实现。通过合理的逻辑和界面设计,可以让用户在Android设备上享受到更好的全屏视频观看体验。 ### 回答3: Android播放器切换全屏需要以下步骤: 1. 首先,确保在播放器布局中有一个用于视频显示的容器,比如一个SurfaceView或TextureView。 2. 在播放器的Activity或Fragment中,设置一个标志变量来记录当前的屏幕状态,比如fullscreenFlag,默认为false。 3. 在播放器的布局文件中,添加一个全屏按钮,使用一个ImageView来表示。当用户点击全屏按钮时,触发一个点击事件。 4. 在点击事件中,先检查当前屏幕状态。如果fullscreenFlag为false,即当前非全屏状态,则进行全屏切换操作。 5. 在全屏切换操作中,首先修改fullscreenFlag为true,然后获取到当前的Activity对象,并设置其显示方式为全屏模式,同时隐藏状态栏和导航栏。 6. 接下来,获取到当前Activity的窗口对象,调用setFlags方法并传入FLAG_FULLSCREEN标志,以全屏显示视频。 7. 修改播放器布局中的容器,将其宽度和高度设置为MATCH_PARENT,使视频充满整个屏幕。 8. 最后,调用横屏切换方法setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),将Activity设置为横屏显示。 通过以上步骤,可以实现Android播放器的全屏切换功能。当用户点击全屏按钮时,播放器会切换全屏模式,视频会充满整个屏幕,同时隐藏状态栏和导航栏。用户可以在全屏模式下享受更好的观影体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值