Procházet zdrojové kódy

完善视频悬浮窗

yangchong před 3 roky
rodič
revize
fec4935ec0

+ 9 - 10
Demo/src/main/java/com/yc/ycvideoplayer/MainActivity.java

@@ -18,20 +18,19 @@ import android.widget.TextView;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.appcompat.app.AppCompatActivity;
-import com.yc.music.model.AudioBean;
+
 import com.yc.music.service.PlayAudioService;
 import com.yc.music.tool.BaseAppHelper;
 import com.yc.video.tool.BaseToast;
 import com.yc.videotool.VideoLogUtils;
 import com.yc.videoview.FloatWindow;
-import com.yc.videoview.MoveType;
-import com.yc.videoview.WindowScreen;
-import com.yc.videoview.WindowUtil;
+import com.yc.videoview.tool.FloatMoveType;
+import com.yc.videoview.tool.FloatScreenType;
+import com.yc.videoview.tool.FloatWindowUtils;
 import com.yc.ycvideoplayer.audio.AudioActivity;
 import com.yc.ycvideoplayer.m3u8.M3u8Activity;
 import com.yc.ycvideoplayer.music.MusicPlayerActivity;
 import com.yc.ycvideoplayer.video.activity.TypeActivity;
-import java.util.List;
 
 import cn.ycbjie.ycstatusbarlib.bar.StateAppBar;
 
