欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android仿優(yōu)酷視頻的懸浮窗播放效果

 更新時(shí)間:2020年07月10日 14:42:08   作者:三非_程序猿  
這篇文章主要介紹了Android仿優(yōu)酷視頻的懸浮窗播放效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

之前接了需求要讓視頻播放時(shí)可以像優(yōu)酷視頻那樣在懸浮窗里播放,并且懸浮窗和主播放頁(yè)面之間要實(shí)現(xiàn)無(wú)縫切換,項(xiàng)目中使用的是自封裝的ijkplayer
這個(gè)要求就代表不能在懸浮窗中新建視頻控件,所以需要在懸浮窗中復(fù)用主頁(yè)面的視頻控件,以達(dá)到無(wú)縫銜接的效果。

主頁(yè)面對(duì)應(yīng)的視頻控件的父view

<FrameLayout
      android:id="@+id/vw_live"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_centerInParent="true"/>

用FrameLayout作為添加視頻控件的ParentView,通過(guò)addview方法將新建的播放器控件添加到父控件內(nèi)部

vw_live = new IjkVideoView(this);
video_frame = findViewById(R.id.vw_live);
video_frame.addView(vw_live);

主播放界面的啟動(dòng)模式

播放主界面的activity的啟動(dòng)模式不能為默認(rèn),因?yàn)槲覀円WC播放主界面在顯示懸浮窗的時(shí)候退到后臺(tái),但是整個(gè)的應(yīng)用不能退到后臺(tái),所以activity的啟動(dòng)模式改為singleInstance

android:launchMode="singleInstance"

退到后臺(tái)我們通過(guò)moveTaskToBack(true)方法;

moveTaskToBack(true);

可以讓播放界面退到后臺(tái)而整個(gè)應(yīng)用不會(huì)退回后臺(tái)

權(quán)限請(qǐng)求

要使用懸浮窗需要申請(qǐng)權(quán)限

<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
if (!Settings.canDrawOverlays(this)) {
      Toast.makeText(this, "當(dāng)前無(wú)權(quán)限,請(qǐng)授權(quán)", Toast.LENGTH_SHORT);
      startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2);
    } 

懸浮窗

 @SuppressLint("ClickableViewAccessibility")
  public void showFloatingWindowView(IjkVideoView view) {
    // 懸浮窗顯示視圖
    LayoutInflater layoutInflater = LayoutInflater.from(activity);
    mShowView = layoutInflater.inflate(R.layout.video_floating_window_layout, null);;
    // 獲取系統(tǒng)窗口管理服務(wù)
    mWindowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
    // 懸浮窗口參數(shù)設(shè)置及返回
    mFloatParams = getParams();
    //floatingWindow內(nèi)部控件實(shí)例
    init(view);
    // 設(shè)置窗口觸摸移動(dòng)事件
    mShowView.setOnTouchListener(new FloatViewMoveListener());

    // 懸浮窗生成
    mWindowManager.addView(mShowView, mFloatParams);
  }
  private void init(IjkVideoView viewGroup){
    videoLayout = mShowView.findViewById(R.id.floating_video);
    videoLayout.removeAllViews();
    if (viewGroup != null){
      ijkVideoView = viewGroup;
      videoLayout.addView(ijkVideoView,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
          ,ViewGroup.LayoutParams.MATCH_PARENT));
    }

    mBtnCloseFloatingWindow = mShowView.findViewById(R.id.close_floating_view);
    mBtnCloseFloatingWindow.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {

      }
    });
    mBtnBackFloatingWindow = (ImageView)mShowView.findViewById(R.id.back_floating_view);
    mBtnBackFloatingWindow.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {

      }
    });
  }

  private WindowManager.LayoutParams getParams() {
    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
    //設(shè)置懸浮窗口類型
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    } else {
      layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    }
    //設(shè)置懸浮窗口屬性
    layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
    //設(shè)置懸浮窗口透明
    layoutParams.format = PixelFormat.TRANSLUCENT;
    //設(shè)置懸浮窗口長(zhǎng)寬數(shù)據(jù)
    layoutParams.width = 500;
    layoutParams.height = 340;
    //設(shè)置懸浮窗顯示位置
    layoutParams.gravity = Gravity.START | Gravity.TOP;
    layoutParams.x = 100;
    layoutParams.y = 100;
    return layoutParams;
  }

懸浮窗的xml,可通過(guò)自定義獲得自己想要的效果

<FrameLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/floating_video_layout"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <FrameLayout
    android:id="@+id/floating_video"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>


  <ImageView
    android:id="@+id/close_floating_view"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_gravity="end"
    android:padding="10dp"
    android:src="@android:drawable/ic_menu_close_clear_cancel" />

  <ImageView
    android:id="@+id/back_floating_view"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:padding="10dp"
    android:src="@android:drawable/ic_menu_revert" />
