用固定长宽比面视图填充剩余空间

我想布置一个像下面这样的视图,但我不知道如何去做这件事:

  • 在屏幕的底部是一个规则的视图,具有固定的大小(填充宽度和一些数字的高度dp)
  • 填充剩余的垂直空间,我想放置一个inheritance自glSurfaceView的自定义视图,限制它必须有一个固定的长宽比,它将以编程方式设置,但在创build活动之前已知。 (在这种情况下假设它是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中是否有一些我想重写的函数,例如将作为parameter passing可用的屏幕空间,让我决定如何设置视图的宽度和高度?

“通货膨胀”是我在这里寻找的合适期限吗? 我认为这与我正在寻找的东西有关,但我真的不知道这个术语。

下面更新我的研究结果,我认为一个可能的正确的解决scheme。

Solutions Collecting From Web of "用固定长宽比面视图填充剩余空间"

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

我想要重写的函数是onMeasure(int widthSpec, int heightSpec) ,父宽度和高度的build议调用(请参阅View.MeasureSpec )。 我还设置了MySurfaceView在xml中具有wrap_content的layout_width / height。 然后,当onMeasure被调用时,我可以计算可用的长宽比,并根据需要设置我的视图的宽度和高度。

我做的第二件事是把我的MySurfaceView放在一个FrameLayout中作为唯一的孩子。 我最初有MySurfaceView在我的图像与SomeOtherView RelativeLayout的MySurfaceView 。 RelativeLayout的问题是,它不会以允许我修改高宽比的方式来协商宽度/高度。

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

一旦进入FrameLayout,我没有这个问题,因为传递给onMeasure的MeasureSpecs只有AT_MOST的限制。 这意味着我可以随时更改宽度和高度,因此我可以根据需要计算我的高宽比。

还没有确认,这适用于所有情况,但希望这将有助于某人。

要设置你应该使用的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(); 

希望这可以帮助

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

这足以达到你所要求的结果。 查看下面的截图:

在这里输入图像说明

在这里输入图像说明

这将工作我testing。

 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(); } } 

这是我创build的布局。

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

希望能帮助你解决。