10

我想布局一个如下所示的视图,但我不知道如何去做:

  • 屏幕底部是一个常规视图,具有固定大小(填充宽度和一些高度的 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 对我没有帮助,因为直到屏幕部分布局并SomeOtherView放置后我才知道可用的屏幕尺寸。

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

“通货膨胀”是我在这里寻找的正确术语吗?我认为这与我正在寻找的内容有关,但我并不真正了解术语。

下面根据我的研究结果进行了更新,我认为可能是正确的解决方案。

4

4 回答 4

13

做了更多的研究,我想我知道我需要做什么:

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

我为完成这项工作所做的第二件事是将我MySurfaceView的 FrameLayout 内部作为唯一的孩子。我最初MySurfaceView在一个带有SomeOtherView来自我的图像的 RelativeLayout 中。RelativeLayout 的问题在于,它不会以允许我修复纵横比的方式协商宽度/高度。

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

一旦进入 FrameLayout,我就没有这个问题,因为传递给的 MeasureSpecsonMeasure只具有限制AT_MOST。这意味着我可以在每次通过 onMeasure 期间自由更改宽度和高度,因此我最终可以在给定可用区域的情况下根据需要计算我的纵横比。

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

于 2012-05-09T18:49:28.410 回答
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(); 

希望这可以帮助

于 2012-05-09T06:25:11.587 回答
1

随着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>

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

在此处输入图像描述

在此处输入图像描述

于 2017-09-25T16:28:19.500 回答
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>

希望能帮助你解决。

于 2012-05-09T06:46:34.277 回答