【问题标题】:How to manage Custom Video player Zoom In / Zoom Out programmatically?如何以编程方式管理自定义视频播放器放大/缩小?
【发布时间】:2020-02-13 14:25:32
【问题描述】:

我们可以通过两种方式实现自定义视频播放器:

  1. 视频视图

  2. SurfaceView 并使用 MediaPlayer 执行此操作。

我阅读了一个与Custom Video Player 相关的教程,其中 SurfaceView 和使用 MediaPlayer 用于实现此功能 - - link here

我需要什么:

如何使您的自定义视图类似于"When you touch on the video screen such as zoom out/zoom in, video view goes to the full screen and after zoom in gesture back to fix size what earlier "

有人可以建议我怎么做吗?

【问题讨论】:

    标签: android video android-video-player


    【解决方案1】:

    我已经与大家分享了我的代码,我正在使用纹理视图通过两根手指(捏缩放)进行放大/缩小

            package com.app.sampletextureview;
    
        import android.app.Activity;
        import android.content.Context;
        import android.content.res.AssetFileDescriptor;
        import android.graphics.Matrix;
        import android.graphics.PointF;
        import android.graphics.SurfaceTexture;
        import android.media.MediaActionSound;
        import android.media.MediaMetadataRetriever;
        import android.media.MediaPlayer;
        import android.support.v7.app.ActionBarActivity;
        import android.os.Bundle;
        import android.util.DisplayMetrics;
    
        import android.util.FloatMath;
        import android.util.Log;
        import android.view.Gravity;
        import android.view.Menu;
        import android.view.MenuItem;
        import android.view.MotionEvent;
        import android.view.ScaleGestureDetector;
        import android.view.Surface;
        import android.view.SurfaceHolder;
        import android.view.TextureView;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.FrameLayout;
        import android.widget.RelativeLayout;
    
        import java.io.IOException;
    
    
        public class MainActivity extends Activity implements TextureView.SurfaceTextureListener,View.OnTouchListener {
            private static final String TAG = MainActivity.class.getName();
            private static final String FILE_NAME = "Vid.mp4";
    
            private MediaPlayer mMediaPlayer;
            private TextureView mTextureView;
            private RelativeLayout mrRelativeLayout;
    
            private float mVideoWidth;
            private float mVideoHeight;
    
            DisplayMetrics dm;
    
            RelativeLayout.LayoutParams params;
    
            private ScaleGestureDetector scaleGestureDetector;
            private Matrix matrix = new Matrix();
    
            @SuppressWarnings("unused")
            private static final float MIN_ZOOM = 1f,MAX_ZOOM = 1f;
    
            // These matrices will be used to scale points of the image
    
            Matrix savedMatrix = new Matrix();
    
            // The 3 states (events) which the user is trying to perform
            static final int NONE = 0;
            static final int DRAG = 1;
            static final int ZOOM = 2;
            int mode = NONE;
    
            // these PointF objects are used to record the point(s) the user is touching
            PointF start = new PointF();
            PointF mid = new PointF();
            float oldDist = 1f;
    
            private float mVideoWidth;
        private float mVideoHeight;
    
    
    
        int viewWidth=0,viewHeight=0,xoff=0,yoff=0;;
    
    
    
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
    
                calculateVideoSize();
    
                initView();
    
            }
            private void initView() {
    
                mrRelativeLayout= (RelativeLayout) findViewById(R.id.rootView);
                mTextureView = (TextureView) findViewById(R.id.textureView);
    
                mTextureView.setOnTouchListener(this);
    
    
                /*Log.d("Height-WidthOnCreate",""+mVideoHeight+"-"+mVideoWidth);
                mTextureView.setMinimumWidth((int)mVideoWidth);
    
                mTextureView.setMinimumHeight((int)mVideoHeight);
    
                mTextureView.setSurfaceTextureListener(this);
    
    
            }
    
    
            @Override
            protected void onDestroy() {
                super.onDestroy();
                if (mMediaPlayer != null) {
                    mMediaPlayer.stop();
                    mMediaPlayer.release();
                    mMediaPlayer = null;
                }
            }
    
            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.menu_main, menu);
                return true;
            }
    
            @Override
            public boolean onOptionsItemSelected(MenuItem item) {
                // Handle action bar item clicks here. The action bar will
                // automatically handle clicks on the Home/Up button, so long
                // as you specify a parent activity in AndroidManifest.xml.
                int id = item.getItemId();
    
                //noinspection SimplifiableIfStatement
                if (id == R.id.action_settings) {
                    return true;
                }
    
                return super.onOptionsItemSelected(item);
            }
    
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
                Surface surface = new Surface(surfaceTexture);
    
                try {
                    AssetFileDescriptor afd = getAssets().openFd(FILE_NAME);
                    mMediaPlayer = new MediaPlayer();
    
                    mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
    
                    mMediaPlayer.setSurface(surface);
    
                    mMediaPlayer.setLooping(true);
    
                    // don't forget to call MediaPlayer.prepareAsync() method when you use constructor for
                    // creating MediaPlayer
                    mMediaPlayer.prepareAsync();
    
                    adjustAspectRatio((int) mVideoWidth, (int)mVideoHeight);
                        Log.d("SurfaceCreate",""+mVideoWidth+""+mVideoHeight);
    
    
    
                    // Play video when the media source is ready for playback.
                    mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mediaPlayer) {
                            mediaPlayer.start();
                        }
                    });
    
                } catch (IllegalArgumentException e) {
                    Log.d(TAG, e.getMessage());
                } catch (SecurityException e) {
                    Log.d(TAG, e.getMessage());
                } catch (IllegalStateException e) {
                    Log.d(TAG, e.getMessage());
                } catch (IOException e) {
                    Log.d(TAG, e.getMessage());
                }
    
    
    
    
            }
    
            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
    
            }
    
            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
    
    
    
                return false;
            }
    
            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
    
            }
    
            private void calculateVideoSize() {
                try {
                    AssetFileDescriptor afd = getAssets().openFd(FILE_NAME);
                    MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
                    metaRetriever.setDataSource(
                            afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                    String height = metaRetriever
                            .extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
                    String width = metaRetriever
                            .extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
                    mVideoHeight = Float.parseFloat(height);
                    mVideoWidth = Float.parseFloat(width);
    
                    Log.d("Height-Width",""+mVideoHeight+"-"+mVideoWidth);
    
                } catch (IOException e) {
                    Log.d(TAG, e.getMessage());
                } catch (NumberFormatException e) {
                    Log.d(TAG, e.getMessage());
                }
            }
    
    
            private void updateTextureViewSize(int viewWidth, int viewHeight) {
                float scaleX = 1.0f;
                float scaleY = 1.0f;
    
                if (mVideoWidth > viewWidth && mVideoHeight > viewHeight) {
                    scaleX = mVideoWidth / viewWidth;
                    scaleY = mVideoHeight / viewHeight;
                } else if (mVideoWidth < viewWidth && mVideoHeight < viewHeight) {
                    scaleY = viewWidth / mVideoWidth;
                    scaleX = viewHeight / mVideoHeight;
                } else if (viewWidth > mVideoWidth) {
                    scaleY = (viewWidth / mVideoWidth) / (viewHeight / mVideoHeight);
                } else if (viewHeight > mVideoHeight) {
                    scaleX = (viewHeight / mVideoHeight) / (viewWidth / mVideoWidth);
                }
    
                // Calculate pivot points, in our case crop from center
                int pivotPointX = viewWidth / 2;
                int pivotPointY = viewHeight / 2;
    
                Matrix matrix = new Matrix();
                matrix.setScale(scaleX, scaleY, pivotPointX, pivotPointY);
    
                mTextureView.setTransform(matrix);
    
            }
    
    
            private void adjustAspectRatio(int videoWidth, int videoHeight) {
                int viewWidth = mTextureView.getWidth();
                int viewHeight = mTextureView.getHeight();
                double aspectRatio = (double) videoHeight / videoWidth;
    
                int newWidth, newHeight;
                if (viewHeight > (int) (viewWidth * aspectRatio)) {
                    // limited by narrow width; restrict height
                    newWidth = viewWidth;
                    newHeight = (int) (viewWidth * aspectRatio);
                } else {
                    // limited by short height; restrict width
                    newWidth = (int) (viewHeight / aspectRatio);
                    newHeight = viewHeight;
                }
                int xoff = (viewWidth - newWidth) / 2;
                int yoff = (viewHeight - newHeight) / 2;
                Log.v(TAG, "video=" + videoWidth + "x" + videoHeight +
                        " view=" + viewWidth + "x" + viewHeight +
                        " newView=" + newWidth + "x" + newHeight +
                        " off=" + xoff + "," + yoff);
    
                Matrix txform = new Matrix();
                mTextureView.getTransform(txform);
                txform.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight);
                //txform.postRotate(10);          // just for fun
                txform.postTranslate(xoff, yoff);
                mTextureView.setTransform(txform);
            }
    
    
          /*  @Override
            public boolean onTouchEvent(MotionEvent ev) {
        //        scaleGestureDetector.onTouchEvent(ev);
                return true;
            }
        */
    
    
    
            private class ScaleListener extends ScaleGestureDetector.
                    SimpleOnScaleGestureListener {
                @Override
                public boolean onScale(ScaleGestureDetector detector) {
                    float scaleFactor = detector.getScaleFactor();
                    scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 5.0f));
                    matrix.setScale(scaleFactor, scaleFactor);
                    Log.d("Matrix", "" + scaleFactor);
                    mTextureView.setTransform(matrix);
    
                    return true;
                }
            }
    
    
         @Override
        public boolean onTouch(View v, MotionEvent event)
        {
    
    
    
            dumpEvent(event);
            // Handle touch events here...
    
    
            switch (event.getAction() & MotionEvent.ACTION_MASK)
            {
                case MotionEvent.ACTION_DOWN:   // first finger down only
    
                    if (!istouch) {
                        istouch=true;
                        ll_bottombar.setVisibility(View.VISIBLE);
                        ll_topheader.setVisibility(View.VISIBLE);
                        hideSystemUI(getWindow());
    
                    }else{
                        String tag = btnLock.getTag().toString();
                        if (tag.equals("false")) {
                            istouch = false;
                            ll_bottombar.setVisibility(View.GONE);
                            ll_topheader.setVisibility(View.GONE);
                            hideSystemUI(getWindow());
    
                        }
                    }
                    break;
    
                case MotionEvent.ACTION_UP: // first finger lifted
    
                    mode = NONE;
                    Log.d(TAG, "mode=NONE");
                    break;
    
                case MotionEvent.ACTION_POINTER_UP: // second finger lifted
    
                    mode = NONE;
                    Log.d(TAG, "mode=NONE");
                    break;
    
                case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
               //case MotionEvent.ACTION_POINTER_2_DOWN:
    
                    oldDist = spacing(event);
                    Log.d(TAG, "oldDist=" + oldDist);
    
                    if (oldDist > 5f) {
                       savedMatrix.set(matrix);
                        midPoint(mid, event);
                      //  matrix.setScale( mid.y,(float) newWidth / viewWidth,mid.x, (float) newHeight / viewHeight);
                       // matrix.setScale(mid.x,mid.y);
                        if(event.getPointerCount() >= 2) {
                            event.setAction(MotionEvent.ACTION_MOVE);
                            mode = ZOOM;
    
                            Log.d(TAG, "mode=ZOOM");
                        }
    
                    }
                   break;
    
    
                case MotionEvent.ACTION_MOVE:
                    if (mode == NONE)
                {
                    mode = NONE;
                    Log.d(TAG, "mode=NONE");
    
                }
                    if (event.getPointerCount() >= 2) {
                   /* if (mode == DRAG)
                    {
    
                        // matrix.set(savedMatrix);
                        //  matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix  of points
                    }else if (mode == NONE)
                {
                    mode = NONE;
                    Log.d(TAG, "mode=NONE");
    
                }*/
                     if (mode == ZOOM) {
    
                            // pinch zooming
                            float newDist = spacing(event);
    
                            Log.d(TAG, "newDist=" + newDist);
                            if (newDist > 5f) {
                                matrix.set(savedMatrix);
                                Log.d(TAG, "NEW="+newDist+"--"+oldDist);
                                Log.d(TAG, "NEW Mid Point="+mid.x+"--"+mid.y);
                                scale = newDist / oldDist;
                               // matrix.setScale();
                               // matrix.setScale(scale,scale);
                                matrix.postScale(scale,scale,mid.x, mid.y);
    
    
                                Log.d(TAG,"New Hight Width"+mTextureView.getWidth()+"--"+mTextureView.getHeight());
    
                            }
    
                        }
    
                        mTextureView.setTransform(matrix);
                    }
    
    
                    break;
            }
    
          // display the transformation on screen
    
            return true; // indicate event was handled
        }
          /*  * --------------------------------------------------------------------------
             * Method: spacing Parameters: MotionEvent Returns: float Description:
             * checks the spacing between the two fingers on touch
             * ----------------------------------------------------
        */
    
    
            private float spacing(MotionEvent event)
            {
                float x = event.getX(0) - event.getX(1);
                float y = event.getY(0) - event.getY(1);
                return (float)Math.sqrt(x * x + y * y);
            }
    
           /*  * --------------------------------------------------------------------------
             * Method: midPoint Parameters: PointF object, MotionEvent Returns: void
             * Description: calculates the midpoint between the two fingers
             * ------------------------------------------------------------
    
            private void midPoint(PointF point, MotionEvent event)
            {
                float x = mrRelativeLayout.getX()+mrRelativeLayout.getWidth();
                float y = mrRelativeLayout.getY()+mrRelativeLayout.getHeight();
                point.set(x / 2, y / 2);
            }
    
    
            private void dumpEvent(MotionEvent event)
            {
                String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE","POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
                StringBuilder sb = new StringBuilder();
                int action = event.getAction();
                int actionCode = action & MotionEvent.ACTION_MASK;
                sb.append("event ACTION_").append(names[actionCode]);
    
                if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP)
                {
                    sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
                    sb.append(")");
                }
    
                sb.append("[");
                for (int i = 0; i < event.getPointerCount(); i++)
                {
                    sb.append("#").append(i);
                    sb.append("(pid ").append(event.getPointerId(i));
                    sb.append(")=").append((int) event.getX(i));
                    sb.append(",").append((int) event.getY(i));
                    if (i + 1 < event.getPointerCount())
                        sb.append(";");
                }
    
                sb.append("]");
            }
    
    
    
        private void adjustAspectRatio(int videoWidth, int videoHeight) {
    
         viewWidth = mTextureView.getWidth();
             viewHeight = mTextureView.getHeight();
    
            double aspectRatio = (double) videoHeight / videoWidth;
    
    
            if (viewHeight > (int) (viewWidth * aspectRatio)) {
                // limited by narrow width; restrict height
                newWidth = viewWidth;
                newHeight = (int) (viewWidth * aspectRatio);
            } else {
                // limited by short height; restrict width
                newWidth = (int) (viewHeight / aspectRatio);
                newHeight = viewHeight;
            }
    
            xoff = (viewWidth - newWidth) / 2;
    
            yoff = (viewHeight - newHeight) / 2;
    
    
            Log.d(TAG, "video=" + videoWidth + "x" + videoHeight +
                    " view=" + viewWidth + "x" + viewHeight +
                    " newView=" + newWidth + "x" + newHeight +
                    " off=" + xoff + "," + yoff);
    
            Log.d(TAG, "video="+mTextureView.getHeight()+"--"+mTextureView.getWidth());
            Log.d(TAG, "video="+newHeight+"--"+newWidth);
            mTextureView.setMinimumWidth(newWidth);
            mTextureView.setMinimumHeight(newHeight);
    
           // Matrix txform = new Matrix();
            mTextureView.getTransform(matrix);
            matrix.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight);
            //txform.postRotate(10);          // just for fun
            matrix.postTranslate(xoff, yoff);
            mTextureView.setTransform(matrix);
        }
    
    }
        }
    

    【讨论】:

    • 在上面的代码中,我使用“纹理视图”来播放视频,并且我已将视频文件放在行文件夹中。用于视频放大/缩小 private ScaleGestureDetector scaleGestureDetector;私有矩阵矩阵 = new Matrix();
    猜你喜欢
    • 2023-03-20
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多