@@ -110,7 +109,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
                 break;
             case R.id.tv_6:
                 if (Build.VERSION.SDK_INT >= 23) {
-                    if (!WindowUtil.hasPermission(this)) {
+                    if (!FloatWindowUtils.hasPermission(this)) {
                         requestAlertWindowPermission();
                     } else {
                         windowDialog();
@@ -135,7 +134,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         if (Build.VERSION.SDK_INT >= 23) {
-            if (WindowUtil.hasPermission(this)) {
+            if (FloatWindowUtils.hasPermission(this)) {
 
             } else {
                 this.finish();
@@ -153,9 +152,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
                 //.setWidth(WindowScreen.WIDTH, 0.4f)
                 //.setHeight(WindowScreen.WIDTH, 0.3f)
                 //这个是设置位置
-                .setX(WindowScreen.WIDTH, 0.8f)
-                .setY(WindowScreen.HEIGHT, 0.3f)
-                .setMoveType(MoveType.slide)
+                .setX(FloatScreenType.WIDTH, 0.8f)
+                .setY(FloatScreenType.HEIGHT, 0.3f)
+                .setMoveType(FloatMoveType.SLIDE)
                 .setFilter(false)
                 //.setFilter(true, WindowActivity.class, EmptyActivity.class)
                 .setMoveStyle(500, new BounceInterpolator())

+ 0 - 568
ReadMeWiki/00.方案实践/03.播放器UI抽取封装.md

@@ -140,574 +140,6 @@
 
 
 
-### 04.VideoPlayer如何实现
-- 代码如下所示,省略了部分代码,具体看demo
-    ``` java
-    public class VideoPlayer<P extends AbstractVideoPlayer> extends FrameLayout
-            implements InterVideoPlayer, VideoPlayerListener {
-    
-        private Context mContext;
-        /**
-         * 播放器
-         */
-        protected P mMediaPlayer;
-        /**
-         * 实例化播放核心
-         */
-        protected PlayerFactory<P> mPlayerFactory;
-        /**
-         * 控制器
-         */
-        @Nullable
-        protected BaseVideoController mVideoController;
-        /**
-         * 真正承载播放器视图的容器
-         */
-        protected FrameLayout mPlayerContainer;
-
-        public VideoPlayer(@NonNull Context context) {
-            this(context, null);
-        }
-    
-        public VideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs) {
-            this(context, attrs, 0);
-        }
-    
-        public VideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-            super(context, attrs, defStyleAttr);
-            mContext = context;
-            init(attrs);
-        }
-    
-        private void init(AttributeSet attrs) {
-            BaseToast.init(mContext.getApplicationContext());
-            //读取全局配置
-            initConfig();
-            //读取xml中的配置,并综合全局配置
-            initAttrs(attrs);
-            initView();
-        }
-    
-        private void initConfig() {
-            VideoPlayerConfig config = VideoViewManager.getConfig();
-            mEnableAudioFocus = config.mEnableAudioFocus;
-            mProgressManager = config.mProgressManager;
-            mPlayerFactory = config.mPlayerFactory;
-            mCurrentScreenScaleType = config.mScreenScaleType;
-            mRenderViewFactory = config.mRenderViewFactory;
-            //设置是否打印日志
-            VideoLogUtils.setIsLog(config.mIsEnableLog);
-        }
-
-        @Override
-        protected Parcelable onSaveInstanceState() {
-            VideoLogUtils.d("onSaveInstanceState: " + mCurrentPosition);
-            //activity切到后台后可能被系统回收,故在此处进行进度保存
-            saveProgress();
-            return super.onSaveInstanceState();
-        }
-    
-        private void initAttrs(AttributeSet attrs) {
-            TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.VideoPlayer);
-            mEnableAudioFocus = a.getBoolean(R.styleable.VideoPlayer_enableAudioFocus, mEnableAudioFocus);
-            mIsLooping = a.getBoolean(R.styleable.VideoPlayer_looping, false);
-            mCurrentScreenScaleType = a.getInt(R.styleable.VideoPlayer_screenScaleType, mCurrentScreenScaleType);
-            mPlayerBackgroundColor = a.getColor(R.styleable.VideoPlayer_playerBackgroundColor, Color.BLACK);
-            a.recycle();
-        }
-    
-        /**
-         * 初始化播放器视图
-         */
-        protected void initView() {
-            mPlayerContainer = new FrameLayout(getContext());
-            //设置背景颜色,目前设置为纯黑色
-            mPlayerContainer.setBackgroundColor(mPlayerBackgroundColor);
-            LayoutParams params = new LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT);
-            //将布局添加到该视图中
-            this.addView(mPlayerContainer, params);
-        }
-    
-        /**
-         * 设置控制器,传null表示移除控制器
-         * @param mediaController                           controller
-         */
-        public void setController(@Nullable BaseVideoController mediaController) {
-            mPlayerContainer.removeView(mVideoController);
-            mVideoController = mediaController;
-            if (mediaController != null) {
-                mediaController.setMediaPlayer(this);
-                LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-                        ViewGroup.LayoutParams.MATCH_PARENT);
-                mPlayerContainer.addView(mVideoController, params);
-            }
-        }
-    
-        /**
-         * 开始播放,注意:调用此方法后必须调用{@link #release()}释放播放器,否则会导致内存泄漏
-         */
-        @Override
-        public void start() {
-            if (mVideoController==null){
-                //在调用start方法前,请先初始化视频控制器,调用setController方法
-                throw new VideoException(VideoException.CODE_NOT_SET_CONTROLLER,
-                        "Controller must not be null , please setController first");
-            }
-            boolean isStarted = false;
-            if (isInIdleState() || isInStartAbortState()) {
-                isStarted = startPlay();
-            } else if (isInPlaybackState()) {
-                startInPlaybackState();
-                isStarted = true;
-            }
-            if (isStarted) {
-                mPlayerContainer.setKeepScreenOn(true);
-                if (mAudioFocusHelper != null){
-                    mAudioFocusHelper.requestFocus();
-                }
-            }
-        }
-    
-        /**
-         * 第一次播放
-         * @return 是否成功开始播放
-         */
-        protected boolean startPlay() {
-            //如果要显示移动网络提示则不继续播放
-            if (showNetWarning()) {
-                //中止播放
-                setPlayState(ConstantKeys.CurrentState.STATE_START_ABORT);
-                return false;
-            }
-            //监听音频焦点改变
-            if (mEnableAudioFocus) {
-                mAudioFocusHelper = new AudioFocusHelper(this);
-            }
-            //读取播放进度
-            if (mProgressManager != null) {
-                mCurrentPosition = mProgressManager.getSavedProgress(mUrl);
-            }
-            initPlayer();
-            addDisplay();
-            startPrepare(false);
-            return true;
-        }
-    
-    
-        /**
-         * 初始化播放器
-         */
-        protected void initPlayer() {
-            //通过工厂模式创建对象
-            mMediaPlayer = mPlayerFactory.createPlayer(mContext);
-            mMediaPlayer.setPlayerEventListener(this);
-            setInitOptions();
-            mMediaPlayer.initPlayer();
-            setOptions();
-        }
-
-        /**
-         * 初始化视频渲染View
-         */
-        protected void addDisplay() {
-            if (mRenderView != null) {
-                mPlayerContainer.removeView(mRenderView.getView());
-                mRenderView.release();
-            }
-            //创建TextureView对象
-            mRenderView = mRenderViewFactory.createRenderView(mContext);
-            //绑定mMediaPlayer对象
-            mRenderView.attachToPlayer(mMediaPlayer);
-            LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
-            mPlayerContainer.addView(mRenderView.getView(), 0, params);
-        }
-    
-        /**
-         * 开始准备播放(直接播放)
-         */
-        protected void startPrepare(boolean reset) {
-            if (reset) {
-                mMediaPlayer.reset();
-                //重新设置option,media player reset之后,option会失效
-                setOptions();
-            }
-            if (prepareDataSource()) {
-                mMediaPlayer.prepareAsync();
-                setPlayState(ConstantKeys.CurrentState.STATE_PREPARING);
-                setPlayerState(isFullScreen() ? ConstantKeys.PlayMode.MODE_FULL_SCREEN :
-                        isTinyScreen() ? ConstantKeys.PlayMode.MODE_TINY_WINDOW : ConstantKeys.PlayMode.MODE_NORMAL);
-            }
-        }
-    
-        /**
-         * 设置播放数据
-         * @return 播放数据是否设置成功
-         */
-        protected boolean prepareDataSource() {
-            if (mAssetFileDescriptor != null) {
-                mMediaPlayer.setDataSource(mAssetFileDescriptor);
-                return true;
-            } else if (!TextUtils.isEmpty(mUrl)) {
-                mMediaPlayer.setDataSource(mUrl, mHeaders);
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * 向Controller设置播放状态,用于控制Controller的ui展示
-         * 这里使用注解限定符,不要使用1,2这种直观数字,不方便知道意思
-         * 播放状态,主要是指播放器的各种状态
-         * -1               播放错误
-         * 0                播放未开始
-         * 1                播放准备中
-         * 2                播放准备就绪
-         * 3                正在播放
-         * 4                暂停播放
-         * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
-         * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
-         * 7                播放完成
-         * 8                开始播放中止
-         */
-        protected void setPlayState(@ConstantKeys.CurrentStateType int playState) {
-            mCurrentPlayState = playState;
-            if (mVideoController != null) {
-                mVideoController.setPlayState(playState);
-            }
-            if (mOnStateChangeListeners != null) {
-                for (OnVideoStateListener l : PlayerUtils.getSnapshot(mOnStateChangeListeners)) {
-                    if (l != null) {
-                        l.onPlayStateChanged(playState);
-                    }
-                }
-            }
-        }
-    
-        /**
-         * 向Controller设置播放器状态,包含全屏状态和非全屏状态
-         * 播放模式
-         * 普通模式,小窗口模式,正常模式三种其中一种
-         * MODE_NORMAL              普通模式
-         * MODE_FULL_SCREEN         全屏模式
-         * MODE_TINY_WINDOW         小屏模式
-         */
-        protected void setPlayerState(@ConstantKeys.PlayModeType int playerState) {
-            mCurrentPlayerState = playerState;
-            if (mVideoController != null) {
-                mVideoController.setPlayerState(playerState);
-            }
-            if (mOnStateChangeListeners != null) {
-                for (OnVideoStateListener l : PlayerUtils.getSnapshot(mOnStateChangeListeners)) {
-                    if (l != null) {
-                        l.onPlayerStateChanged(playerState);
-                    }
-                }
-            }
-        }
-    
-        /**
-         * OnStateChangeListener的空实现。用的时候只需要重写需要的方法
-         */
-        public static class SimpleOnStateChangeListener implements OnVideoStateListener {
-            @Override
-            public void onPlayerStateChanged(@ConstantKeys.PlayModeType int playerState) {}
-            @Override
-            public void onPlayStateChanged(int playState) {}
-        }
-    
-        /**
-         * 添加一个播放状态监听器,播放状态发生变化时将会调用。
-         */
-        public void addOnStateChangeListener(@NonNull OnVideoStateListener listener) {
-            if (mOnStateChangeListeners == null) {
-                mOnStateChangeListeners = new ArrayList<>();
-            }
-            mOnStateChangeListeners.add(listener);
-        }
-    
-        /**
-         * 移除某个播放状态监听
-         */
-        public void removeOnStateChangeListener(@NonNull OnVideoStateListener listener) {
-            if (mOnStateChangeListeners != null) {
-                mOnStateChangeListeners.remove(listener);
-            }
-        }
-    
-        /**
-         * 设置一个播放状态监听器,播放状态发生变化时将会调用,
-         * 如果你想同时设置多个监听器,推荐 {@link #addOnStateChangeListener(OnVideoStateListener)}。
-         */
-        public void setOnStateChangeListener(@NonNull OnVideoStateListener listener) {
-            if (mOnStateChangeListeners == null) {
-                mOnStateChangeListeners = new ArrayList<>();
-            } else {
-                mOnStateChangeListeners.clear();
-            }
-            mOnStateChangeListeners.add(listener);
-        }
-    
-        /**
-         * 移除所有播放状态监听
-         */
-        public void clearOnStateChangeListeners() {
-            if (mOnStateChangeListeners != null) {
-                mOnStateChangeListeners.clear();
-            }
-        }
-    
-        /**
-         * 改变返回键逻辑,用于activity
-         */
-        public boolean onBackPressed() {
-            return mVideoController != null && mVideoController.onBackPressed();
-        }
-
-    }
-    ```
-
-
-### 05.VideoController实现
-- 代码如下所示,代码太长,省略部分代码,具体看demo
-    ``` java
-    public abstract class BaseVideoController extends FrameLayout implements InterVideoController,
-            OrientationHelper.OnOrientationChangeListener {
-    
-        //播放器包装类,集合了MediaPlayerControl的api和IVideoController的api
-        protected ControlWrapper mControlWrapper;
-
-        public BaseVideoController(@NonNull Context context) {
-            //创建
-            this(context, null);
-        }
-    
-        public BaseVideoController(@NonNull Context context, @Nullable AttributeSet attrs) {
-            //创建
-            this(context, attrs, 0);
-        }
-    
-        public BaseVideoController(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
-            super(context, attrs, defStyleAttr);
-            initView(context);
-        }
-
-        protected void initView(Context context) {
-            if (getLayoutId() != 0) {
-                LayoutInflater.from(getContext()).inflate(getLayoutId(), this, true);
-            }
-            mOrientationHelper = new OrientationHelper(context.getApplicationContext());
-            mEnableOrientation = VideoViewManager.getConfig().mEnableOrientation;
-            mAdaptCutout = VideoViewManager.getConfig().mAdaptCutout;
-            mShowAnim = new AlphaAnimation(0f, 1f);
-            mShowAnim.setDuration(300);
-            mHideAnim = new AlphaAnimation(1f, 0f);
-            mHideAnim.setDuration(300);
-            mActivity = PlayerUtils.scanForActivity(context);
-        }
-    
-        /**
-         * 设置控制器布局文件,子类必须实现
-         */
-        protected abstract int getLayoutId();
-    
-        /**
-         * 重要:此方法用于将{@link VideoPlayer} 和控制器绑定
-         */
-        @CallSuper
-        public void setMediaPlayer(InterVideoPlayer mediaPlayer) {
-            mControlWrapper = new ControlWrapper(mediaPlayer, this);
-            //绑定ControlComponent和Controller
-            for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
-                InterControlView component = next.getKey();
-                component.attach(mControlWrapper);
-            }
-            //开始监听设备方向
-            mOrientationHelper.setOnOrientationChangeListener(this);
-        }
-    
-        /**
-         * 添加控制组件,最后面添加的在最下面,合理组织添加顺序,可让ControlComponent位于不同的层级
-         */
-        public void addControlComponent(InterControlView... component) {
-            for (InterControlView item : component) {
-                addControlComponent(item, false);
-            }
-        }
-    
-        /**
-         * 添加控制组件,最后面添加的在最下面,合理组织添加顺序,可让ControlComponent位于不同的层级
-         *
-         * @param isPrivate 是否为独有的组件,如果是就不添加到控制器中
-         */
-        public void addControlComponent(InterControlView component, boolean isPrivate) {
-            mControlComponents.put(component, isPrivate);
-            if (mControlWrapper != null) {
-                component.attach(mControlWrapper);
-            }
-            View view = component.getView();
-            if (view != null && !isPrivate) {
-                addView(view, 0);
-            }
-        }
-    
-        /**
-         * 移除控制组件
-         */
-        public void removeControlComponent(InterControlView component) {
-            removeView(component.getView());
-            mControlComponents.remove(component);
-        }
-    
-        /**
-         * 移除所有的组件
-         */
-        public void removeAllControlComponent() {
-            for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
-                removeView(next.getKey().getView());
-            }
-            mControlComponents.clear();
-        }
-    
-        public void removeAllPrivateComponents() {
-            Iterator<Map.Entry<InterControlView, Boolean>> it = mControlComponents.entrySet().iterator();
-            while (it.hasNext()) {
-                Map.Entry<InterControlView, Boolean> next = it.next();
-                if (next.getValue()) {
-                    it.remove();
-                }
-            }
-        }
-    
-        /**
-         * {@link VideoPlayer}调用此方法向控制器设置播放状态。
-         * 这里使用注解限定符,不要使用1,2这种直观数字,不方便知道意思
-         * 播放状态,主要是指播放器的各种状态
-         * -1               播放错误
-         * 0                播放未开始
-         * 1                播放准备中
-         * 2                播放准备就绪
-         * 3                正在播放
-         * 4                暂停播放
-         * 5                正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
-         * 6                暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
-         * 7                播放完成
-         * 8                开始播放中止
-         */
-        @CallSuper
-        public void setPlayState(@ConstantKeys.CurrentStateType int playState) {
-            //设置播放器的状态
-            handlePlayStateChanged(playState);
-        }
-    
-        /**
-         * {@link VideoPlayer}调用此方法向控制器设置播放器状态
-         * 播放模式
-         * 普通模式,小窗口模式,正常模式三种其中一种
-         * MODE_NORMAL              普通模式
-         * MODE_FULL_SCREEN         全屏模式
-         * MODE_TINY_WINDOW         小屏模式
-         */
-        @CallSuper
-        public void setPlayerState(@ConstantKeys.PlayModeType final int playerState) {
-            //调用此方法向控制器设置播放器状态
-            handlePlayerStateChanged(playerState);
-        }
-        
-        private void handleVisibilityChanged(boolean isVisible, Animation anim) {
-            if (!mIsLocked) {
-                //没锁住时才向ControlComponent下发此事件
-                for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
-                    InterControlView component = next.getKey();
-                    component.onVisibilityChanged(isVisible, anim);
-                }
-            }
-            onVisibilityChanged(isVisible, anim);
-        }
-    
-        private void handlePlayStateChanged(int playState) {
-            for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
-                InterControlView component = next.getKey();
-                component.onPlayStateChanged(playState);
-            }
-            onPlayStateChanged(playState);
-        }
-    
-        /**
-         * 子类重写此方法并在其中更新控制器在不同播放状态下的ui
-         */
-        @CallSuper
-        protected void onPlayStateChanged(int playState) {
-            switch (playState) {
-                case ConstantKeys.CurrentState.STATE_IDLE:
-                    mOrientationHelper.disable();
-                    mOrientation = 0;
-                    mIsLocked = false;
-                    mShowing = false;
-                    removeAllPrivateComponents();
-                    break;
-                case ConstantKeys.CurrentState.STATE_BUFFERING_PLAYING:
-                    mIsLocked = false;
-                    mShowing = false;
-                    break;
-                case ConstantKeys.CurrentState.STATE_ERROR:
-                    mShowing = false;
-                    break;
-            }
-        }
-    
-        /**
-         * 播放器状态改变
-         * @param playerState                       播放器状态
-         */
-        private void handlePlayerStateChanged(int playerState) {
-            for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
-                InterControlView component = next.getKey();
-                component.onPlayerStateChanged(playerState);
-            }
-            onPlayerStateChanged(playerState);
-        }
-    
-        /**
-         * 子类重写此方法并在其中更新控制器在不同播放器状态下的ui
-         * 普通模式,小窗口模式,正常模式三种其中一种
-         * MODE_NORMAL              普通模式
-         * MODE_FULL_SCREEN         全屏模式
-         * MODE_TINY_WINDOW         小屏模式
-         */
-        @CallSuper
-        protected void onPlayerStateChanged(@ConstantKeys.PlayMode int playerState) {
-            switch (playerState) {
-                case ConstantKeys.PlayMode.MODE_NORMAL:
-                    //视频正常播放是设置监听
-                    if (mEnableOrientation) {
-                        //检查系统是否开启自动旋转
-                        mOrientationHelper.enable();
-                    } else {
-                        //取消监听
-                        mOrientationHelper.disable();
-                    }
-                    if (hasCutout()) {
-                        StatesCutoutUtils.adaptCutoutAboveAndroidP(getContext(), false);
-                    }
-                    break;
-                case ConstantKeys.PlayMode.MODE_FULL_SCREEN:
-                    //在全屏时强制监听设备方向
-                    mOrientationHelper.enable();
-                    if (hasCutout()) {
-                        StatesCutoutUtils.adaptCutoutAboveAndroidP(getContext(), true);
-                    }
-                    break;
-                case ConstantKeys.PlayMode.MODE_TINY_WINDOW:
-                    //小窗口取消重力感应监听
-                    mOrientationHelper.disable();
-                    break;
-            }
-        }
-    }
-    ```
 
 
 ### 06.播放Player和UI通信

+ 1 - 1
ReadMeWiki/00.方案实践/06.视频边播边缓存分析.md

@@ -1,4 +1,4 @@
-# 12.视频边播边缓存分析
+# 视频边播边缓存分析
 #### 目录介绍
 - 01.前沿场景介绍一下
 - 02.致敬优秀开源项目

+ 0 - 155
ReadMeWiki/00.方案实践/12.TTS音频播放实践.md

@@ -1,155 +0,0 @@
-# TTS音频播放基础
-#### 目录介绍
-- 01.TTS简单的描述
-- 02.TTS简单的案例
-- 03.TTS播报监听处理
-- 04.TTS播报异常分析
-- 05.TTS播放音频案例
-- 06.TTS播放测试用例
-- 08.TTS接口设计架构
-
-
-
-
-
-### 01.TTS简单的描述
-- TTS全称Text  To Speech ,是文本转语音服务
-
-
-
-### 02.TTS简单的案例
-#### 2.1 初始化tts
-- 代码如下所示
-    ```
-    textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
-        @Override
-        public void onInit(int status) {
-            if (!mReady  && (TextToSpeech.SUCCESS == status) && textToSpeech != null) {
-                VideoLogUtils.i("Initialize TTS success");
-                //获取locale
-                final Locale locale = mContext.getApplicationContext()
-                        .getResources().getConfiguration().locale;
-                if (locale != null) {
-                    VideoLogUtils.i("tts isLanguageAvailable " + mTts.isLanguageAvailable(locale) +
-                            "; variant is " + locale.getVariant() +
-                            "; locale is " + locale + " ; country  is " + locale.getCountry());
-                }
-                //设置朗读语言
-                int setLanguage = this.textToSpeech.setLanguage(null != locale ? locale : Locale.getDefault());
-                switch (setLanguage) {
-                    case TextToSpeech.LANG_MISSING_DATA:
-                        VideoLogUtils.i("TTS set language: Language missing data");
-                        break;
-                    case TextToSpeech.LANG_NOT_SUPPORTED:
-                        VideoLogUtils.i("TTS set language: Language not supported");
-                        break;
-                    case TextToSpeech.LANG_AVAILABLE:
-                        VideoLogUtils.i("TTS set language: Language available");
-                        break;
-                    case TextToSpeech.LANG_COUNTRY_AVAILABLE:
-                        VideoLogUtils.i("TTS set language: Language country available");
-                        break;
-                    case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
-                        VideoLogUtils.i("TTS set language: Language country var available");
-                        break;
-                    default:
-                        VideoLogUtils.i("TTS set language: Unknown error");
-                        break;
-                }
-            } else if (TextToSpeech.ERROR == status) {
-                VideoLogUtils.i("Initialize TTS error");
-            } else {
-                VideoLogUtils.i("Initialize TTS error");
-            }
-        }
-    });
-    ```
-
-
-#### 2.2 如何进行初始化
-- 如何进行播放?
-    ```
-    textToSpeech.speak(tts, TextToSpeech.QUEUE_FLUSH, null);
-    ```
-- 循环播放语音
-    - 想让他报个2-3遍或者循环播报的时候,我们来试一下
-    ```
-    for (int i=0 ; i<5 ; i++){
-        textToSpeech.speak("简单播放tts,"+i, TextToSpeech.QUEUE_FLUSH, null);
-    }
-    ```
-    - 简单的不行,但是问题来了,一段长的文字他只播报前面几个字,然后又重新开始播报。
-    - 这是因为textToSpeech.speak(tts, TextToSpeech.QUEUE_FLUSH, null);这个方法会自动关闭掉上面一个播报的内容,从而进行新一轮的播报。
-- 播放完成后再播放
-    - 要等上一条播报完整了再进行播报,该如何操作呢?那么可以TTS有 isSpeaking() 这个方法
-    ```
-    for (int i=0 ; i<5 ; i++){
-        if (!textToSpeech.isSpeaking()){
-            textToSpeech.speak("简单播放tts,"+i, TextToSpeech.QUEUE_FLUSH, null);
-        }
-    }
-    ```
-    - 这样就可以播全了嘛? 非也,for循环飞快的跑只要发现在speaking那么直接跳过开始走下一个i
-- 如何正确循环播放
-    ```
-    for (int i=0 ; i<5 ; i++){
-        textToSpeech.speak("简单播放,"+i, TextToSpeech.QUEUE_ADD, null);
-    }
-    ```
-    - 这样就相当于在一个消息队列然后进行循环的播报。
-
-
-### 03.TTS播报监听处理
-- 关于监听tts状态如下所示:
-    ```
-    private final class OnCompleteListener extends UtteranceProgressListener {
-    
-        OnCompleteListener() {
-    
-        }
-    
-        /**
-         * 播放完成。这个是播报完毕的时候 每一次播报完毕都会走
-         * @param utteranceId                       话语id
-         */
-        @Override
-        public void onDone(final String utteranceId) {
-            VideoLogUtils.i("TTSPlayer OnCompleteListener onDone");
-            onCompleted();
-        }
-    
-        /**
-         * 播放异常
-         * @param utteranceId                       话语id
-         */
-        @Override
-        public void onError(final String utteranceId) {
-            VideoLogUtils.i("TTSPlayer OnCompleteListener onError");
-            stop();
-            onError("TTSPlayer has play fail : " + utteranceId);
-            onCompleted();
-        }
-    
-        /**
-         * 播放开始。这个是开始的时候。是先发声之后才会走这里
-         * 调用isSpeaking()方法在这为true
-         * @param utteranceId                       话语id
-         */
-        @Override
-        public void onStart(final String utteranceId) {
-    
-        }
-    }
-    ```
-
-
-### 08.TTS接口设计架构
-
-
-### 参考
-- https://blog.csdn.net/qq_30359699/article/details/105388575
-- https://blog.csdn.net/awodefengduanwu/article/details/105683306
-
-
-
-

+ 1 - 1
VideoView/src/main/java/com/yc/videoview/FloatLifecycle.java

@@ -37,7 +37,7 @@ public class FloatLifecycle extends BroadcastReceiver implements Application.Act
     private final ILifecycleListener mLifecycleListener;
 
 
-    FloatLifecycle(Context applicationContext, boolean showFlag, Class[] activities,
+    public FloatLifecycle(Context applicationContext, boolean showFlag, Class[] activities,
                    ILifecycleListener lifecycleListener) {
         this.showFlag = showFlag;
         this.activities = activities;

+ 34 - 30
VideoView/src/main/java/com/yc/videoview/FloatWindow.java

@@ -12,7 +12,11 @@ import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.yc.videoview.impl.FloatWindowImpl;
 import com.yc.videoview.inter.IFloatWindow;
+import com.yc.videoview.tool.FloatMoveType;
+import com.yc.videoview.tool.FloatScreenType;
+import com.yc.videoview.tool.FloatWindowUtils;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -65,19 +69,19 @@ public class FloatWindow {
     }
 
     public static class Builder {
-        Context mApplicationContext;
-        View mView;
+        public Context mApplicationContext;
+        public View mView;
         private int mLayoutId;
-        int mWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
-        int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
-        int gravity = Gravity.TOP | Gravity.START;
-        int xOffset;
-        int yOffset;
-        boolean mShow = true;
-        Class[] mActivities;
-        int mMoveType = MoveType.fixed;
-        long mDuration = 300;
-        TimeInterpolator mInterpolator;
+        public int mWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
+        public int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
+        public int gravity = Gravity.TOP | Gravity.START;
+        public int xOffset;
+        public int yOffset;
+        public boolean mShow = true;
+        public Class[] mActivities;
+        public int mMoveType = FloatMoveType.FIXED;
+        public long mDuration = 300;
+        public TimeInterpolator mInterpolator;
         private String mTag = mDefaultTag;
 
         private Builder() {
@@ -108,18 +112,18 @@ public class FloatWindow {
             return this;
         }
 
-        public Builder setWidth(@WindowScreen.screenType int screenType, float ratio) {
-            mWidth = (int) ((screenType == WindowScreen.WIDTH ?
-                    WindowUtil.getScreenWidth(mApplicationContext) :
-                    WindowUtil.getScreenHeight(mApplicationContext)) * ratio);
+        public Builder setWidth(@FloatScreenType.screenType int screenType, float ratio) {
+            mWidth = (int) ((screenType == FloatScreenType.WIDTH ?
+                    FloatWindowUtils.getScreenWidth(mApplicationContext) :
+                    FloatWindowUtils.getScreenHeight(mApplicationContext)) * ratio);
             return this;
         }
 
 
-        public Builder setHeight(@WindowScreen.screenType int screenType, float ratio) {
-            mHeight = (int) ((screenType == WindowScreen.WIDTH ?
-                    WindowUtil.getScreenWidth(mApplicationContext) :
-                    WindowUtil.getScreenHeight(mApplicationContext)) * ratio);
+        public Builder setHeight(@FloatScreenType.screenType int screenType, float ratio) {
+            mHeight = (int) ((screenType == FloatScreenType.WIDTH ?
+                    FloatWindowUtils.getScreenWidth(mApplicationContext) :
+                    FloatWindowUtils.getScreenHeight(mApplicationContext)) * ratio);
             return this;
         }
 
@@ -134,17 +138,17 @@ public class FloatWindow {
             return this;
         }
 
-        public Builder setX(@WindowScreen.screenType int screenType, float ratio) {
-            xOffset = (int) ((screenType == WindowScreen.WIDTH ?
-                    WindowUtil.getScreenWidth(mApplicationContext) :
-                    WindowUtil.getScreenHeight(mApplicationContext)) * ratio);
+        public Builder setX(@FloatScreenType.screenType int screenType, float ratio) {
+            xOffset = (int) ((screenType == FloatScreenType.WIDTH ?
+                    FloatWindowUtils.getScreenWidth(mApplicationContext) :
+                    FloatWindowUtils.getScreenHeight(mApplicationContext)) * ratio);
             return this;
         }
 
-        public Builder setY(@WindowScreen.screenType int screenType, float ratio) {
-            yOffset = (int) ((screenType == WindowScreen.WIDTH ?
-                    WindowUtil.getScreenWidth(mApplicationContext) :
-                    WindowUtil.getScreenHeight(mApplicationContext)) * ratio);
+        public Builder setY(@FloatScreenType.screenType int screenType, float ratio) {
+            yOffset = (int) ((screenType == FloatScreenType.WIDTH ?
+                    FloatWindowUtils.getScreenWidth(mApplicationContext) :
+                    FloatWindowUtils.getScreenHeight(mApplicationContext)) * ratio);
             return this;
         }
 
@@ -161,7 +165,7 @@ public class FloatWindow {
             return this;
         }
 
-        public Builder setMoveType(@MoveType.MOVE_TYPE int moveType) {
+        public Builder setMoveType(@FloatMoveType.MOVE_TYPE int moveType) {
             mMoveType = moveType;
             return this;
         }
@@ -195,7 +199,7 @@ public class FloatWindow {
                     mView = inflate.inflate(mLayoutId, null);
                 }
             }
-            IFloatWindow floatWindowImpl = new IFloatWindowImpl(this);
+            IFloatWindow floatWindowImpl = new FloatWindowImpl(this);
             mFloatWindowMap.put(mTag, floatWindowImpl);
         }
     }

+ 0 - 23
VideoView/src/main/java/com/yc/videoview/MoveType.java

@@ -1,23 +0,0 @@
-package com.yc.videoview;
-
-
-import androidx.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-public class MoveType {
-
-    public static final int fixed = 0;
-    public static final int free = 1;
-    public static final int active = 2;
-    public static final int slide = 3;
-    public static final int back = 4;
-
-    @IntDef({fixed, free, active, slide, back})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface MOVE_TYPE {
-
-    }
-
-}

+ 4 - 2
VideoView/src/main/java/com/yc/videoview/PermissionActivity.java

@@ -9,6 +9,8 @@ import android.os.Bundle;
 import androidx.annotation.RequiresApi;
 import androidx.appcompat.app.AppCompatActivity;
 
+import com.yc.videoview.tool.FloatWindowUtils;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -48,7 +50,7 @@ public class PermissionActivity extends AppCompatActivity {
         super.onActivityResult(requestCode, resultCode, data);
         if (Build.VERSION.SDK_INT >= 23){
             //用23以上编译即可出现canDrawOverlays
-            if (WindowUtil.hasPermission(this)) {
+            if (FloatWindowUtils.hasPermission(this)) {
                 mPermissionListener.onSuccess();
             } else {
                 mPermissionListener.onFail();
@@ -57,7 +59,7 @@ public class PermissionActivity extends AppCompatActivity {
         finish();
     }
 
-    static synchronized void request(Context context, PermissionListener permissionListener) {
+    public static synchronized void request(Context context, PermissionListener permissionListener) {
         if (mPermissionListenerList == null) {
             mPermissionListenerList = new ArrayList<>();
             mPermissionListener = new PermissionListener() {

+ 15 - 12
VideoView/src/main/java/com/yc/videoview/abs/AbsFloatView.java

@@ -1,6 +1,6 @@
 package com.yc.videoview.abs;
 
-import android.view.View;
+import com.yc.videoview.inter.IFloatView;
 
 /**
  * <pre>
@@ -11,22 +11,25 @@ import android.view.View;
  *     revise: 定义抽象方法和普通方法
  * </pre>
  */
-public abstract class AbsFloatView {
-
-    public abstract void setSize(int width, int height);
-
-    public abstract void setView(View view);
-
-    public abstract void setGravity(int gravity, int xOffset, int yOffset);
-
-    public abstract void init();
-
-    public abstract void dismiss();
+public abstract class AbsFloatView implements IFloatView {
 
+    /**
+     * 更新x和y
+     * @param x                     x
+     * @param y                     y
+     */
     public void updateXY(int x, int y) {}
 
+    /**
+     * 更新x
+     * @param x                     x
+     */
     public void updateX(int x) {}
 
+    /**
+     * 更新y
+     * @param y                     y
+     */
     public void updateY(int y) {}
 
     public int getX() {

+ 6 - 4
VideoView/src/main/java/com/yc/videoview/FloatPhone.java → VideoView/src/main/java/com/yc/videoview/impl/FloatPhoneImpl.java

@@ -1,4 +1,4 @@
-package com.yc.videoview;
+package com.yc.videoview.impl;
 
 import android.content.Context;
 import android.graphics.PixelFormat;
@@ -6,6 +6,8 @@ import android.os.Build;
 import android.view.View;
 import android.view.WindowManager;
 
+import com.yc.videoview.PermissionActivity;
+import com.yc.videoview.tool.FloatWindowUtils;
 import com.yc.videoview.abs.AbsFloatView;
 
 /**
@@ -17,7 +19,7 @@ import com.yc.videoview.abs.AbsFloatView;
  *     revise: 7.1及以上需申请权限
  * </pre>
  */
-public class FloatPhone extends AbsFloatView {
+public class FloatPhoneImpl extends AbsFloatView {
 
     private final Context mContext;
     private final WindowManager mWindowManager;
@@ -25,7 +27,7 @@ public class FloatPhone extends AbsFloatView {
     private View mView;
     private int mX, mY;
 
-    FloatPhone(Context applicationContext) {
+    public FloatPhoneImpl(Context applicationContext) {
         mContext = applicationContext;
         //创建WindowManager
         mWindowManager = (WindowManager)
@@ -82,7 +84,7 @@ public class FloatPhone extends AbsFloatView {
     @Override
     public void init() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            if (WindowUtil.hasPermission(mContext)) {
+            if (FloatWindowUtils.hasPermission(mContext)) {
                 //设置bitmap的格式
                 mLayoutParams.format = PixelFormat.RGBA_8888;
                 //将悬浮窗控件添加到WindowManager

+ 3 - 3
VideoView/src/main/java/com/yc/videoview/FloatToast.java → VideoView/src/main/java/com/yc/videoview/impl/FloatToastImpl.java

@@ -1,4 +1,4 @@
-package com.yc.videoview;
+package com.yc.videoview.impl;
 
 import android.content.Context;
 import android.view.View;
@@ -20,7 +20,7 @@ import java.lang.reflect.Method;
  *     revise:
  * </pre>
  */
-public class FloatToast extends AbsFloatView {
+public class FloatToastImpl extends AbsFloatView {
 
     private final Toast toast;
     private Object mTN;
@@ -30,7 +30,7 @@ public class FloatToast extends AbsFloatView {
     private int mHeight;
 
 
-    FloatToast(Context applicationContext) {
+    public FloatToastImpl(Context applicationContext) {
         toast = new Toast(applicationContext);
     }
 

+ 45 - 40
VideoView/src/main/java/com/yc/videoview/IFloatWindowImpl.java → VideoView/src/main/java/com/yc/videoview/impl/FloatWindowImpl.java

@@ -1,4 +1,4 @@
-package com.yc.videoview;
+package com.yc.videoview.impl;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -11,6 +11,11 @@ import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.DecelerateInterpolator;
 
+import com.yc.videoview.FloatLifecycle;
+import com.yc.videoview.FloatWindow;
+import com.yc.videoview.tool.FloatMoveType;
+import com.yc.videoview.tool.FloatScreenType;
+import com.yc.videoview.tool.FloatWindowUtils;
 import com.yc.videoview.abs.AbsFloatView;
 import com.yc.videoview.inter.IFloatWindow;
 import com.yc.videoview.inter.ILifecycleListener;
@@ -24,10 +29,10 @@ import com.yc.videoview.inter.ILifecycleListener;
  *     revise:
  * </pre>
  */
-public class IFloatWindowImpl implements IFloatWindow {
+public class FloatWindowImpl implements IFloatWindow {
 
 
-    private FloatWindow.Builder mB;
+    private FloatWindow.Builder mBuilder;
     private AbsFloatView mFloatView;
     private FloatLifecycle mFloatLifecycle;
     private boolean isShow;
@@ -35,28 +40,28 @@ public class IFloatWindowImpl implements IFloatWindow {
     private ValueAnimator mAnimator;
     private TimeInterpolator mDecelerateInterpolator;
 
-    private IFloatWindowImpl() {
+    private FloatWindowImpl() {
 
     }
 
-    IFloatWindowImpl(FloatWindow.Builder b) {
-        mB = b;
+    public FloatWindowImpl(FloatWindow.Builder b) {
+        mBuilder = b;
         //这一步相当于创建系统级的window,通过windowManager添加view并且展示
-        if (mB.mMoveType == MoveType.fixed) {
+        if (mBuilder.mMoveType == FloatMoveType.FIXED) {
             if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.N_MR1) {
-                mFloatView = new FloatPhone(b.mApplicationContext);
+                mFloatView = new FloatPhoneImpl(b.mApplicationContext);
             } else {
-                mFloatView = new FloatToast(b.mApplicationContext);
+                mFloatView = new FloatToastImpl(b.mApplicationContext);
             }
         } else {
-            mFloatView = new FloatPhone(b.mApplicationContext);
+            mFloatView = new FloatPhoneImpl(b.mApplicationContext);
             initTouchEvent();
         }
-        mFloatView.setSize(mB.mWidth, mB.mHeight);
-        mFloatView.setGravity(mB.gravity, mB.xOffset, mB.yOffset);
-        mFloatView.setView(mB.mView);
-        mFloatLifecycle = new FloatLifecycle(mB.mApplicationContext,
-                mB.mShow, mB.mActivities, new ILifecycleListener() {
+        mFloatView.setSize(mBuilder.mWidth, mBuilder.mHeight);
+        mFloatView.setGravity(mBuilder.gravity, mBuilder.xOffset, mBuilder.yOffset);
+        mFloatView.setView(mBuilder.mView);
+        mFloatLifecycle = new FloatLifecycle(mBuilder.mApplicationContext,
+                mBuilder.mShow, mBuilder.mActivities, new ILifecycleListener() {
             @Override
             public void onShow() {
                 show();
@@ -111,34 +116,34 @@ public class IFloatWindowImpl implements IFloatWindow {
     @Override
     public void updateX(int x) {
         checkMoveType();
-        mB.xOffset = x;
+        mBuilder.xOffset = x;
         mFloatView.updateX(x);
     }
 
     @Override
     public void updateY(int y) {
         checkMoveType();
-        mB.yOffset = y;
+        mBuilder.yOffset = y;
         mFloatView.updateY(y);
     }
 
     @Override
     public void updateX(int screenType, float ratio) {
         checkMoveType();
-        mB.xOffset = (int) ((screenType == WindowScreen.WIDTH ?
-                WindowUtil.getScreenWidth(mB.mApplicationContext) :
-                WindowUtil.getScreenHeight(mB.mApplicationContext)) * ratio);
-        mFloatView.updateX(mB.xOffset);
+        mBuilder.xOffset = (int) ((screenType == FloatScreenType.WIDTH ?
+                FloatWindowUtils.getScreenWidth(mBuilder.mApplicationContext) :
+                FloatWindowUtils.getScreenHeight(mBuilder.mApplicationContext)) * ratio);
+        mFloatView.updateX(mBuilder.xOffset);
 
     }
 
     @Override
     public void updateY(int screenType, float ratio) {
         checkMoveType();
-        mB.yOffset = (int) ((screenType == WindowScreen.WIDTH ?
-                WindowUtil.getScreenWidth(mB.mApplicationContext) :
-                WindowUtil.getScreenHeight(mB.mApplicationContext)) * ratio);
-        mFloatView.updateY(mB.yOffset);
+        mBuilder.yOffset = (int) ((screenType == FloatScreenType.WIDTH ?
+                FloatWindowUtils.getScreenWidth(mBuilder.mApplicationContext) :
+                FloatWindowUtils.getScreenHeight(mBuilder.mApplicationContext)) * ratio);
+        mFloatView.updateY(mBuilder.yOffset);
 
     }
 
@@ -155,7 +160,7 @@ public class IFloatWindowImpl implements IFloatWindow {
 
     @Override
     public View getView() {
-        return mB.mView;
+        return mBuilder.mView;
     }
 
     void postHide() {
@@ -172,14 +177,14 @@ public class IFloatWindowImpl implements IFloatWindow {
     }
 
     private void checkMoveType() {
-        if (mB.mMoveType == MoveType.fixed) {
+        if (mBuilder.mMoveType == FloatMoveType.FIXED) {
             throw new IllegalArgumentException("FloatWindow of this tag is not allowed to move!");
         }
     }
 
     private void initTouchEvent() {
-        switch (mB.mMoveType) {
-            case MoveType.free:
+        switch (mBuilder.mMoveType) {
+            case FloatMoveType.FREE:
                 break;
             default:
                 getView().setOnTouchListener(onTouchListener);
@@ -208,12 +213,12 @@ public class IFloatWindowImpl implements IFloatWindow {
                     lastY = event.getRawY();
                     break;
                 case MotionEvent.ACTION_UP:
-                    switch (mB.mMoveType) {
-                        case MoveType.slide:
+                    switch (mBuilder.mMoveType) {
+                        case FloatMoveType.SLIDE:
                             int startX = mFloatView.getX();
                             int endX = (startX * 2 + v.getWidth() >
-                                    WindowUtil.getScreenWidth(mB.mApplicationContext)) ?
-                                    WindowUtil.getScreenWidth(mB.mApplicationContext) - v.getWidth() : 0;
+                                    FloatWindowUtils.getScreenWidth(mBuilder.mApplicationContext)) ?
+                                    FloatWindowUtils.getScreenWidth(mBuilder.mApplicationContext) - v.getWidth() : 0;
                             mAnimator = ObjectAnimator.ofInt(startX, endX);
                             mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                 @Override
@@ -224,9 +229,9 @@ public class IFloatWindowImpl implements IFloatWindow {
                             });
                             startAnimator();
                             break;
-                        case MoveType.back:
-                            PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("x", mFloatView.getX(), mB.xOffset);
-                            PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("y", mFloatView.getY(), mB.yOffset);
+                        case FloatMoveType.BACK:
+                            PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("x", mFloatView.getX(), mBuilder.xOffset);
+                            PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("y", mFloatView.getY(), mBuilder.yOffset);
                             mAnimator = ObjectAnimator.ofPropertyValuesHolder(pvhX, pvhY);
                             mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                 @Override
@@ -254,13 +259,13 @@ public class IFloatWindowImpl implements IFloatWindow {
      * 开启动画
      */
     private void startAnimator() {
-        if (mB.mInterpolator == null) {
+        if (mBuilder.mInterpolator == null) {
             if (mDecelerateInterpolator == null) {
                 mDecelerateInterpolator = new DecelerateInterpolator();
             }
-            mB.mInterpolator = mDecelerateInterpolator;
+            mBuilder.mInterpolator = mDecelerateInterpolator;
         }
-        mAnimator.setInterpolator(mB.mInterpolator);
+        mAnimator.setInterpolator(mBuilder.mInterpolator);
         mAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -269,7 +274,7 @@ public class IFloatWindowImpl implements IFloatWindow {
                 mAnimator = null;
             }
         });
-        mAnimator.setDuration(mB.mDuration).start();
+        mAnimator.setDuration(mBuilder.mDuration).start();
     }
 
     /**

+ 47 - 0
VideoView/src/main/java/com/yc/videoview/inter/IFloatView.java

@@ -0,0 +1,47 @@
+package com.yc.videoview.inter;
+
+import android.view.View;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2021/12/21
+ *     desc  : 悬浮view接口
+ *     revise:
+ * </pre>
+ */
+public interface IFloatView {
+
+    /**
+     * 设置大小
+     * @param width                 宽
+     * @param height                高
+     */
+    void setSize(int width, int height);
+
+    /**
+     * 设置view
+     * @param view                  view
+     */
+    void setView(View view);
+
+    /**
+     * 设置是否显示
+     * @param gravity               显示
+     * @param xOffset               x偏移
+     * @param yOffset               y偏移
+     */
+    void setGravity(int gravity, int xOffset, int yOffset);
+
+    /**
+     * 初始化
+     */
+    void init();
+
+    /**
+     * 销毁
+     */
+    void dismiss();
+
+}

+ 3 - 3
VideoView/src/main/java/com/yc/videoview/inter/IFloatWindow.java

@@ -2,7 +2,7 @@ package com.yc.videoview.inter;
 
 import android.view.View;
 
-import com.yc.videoview.WindowScreen;
+import com.yc.videoview.tool.FloatScreenType;
 
 /**
  * <pre>
@@ -25,11 +25,11 @@ public interface IFloatWindow {
 
     void updateX(int x);
 
-    void updateX(@WindowScreen.screenType int screenType, float ratio);
+    void updateX(@FloatScreenType.screenType int screenType, float ratio);
 
     void updateY(int y);
 
-    void updateY(@WindowScreen.screenType int screenType, float ratio);
+    void updateY(@FloatScreenType.screenType int screenType, float ratio);
 
     View getView();
 

+ 23 - 0
VideoView/src/main/java/com/yc/videoview/tool/FloatMoveType.java

@@ -0,0 +1,23 @@
+package com.yc.videoview.tool;
+
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public final class FloatMoveType {
+
+    public static final int FIXED = 0;
+    public static final int FREE = 1;
+    public static final int ACTIVE = 2;
+    public static final int SLIDE = 3;
+    public static final int BACK = 4;
+
+    @IntDef({FIXED, FREE, ACTIVE, SLIDE, BACK})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MOVE_TYPE {
+
+    }
+
+}

+ 2 - 2
VideoView/src/main/java/com/yc/videoview/WindowScreen.java → VideoView/src/main/java/com/yc/videoview/tool/FloatScreenType.java

@@ -1,4 +1,4 @@
-package com.yc.videoview;
+package com.yc.videoview.tool;
 
 
 import androidx.annotation.IntDef;
@@ -7,7 +7,7 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 
-public class WindowScreen {
+public final class FloatScreenType {
     public static final int WIDTH = 0;
     public static final int HEIGHT = 1;
 

+ 2 - 2
VideoView/src/main/java/com/yc/videoview/WindowUtil.java → VideoView/src/main/java/com/yc/videoview/tool/FloatWindowUtils.java

@@ -1,4 +1,4 @@
-package com.yc.videoview;
+package com.yc.videoview.tool;
 
 import android.content.Context;
 import android.graphics.Point;
@@ -9,7 +9,7 @@ import android.view.WindowManager;
 import androidx.annotation.RequiresApi;
 
 
-public final class WindowUtil {
+public final class FloatWindowUtils {
 
 
     @RequiresApi(api = Build.VERSION_CODES.M)