org.videolan.vlc.gui.view.PopupLayout.java Source code

Java tutorial

Introduction

Here is the source code for org.videolan.vlc.gui.view.PopupLayout.java

Source

/*
 * ************************************************************************
 *  PopupView.java
 * *************************************************************************
 *  Copyright  2016 VLC authors and VideoLAN
 *  Author: Geoffrey Mtais
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *
 *  *************************************************************************
 */

package org.videolan.vlc.gui.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.Build;
import android.support.v4.view.GestureDetectorCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;

import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;

public class PopupLayout extends RelativeLayout
        implements ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener {
    private static final String TAG = "VLC/PopupView";

    private WindowManager mWindowManager;
    private GestureDetectorCompat mGestureDetector;
    private ScaleGestureDetector mScaleGestureDetector;
    private double mScaleFactor = 1.d;
    private int mPopupWidth, mPopupHeight;
    private int mScreenWidth, mScreenHeight;

    private int initialX, initialY;
    private float initialTouchX, initialTouchY;
    WindowManager.LayoutParams mLayoutParams;

    public PopupLayout(Context context) {
        super(context);
        init(context);
    }

    public PopupLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PopupLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /*
     * Remove layout from window manager
     */
    public void close() {
        setKeepScreenOn(false);
        mWindowManager.removeView(this);
        mWindowManager = null;
    }

    public void setGestureDetector(GestureDetectorCompat gdc) {
        mGestureDetector = gdc;
    }

    /*
     * Update layout dimensions and apply layout params to window manager
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    public void setViewSize(int width, int height) {
        if (width > mScreenWidth) {
            height = height * mScreenWidth / width;
            width = mScreenWidth;
        }
        if (height > mScreenHeight) {
            width = width * mScreenHeight / height;
            height = mScreenHeight;
        }
        containInScreen(width, height);
        mLayoutParams.width = width;
        mLayoutParams.height = height;
        mWindowManager.updateViewLayout(this, mLayoutParams);
    }

    @SuppressWarnings("deprecation")
    private void init(Context context) {
        mWindowManager = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                VLCApplication.getAppResources().getDimensionPixelSize(R.dimen.video_pip_width),
                VLCApplication.getAppResources().getDimensionPixelSize(R.dimen.video_pip_heigth),
                WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.OPAQUE);

        params.gravity = Gravity.BOTTOM | Gravity.START;
        params.x = 50;
        params.y = 50;
        if (AndroidUtil.isHoneycombOrLater())
            mScaleGestureDetector = new ScaleGestureDetector(context, this);
        setOnTouchListener(this);
        mWindowManager.addView(this, params);
        mLayoutParams = (WindowManager.LayoutParams) getLayoutParams();

        updateWindowSize();
    }

    private void updateWindowSize() {
        if (AndroidUtil.isHoneycombMr2OrLater()) {
            Point size = new Point();
            mWindowManager.getDefaultDisplay().getSize(size);
            mScreenWidth = size.x;
            mScreenHeight = size.y;
        } else {
            mScreenWidth = mWindowManager.getDefaultDisplay().getWidth();
            mScreenHeight = mWindowManager.getDefaultDisplay().getHeight();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (mWindowManager == null)
            return false;
        if (mScaleGestureDetector != null)
            mScaleGestureDetector.onTouchEvent(event);
        if (mGestureDetector != null && mGestureDetector.onTouchEvent(event))
            return true;
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            initialX = mLayoutParams.x;
            initialY = mLayoutParams.y;
            initialTouchX = event.getRawX();
            initialTouchY = event.getRawY();
            updateWindowSize();
            return true;
        case MotionEvent.ACTION_UP:
            return true;
        case MotionEvent.ACTION_MOVE:
            if (mScaleGestureDetector == null || !mScaleGestureDetector.isInProgress()) {
                mLayoutParams.x = initialX + (int) (event.getRawX() - initialTouchX);
                mLayoutParams.y = initialY - (int) (event.getRawY() - initialTouchY);
                containInScreen(mLayoutParams.width, mLayoutParams.height);
                mWindowManager.updateViewLayout(PopupLayout.this, mLayoutParams);
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();

        mScaleFactor = Math.max(0.1d, Math.min(mScaleFactor, 5.0d));
        mPopupWidth = (int) (getWidth() * mScaleFactor);
        mPopupHeight = (int) (getHeight() * mScaleFactor);
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
        lp.width *= mScaleFactor;
        lp.height *= mScaleFactor;
        setViewSize(mPopupWidth, mPopupHeight);
        mScaleFactor = 1.0d;
    }

    private void containInScreen(int width, int height) {
        mLayoutParams.x = Math.max(mLayoutParams.x, 0);
        mLayoutParams.y = Math.max(mLayoutParams.y, 0);
        if (mLayoutParams.x + width > mScreenWidth)
            mLayoutParams.x = mScreenWidth - width;
        if (mLayoutParams.y + height > mScreenHeight)
            mLayoutParams.y = mScreenHeight - height;
    }
}