使用固定宽高比surfaceview填充剩余空间

时间:2012-05-09 05:35:43

标签: android

我想布置一个如下所示的视图,但我不知道该怎么做:

  • 在屏幕的底部是一个常规视图,具有固定的大小(填充宽度和一些高度的dp)
  • 填充剩余的垂直空间,我想放置一个继承自glSurfaceView的自定义视图,其限制必须具有固定的宽高比,这将以编程方式设置,但在创建活动之前已知。 (在这种情况下假设它是2:3 w:h)。

这是我想象的一个小图片:

 .----------------------. 
 |   .--------------.   |  
 | b |              | b |  
 | g |              | g | 
 |   |              |   |  
 | i |  MySurface   | i | 
 | m |     View     | m | 
 | a |              | a | 
 | g |  (2:3 w:h)   | g | 
 | e |              | e | 
 |   *--------------*   | 
 |.--------------------.| 
 ||                    || 
 ||   SomeOtherView    || 
 ||                    || 
 |*--------------------*| 
 *----------------------* 

就设置MySurfaceView而言,我认为普通的layout_width和layout_height不会对我有所帮助,因为直到屏幕部分布局之后我才知道可用的屏幕尺寸,{{1}已被放置。

我想要覆盖SomeOtherView中的某些功能,例如将作为参数传递可用的屏幕空间,让我决定如何设置视图的宽度和高度?

'通货膨胀'是我正在寻找的正确名词吗?我认为这与我正在寻找的东西有关,但我真的不知道术语。

Updated below我的研究结果,我认为可能是正确的解决方案。

4 个答案:

答案 0 :(得分:13)

做了更多的研究,我想我想出了我需要做的事情:

我想要覆盖的函数是onMeasure(int widthSpec, int heightSpec),由父级调用,提供宽度和高度的建议(参见View.MeasureSpec)。我还将MySurfaceView设置为在xml中具有wrap_content的layout_width / height。然后,当调用onMeasure时,我可以计算可用的宽高比,并根据需要设置视图的宽度和高度。

我做的第二件事是将我的MySurfaceView放在FrameLayout中作为唯一的孩子。我最初在RelativeLayout中使用MySurfaceView并使用我的图片中的SomeOtherView。 RelativeLayout的问题在于它不会以允许我修复宽高比的方式协商宽度/高度。

onMeasure在测量过程中被多次调用,而RelativeLayout的工作方式是它首先询问自定义视图的宽度而不告诉它可用的高度,然后再回来询问高度,同时宽度将锁定为您在第一次传递(MeasureSpec.EXACTLY)中指定的宽度。这使得无法生成特定比率的视图,因为在知道可用高度之前必须确认宽度。

一旦进入FrameLayout,我就没有这个问题,因为传递给onMeasure的MeasureSpecs只有限制AT_MOST。这意味着我可以在onMeasure的每次传递过程中自由更改宽度和高度,因此我可以根据可用区域最终计算出我的宽高比。

尚未确认这适用于所有情况,但希望这会对某人有所帮助。

答案 1 :(得分:1)

要设置应使用的SurfaceView的大小:

    // Set surfaceview size in px
private void setVideoSize(int width, int height) {
    LayoutParams params = (LayoutParams) mYourSurfaceView.getLayoutParams();
    params.height = height;
    params.width = width;
    mYourSurfaceView.setLayoutParams(params);
}

如果你想知道屏幕的大小:

Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
int width = display.getWidth(); 
int heigth = display.getHeight(); 

希望这有帮助

答案 2 :(得分:0)

这将是我测试过的。

public class Test_stflowActivity extends Activity {
    SurfaceView sv = null;
    RelativeLayout rl = null;
    int current_width = 0;
    int current_height   = 0;
    boolean already_created = false;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        sv = (SurfaceView) findViewById(R.id.SurfaceView1);
        rl = (RelativeLayout) findViewById(R.id.relativeLayout3);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                current_height = rl.getHeight();
                while (current_height == 0) {
                    current_height = rl.getHeight();
                }
                current_width  = rl.getWidth();
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        update_surface(current_height, current_width);
                    }
                });
            }
        });
        thread.start();
        already_created = false;
    }

    void update_surface(int current_height,int current_width) {
        if (already_created == false){

            // CALCULATE ASPECTED RATIO ACCORDING TO ABOVE HEIGHT AND WIDTH.
            int calculated_height = current_height/2;
            int calculated_width = current_width /2;
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(calculated_height,
                                                                             calculated_width);
            lp.addRule(RelativeLayout.CENTER_IN_PARENT);
            sv.setLayoutParams(lp);
            sv.setVisibility(View.VISIBLE);
            already_created = true;
        }
        super.onResume();
    }
}

这是我创建的布局。

<RelativeLayout
    android:id="@+id/relativeLayout2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="87dp"
        android:text="Button" />

</RelativeLayout>





<RelativeLayout
    android:id="@+id/relativeLayout3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@+id/relativeLayout2"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true" >

    <android.view.SurfaceView
        android:id="@+id/SurfaceView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" android:layout_centerInParent="true" android:background="#ff0000" android:visibility="invisible"/>

</RelativeLayout>

希望帮助你解决。

答案 3 :(得分:0)

随着ConstraintLayout和布局编辑器的引入,处理比率变得更加容易。

请查看下面的XML代码段:

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/bckg" />

    <FrameLayout
        android:id="@+id/mySurfaceView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#99000000"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/someOtherView"
        app:layout_constraintDimensionRatio="W,2:3" />

    <FrameLayout
        android:id="@+id/someOtherView"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="#AAFFFFFF"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</android.support.constraint.ConstraintLayout>

这足以达到你要求的结果。请参见下面的屏幕截图:

enter image description here

enter image description here