android - 即使 forceLayout() 不起作用,我如何强制 requestLayout()?

标签 android android-layout android-mediaplayer

我正在尝试编写视频播放器代码,它可以很好地播放视频,但我无法调整 SurfaceView 的大小。 准备好 MediaPlayer 后,我设置了所需的大小并调用了 requestLayout 或 forceLayout,但没有附加任何内容。我的 LogCat 说:

08-29 17:42:38.915: I/SEC_Overlay(2707): overlay_setParameter param[4]=0
08-29 17:42:38.915: D/SEC_Overlay(2707): dst width, height have changed [w= 480, h= 800] -> [w=480, h= 800]
08-29 17:42:38.915: I/SEC_Overlay(2707): Nothing to do!

它显然尝试调整大小,但发现没有任何变化,也没有调用 onMesured 或 onLayout

我的代码:

public class VideoSurface extends ViewGroup {
private final String TAG = "VideoSurface";
protected  int mWidth = 0 ;
protected  int mHeight = 0 ;
protected SurfaceView mSurfaceView;
protected SurfaceHolder mHolder;

public VideoSurface(Context context) {
    super(context);
    init(context);
}
public VideoSurface(Context context, AttributeSet attrs) {
    super(context,attrs);
    init(context);
}
public VideoSurface(Context context, AttributeSet attrs, int defStyle) {
    super(context,attrs,defStyle);
    init(context);
}


private void init(Context context){
    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mSurfaceView = new SurfaceView(context);
    this.addView(mSurfaceView);

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder=mSurfaceView.getHolder() ;
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public Surface getSurface(){return mHolder.getSurface();}
public void setSize(Size size){
    mWidth = size.width ;
    mHeight = size.height ;
}
public void setSize(int w,int h){
    mWidth = w ;
    mHeight = h ;
}

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // We purposely disregard child measurements because act as a
    // wrapper to a SurfaceView that centers the camera preview instead
    // of stretching it.
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    setMeasuredDimension(width, height);
    Log.d(TAG,"onMeasure:"+width+"x"+height);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if (changed && getChildCount() > 0) {
        final View child = getChildAt(0);

        final int width = r - l;
        final int height = b - t;

        int previewWidth = width;
        int previewHeight = height;
        if ((mWidth != 0)&&(mHeight != 0)) {
            previewWidth = mWidth;
            previewHeight = mHeight;
        }
        Log.d(TAG,"onLayout L1: Desired:"+mWidth+"x"+mHeight+" Actual:"+previewWidth+"x"+previewHeight);

        // Center the child SurfaceView within the parent.
        if (width * previewHeight > height * previewWidth) {
            final int scaledChildWidth = previewWidth * height / previewHeight;
            child.layout((width - scaledChildWidth) / 2, 0,
                    (width + scaledChildWidth) / 2, height);
        } else {
            final int scaledChildHeight = previewHeight * width / previewWidth;
            child.layout(0, (height - scaledChildHeight) / 2,
                    width, (height + scaledChildHeight) / 2);
        }
    }
    Log.d(TAG,"onLayout L2:"+l+", "+t+", "+r+", "+b);
}

继承类:

public class PlayerView extends VideoSurface implements SurfaceHolder.Callback {
private static final String TAG = "PlayerView";
private MediaPlayer mPlayer = new MediaPlayer() ;
private String mVideoPath = "" ;

public PlayerView(Context context) {
    super(context);
    init();
}
public PlayerView(Context context, AttributeSet attrs) {
    super(context,attrs);
    init();
}
public PlayerView(Context context, AttributeSet attrs, int defStyle) {
    super(context,attrs,defStyle);
    init();
}

private void init(){
    mHolder.addCallback(this);

    mPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener(){
        @Override
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
            //TODO
            mHolder.setFixedSize(width,height);
            setSize(width,height) ;
            setLayoutParams(new LayoutParams(width, height));
            requestLayout() ;
            forceLayout();
            Log.d(TAG,"Size:"+width+"x"+height);
        }
    });
    mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            // TODO 
            setSize(mPlayer.getVideoWidth(), mPlayer.getVideoHeight());
            mPlayer.start();
            Log.d(TAG,"Started");
        }
    });

    //TODO DEBUG
    mVideoPath = Environment.getExternalStorageDirectory().getPath()+"/external_sd/USB Storage/test.mp4" ;
}

private void prepareVideo(String path){
    stop() ;
    try {
        mPlayer.setDataSource(path) ;
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    //TODO
    //mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

    mPlayer.prepareAsync() ;
}

public void start(String path) {
    mVideoPath = path ;
    if (!mHolder.isCreating()){
        prepareVideo(path) ;
    }
}

public void stop() {
    if (mPlayer.isPlaying()) {
        mPlayer.stop();
    }
    mPlayer.reset();
}

public void onStop(){
    stop() ;
    mPlayer.release();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mPlayer.setDisplay(mHolder);
    if(!mVideoPath.isEmpty()){
        prepareVideo(mVideoPath) ;
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}

即使 forceLayout() 不起作用,我如何强制执行 requestLayout()?

最佳答案

您可以使用requestLayout(); 来强制您的布局重绘,所以您需要调用

yourLayout.requestLayout(); 在你的 init() 上。

关于android - 即使 forceLayout() 不起作用,我如何强制 requestLayout()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12182231/

相关文章:

android - 调整 SwipeRefreshLayout 高度以将 View 置于其底部

android - 使用三星默认媒体播放器的媒体按钮广播

java - 在 Android 上播放声音

java - 在 Java 中将方法作为参数传递以将监听器分配给多个按钮

android - 如何在没有新的可运行线程的情况下使用 HTTPPost

android - child 在父 View 外不可点击

Android webview 非常奇怪的行为

android - 如何为包含的布局设置权重?

android - 如何在后台播放广播应用程序并在通知栏上显示小部件?

android - android 上函数的图形库