可缩放、双指放大的videoview

本文介绍了一种自定义的Android视频视图组件,该组件允许用户通过双指缩放和平移操作来调整视频播放的大小和位置。通过继承VideoView并实现GestureDetector的监听接口,组件能够响应用户的触摸事件,实现视频的缩放和平移功能。
public class AlbumVideoView extends VideoView implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
    
    private static final String TAG = "AlbumVideoView";
    private static final float MAX_SCALE = 4;
    private static final float MIN_SCALE = 1;
    private GestureDetector mGestureDetector;
    private boolean isHaveScrolled;
    private boolean isHaveScale;
    private float oldTwoPointerDistance;

    public AlbumVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureDetector = new GestureDetector(getContext(), this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(getClass().toString(), "onTouch: ");
        super.onTouchEvent(event);
        if (event.getPointerCount() == 1) {
            return mGestureDetector.onTouchEvent(event);
        } else if (event.getPointerCount() == 2) {
            return onScaleEvent(event);
        }
        return false;
    }

    private boolean onScaleEvent(MotionEvent event) {
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
            oldTwoPointerDistance = spacing(event);//两点按下时的距离
            Log.d(TAG, "onScaleEvent: ACTION_POINTER_DOWN");
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                oldTwoPointerDistance = spacing(event);//两点按下时的距离
                Log.d(TAG, "onScaleEvent: ACTION_DOWN");
                return true;
            case MotionEvent.ACTION_MOVE:
                //只有2个手指的时候才有放大缩小的操作
                float currentDist = spacing(event);
                Log.d(TAG, "onScaleEvent: currentDist = " + currentDist + " oldTwoPointerDistance = " + oldTwoPointerDistance);
                float scale = currentDist / oldTwoPointerDistance;
                setScale(scale);
                return true;
        }
        return false;
    }

    private float spacing(MotionEvent event) {
        if (event.getPointerCount() == 2) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return (float) Math.sqrt(x * x + y * y);
        } else {
            return 0;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(0, widthMeasureSpec);
        int height = getDefaultSize(0, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    public void setFixedVideoSize(int width, int height) {
        getHolder().setFixedSize(width, height);
    }

    /**
     * 触摸使用的移动事件
     * @param lessX
     * @param lessY
     */
    private void setSelfPivot(float lessX, float lessY) {
        float setPivotX = 0;
        float setPivotY = 0;
        setPivotX = getPivotX() + lessX;
        setPivotY = getPivotY() + lessY;
        Log.e("lawwingLog", "setPivotX:" + setPivotX + "  setPivotY:" + setPivotY
                + "  getWidth:" + getWidth() + "  getHeight:" + getHeight());
        if (setPivotX < 0 && setPivotY < 0) {
            setPivotX = 0;
            setPivotY = 0;
        } else if (setPivotX > 0 && setPivotY < 0) {
            setPivotY = 0;
            if (setPivotX > getWidth()) {
                setPivotX = getWidth();
            }
        } else if (setPivotX < 0 && setPivotY > 0) {
            setPivotX = 0;
            if (setPivotY > getHeight()) {
                setPivotY = getHeight();
            }
        } else {
            if (setPivotX > getWidth()) {
                setPivotX = getWidth();
            }
            if (setPivotY > getHeight()) {
                setPivotY = getHeight();
            }
        }
        setPivot(setPivotX, setPivotY);
    }

    /**
     * 平移画面,当画面的宽或高大于屏幕宽高时,调用此方法进行平移
     * @param x
     * @param y
     */
    public void setPivot(float x, float y) {
        setPivotX(x);
        setPivotY(y);
    }

    /**
     * 设置放大缩小
     * @param scale
     */
    public void setScale(float scale) {
        Log.d(TAG, "setScale: scale = " + scale + " getScaleX() * scale = " + getScaleX() * scale);
        float currentScaleX = getScaleX() * scale;
        float currentScaleY = getScaleY() * scale;
        if (currentScaleX > MAX_SCALE || currentScaleY > MAX_SCALE) {
            currentScaleX = MAX_SCALE;
            currentScaleY = MAX_SCALE;
        } else if (currentScaleX < MIN_SCALE || currentScaleY < MIN_SCALE) {
            currentScaleX = MIN_SCALE;
            currentScaleY = MIN_SCALE;
        }
        setScaleX(currentScaleX);
        setScaleY(currentScaleY);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        isHaveScrolled = false;
        isHaveScale = false;
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        isHaveScrolled = true;
        setSelfPivot(e1.getX() - e2.getX(), e1.getY() - e2.getY());
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }
    
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.d(TAG, "onDoubleTap: ");
        if (getScaleX() > 1) {
            startScaleAnimation(getScaleX(), 1);
        } else {
            startScaleAnimation(getScaleX(), 2);
        }
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }

    private void startScaleAnimation(float start, float end) {
        ValueAnimator anim = ValueAnimator.ofFloat(start, end);
        anim.setDuration(200);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float currentValue = (float) animation.getAnimatedValue();
                setScaleX(currentValue);
                setScaleY(currentValue);
                Log.d("TAG", "cuurent value is " + currentValue);
            }
        });
        anim.start();
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值