</FrameLayout>

懸浮窗的滑動(dòng),我們可以通過(guò)自定義點(diǎn)擊監(jiān)聽實(shí)現(xiàn)

/**
   * 浮窗移動(dòng)/點(diǎn)擊監(jiān)聽
   */
  private class FloatViewMoveListener implements View.OnTouchListener {

    //開始觸控的坐標(biāo),移動(dòng)時(shí)的坐標(biāo)(相對(duì)于屏幕左上角的坐標(biāo))
    private int mTouchStartX;
    private int mTouchStartY;
    //開始時(shí)的坐標(biāo)和結(jié)束時(shí)的坐標(biāo)(相對(duì)于自身控件的坐標(biāo))
    private int mStartX, mStartY;
    //判斷懸浮窗口是否移動(dòng),這里做個(gè)標(biāo)記,防止移動(dòng)后松手觸發(fā)了點(diǎn)擊事件
    private boolean isMove;

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
      int action = motionEvent.getAction();
      int x = (int) motionEvent.getX();
      int y = (int) motionEvent.getY();
      switch (action) {
        case MotionEvent.ACTION_DOWN:
          isMove = false;
          mTouchStartX = (int) motionEvent.getRawX();
          mTouchStartY = (int) motionEvent.getRawY();
          mStartX = x;
          mStartY = y;
          break;
        case MotionEvent.ACTION_MOVE:
          int mTouchCurrentX = (int) motionEvent.getRawX();
          int mTouchCurrentY = (int) motionEvent.getRawY();
          mFloatParams.x += mTouchCurrentX - mTouchStartX;
          mFloatParams.y += mTouchCurrentY - mTouchStartY;
          mWindowManager.updateViewLayout(mShowView, mFloatParams);
          mTouchStartX = mTouchCurrentX;
          mTouchStartY = mTouchCurrentY;
          float deltaX = x - mStartX;
          float deltaY = y - mStartY;
          if (Math.abs(deltaX) >= 5 || Math.abs(deltaY) >= 5) {
            isMove = true;
          }
          break;
        case MotionEvent.ACTION_UP:
          break;
        default:
          break;
      }
      //如果是移動(dòng)事件不觸發(fā)OnClick事件,防止移動(dòng)的時(shí)候一放手形成點(diǎn)擊事件
      return isMove;
    }
  }

懸浮窗的消失,在這里調(diào)用videoLayout.removeAllViews()是為了將復(fù)用的視頻控件的父View清空,返回主播放activity的時(shí)候調(diào)用addview方法不會(huì)再報(bào) child view has Parent,you have to call removeView()的錯(cuò)

public void dismiss() {
    if (mWindowManager != null && mShowView != null) {
      videoLayout.removeAllViews();
      if (mShowView.getParent() != null){
        mWindowManager.removeView(mShowView);
      }
    }
  }

啟動(dòng)懸浮窗

 public videoFloatingWindow(Context context){
    super(context);
    this.activity = context;
  }

對(duì)于懸浮窗的調(diào)用

用hasBind來(lái)記錄是否調(diào)用了懸浮窗

 private void startFloatingWindow(){
    if (!Settings.canDrawOverlays(this)) {
      Toast.makeText(this, "當(dāng)前無(wú)權(quán)限,請(qǐng)授權(quán)", Toast.LENGTH_SHORT);
      startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2);
    } else {
      video_frame.removeView(vw_live);
      videoFloatingWindow.getInstance(this).showFloatingWindowView(vw_live);
      hasBind = true;
      moveTaskToBack(true);
    }
  }

注意

一.由于主界面activity使用了singleInstance啟動(dòng)模式,所以從懸浮窗返回主界面activity時(shí),要添加flag

  Intent intent = new Intent(activity, activity.getClass());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(intent);

二.當(dāng)主界面的activity退回后臺(tái),再重新進(jìn)入主界面的時(shí)候,注意,不再調(diào)用onCreate方法,而是調(diào)用onNewIntent,所以重寫onNewIntent方法,重新進(jìn)入主界面,懸浮窗消失

 @Override
  protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    Log.d("RemoteView", "重新顯示了");
    //不顯示懸浮框
    if (hasBind){
      videoFloatingWindow.getInstance(this).dismiss();
      video_frame.removeAllViews();
      if (vw_live != null){
        video_frame.addView(vw_live);
      }
      hasBind = false;
    }
  }

總結(jié)

到此這篇關(guān)于Android仿優(yōu)酷視頻的懸浮窗播放的文章就介紹到這了,更多相關(guān)android 優(yōu)酷視頻懸浮窗播放內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論