针对 API 14-17、17-30、30+ 的不同屏幕尺寸调整布局
Adjusting layouts for different screen sizes for API 14-17, 17-30, 30+
编辑 2021 年 5 月 9 日:
一般来说,我想通过调整 onCreate()
中的一些几何值来根据智能手机的显示尺寸以编程方式调整某些按钮的 LayoutParams
。显然不是那么简单。
终于找到了一种解决方法,可能 在 API 14-17、17-30、30+ 之间工作。
我的目标是为 14-30 岁以上的所有 API 确定没有插图/导航栏元素的“实际屏幕尺寸”。
我仍然需要为 < API 17 调整方法,因为在这种情况下可能还没有扣除导航栏元素(我目前正在尝试确定这些用例的导航栏大小) .
屏幕尺寸查询(宽、高):
//++++++++++++++ DISPLAY SIZES +++++++++++++
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
int realDisplayWidth;
int realDisplayHeight;
//++++++++++++++ GET HORIZONTAL SCREENSIZE +++++++++
public int getRealScreenWidth(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// TARGETING BUILDVERSIONS GREATER EQUAL API:30
WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
// HORIZONTAL DISPLAY SIZE INCLUDING INSETS
WindowInsets windowInsets = windowMetrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;
// GET THE SIZE OF HORIZONTAL INSETS
Rect bounds = windowMetrics.getBounds();
realDisplayWidth = bounds.width() - insetsWidth;
// HORIZONTAL SCREEN SIZE WITHOUT INSETS
return realDisplayWidth;
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// TARGETING BUILDVERSIONS ABOVE API:17, UNTIL API:30
Display display = this.getWindowManager().getDefaultDisplay();
display.getRealMetrics(realDisplayMetrics);
realDisplayWidth = realDisplayMetrics.widthPixels;
return realDisplayWidth;
}
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
//REFLECTION FOR BUILDVERSIONs ABOVE API:14 UNTIL API:17
Display display = this.getWindowManager().getDefaultDisplay();
try {
Method getHorizontalSize = Display.class.getMethod("getWidth");
realDisplayWidth = (Integer) getHorizontalSize.invoke(display);
} catch (Exception e) {
realDisplayWidth = 1000;
}
return realDisplayWidth;
}
else {
return realDisplayWidth = 1000;
}
}
//++++++++++++++ GET VERTICAL SCREENSIZE +++++++++
public int getRealScreenHeight(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// TARGETING BUILDVERSIONS GREATER EQUAL API:30
WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
// VERTICAL DISPLAY SIZE INCLUDING INSETS
WindowInsets windowInsets = windowMetrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
int insetsHeight = insets.top + insets.bottom;
// GET THE SIZE OF VERTICAL INSETS
Rect bounds = windowMetrics.getBounds();
realDisplayHeight = bounds.height() - insetsHeight;
// HORIZONTAL SCREEN SIZE WITHOUT INSETS
return realDisplayHeight;
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// TARGETING BUILDVERSIONS ABOVE API:17, UNTIL API:30
Display display = this.getWindowManager().getDefaultDisplay();
display.getRealMetrics(realDisplayMetrics);
realDisplayHeight = realDisplayMetrics.heightPixels;
return realDisplayHeight;
}
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
//REFLECTION FOR BUILDVERSIONs ABOVE API:14 UNTIL API:17
Display display = this.getWindowManager().getDefaultDisplay();
try {
Method getVerticalSize = Display.class.getMethod("getHeight");
realDisplayHeight = (Integer) getVerticalSize.invoke(display);
} catch (Exception e) {
realDisplayHeight = 1500;
}
return realDisplayHeight;
}
else {
return realDisplayHeight = 1500;
}
}
public void getLog(){
Log.i("screenWide:", String.valueOf(getRealScreenWidth()));
Log.i("screenHeight:", String.valueOf(getRealScreenHeight()));
}
更改布局参数:
//++++++++++++++ EXAMPLE METHOD FOR CHANGING PARAMS IN ONCREATE() ++++++++++
public void changingLayoutParams(){
// EXAMPLE FOR CHANGING HORIZONTAL LAYOUT PARAMS FOR API ABOVE 17:
Button number1 = (Button) findViewById(R.id.number1);
Button sidebar_v_1 = (Button) findViewById(R.id.sidebar_v_1);
if (getRealScreenWidth() >= 1000){
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) number1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params.setMarginStart((int) getResources().getDimension(R.dimen.levelSymbolLeftMargin));
params.setMargins(params.getMarginStart(), params.topMargin, params.getMarginEnd(), params.bottomMargin);
}
ViewGroup.MarginLayoutParams params2 = (ViewGroup.MarginLayoutParams) sidebar_v_1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.setMarginStart((int) getResources().getDimension(R.dimen.levelSymbolLeftMargin));
params2.setMargins(params2.getMarginStart(), params2.topMargin, params2.getMarginEnd(), params2.bottomMargin);
}
}
else if (getRealScreenWidth() < 1000){
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) number1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params.setMarginStart((int) getResources().getDimension(R.dimen.lockerMarginLeft));
params.setMargins(params.getMarginStart(), params.topMargin, params.getMarginEnd(), params.bottomMargin);
}
ViewGroup.MarginLayoutParams params2 = (ViewGroup.MarginLayoutParams) sidebar_v_1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.setMarginStart((int) getResources().getDimension(R.dimen.lockerMarginLeft));
params2.setMargins(params2.getMarginStart(), params2.topMargin, params2.getMarginEnd(), params2.bottomMargin);
}
}
}
我构建了一个ConstraintLayout
,里面有几个嵌套布局,大致结构如下(减少了里面的元素数量):
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/outerBlock"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="@dimen/nestedScroll_mR"
android:layout_marginEnd="@dimen/nestedScroll_mR"
android:layout_marginLeft="@dimen/nestedScroll_mL"
android:layout_marginStart="@dimen/nestedScroll_mL"
android:layout_marginTop="@dimen/nestedScroll_mT"
android:layout_marginBottom="@dimen/nestedScroll_mB"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerBlock0"
android:layout_width="match_parent"
android:layout_height="@dimen/firstInnerBlockH"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerBlock1"
android:layout_width="match_parent"
android:layout_height="@dimen/innerBlockH"
app:layout_constraintTop_toBottomOf="@id/innerBlock0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent">
<Button
android:id="@+id/number1"
android:layout_width="@dimen/levelSymbol"
android:layout_height="@dimen/levelSymbol"
android:background="@drawable/number1"
android:layout_marginTop="@dimen/numberMarginTop"
android:layout_marginLeft="@dimen/numberMarginLeft"
android:layout_marginStart="@dimen/numberMarginLeft"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/sidebar_v_1"
android:layout_width="@dimen/sidebarVWidth"
android:layout_height="@dimen/sidebarVHeight"
android:background="@drawable/side_v"
android:layout_marginLeft="@dimen/sideMarginLeft"
android:layout_marginStart="@dimen/sideMarginLeft"
app:layout_constraintTop_toBottomOf="@id/number1"
app:layout_constraintLeft_toLeftOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerBlock2"
android:layout_width="match_parent"
android:layout_height="@dimen/innerBlockH"
app:layout_constraintTop_toBottomOf="@id/innerBlock1">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
通过更改 marginLeft
和 marginStart
LayoutParam
布局将更好地适应显示。一开始我只是为1个屏幕尺寸设计的。
我注意到您正试图在 onCreate() 中更改 2 个按钮的边距值。这与更改 activity_main.xml 文件中的边距值具有相同的效果。
如果您尝试执行其他操作,例如,在单击按钮时更改这些值,您只需将 onClickListener 设置为另一个按钮,然后将此代码放入该 onClick 侦听器中。希望这可以帮助。谢谢。
编辑 2021 年 5 月 9 日:
一般来说,我想通过调整 onCreate()
中的一些几何值来根据智能手机的显示尺寸以编程方式调整某些按钮的 LayoutParams
。显然不是那么简单。
终于找到了一种解决方法,可能 在 API 14-17、17-30、30+ 之间工作。
我的目标是为 14-30 岁以上的所有 API 确定没有插图/导航栏元素的“实际屏幕尺寸”。
我仍然需要为 < API 17 调整方法,因为在这种情况下可能还没有扣除导航栏元素(我目前正在尝试确定这些用例的导航栏大小) .
屏幕尺寸查询(宽、高):
//++++++++++++++ DISPLAY SIZES +++++++++++++
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
int realDisplayWidth;
int realDisplayHeight;
//++++++++++++++ GET HORIZONTAL SCREENSIZE +++++++++
public int getRealScreenWidth(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// TARGETING BUILDVERSIONS GREATER EQUAL API:30
WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
// HORIZONTAL DISPLAY SIZE INCLUDING INSETS
WindowInsets windowInsets = windowMetrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;
// GET THE SIZE OF HORIZONTAL INSETS
Rect bounds = windowMetrics.getBounds();
realDisplayWidth = bounds.width() - insetsWidth;
// HORIZONTAL SCREEN SIZE WITHOUT INSETS
return realDisplayWidth;
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// TARGETING BUILDVERSIONS ABOVE API:17, UNTIL API:30
Display display = this.getWindowManager().getDefaultDisplay();
display.getRealMetrics(realDisplayMetrics);
realDisplayWidth = realDisplayMetrics.widthPixels;
return realDisplayWidth;
}
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
//REFLECTION FOR BUILDVERSIONs ABOVE API:14 UNTIL API:17
Display display = this.getWindowManager().getDefaultDisplay();
try {
Method getHorizontalSize = Display.class.getMethod("getWidth");
realDisplayWidth = (Integer) getHorizontalSize.invoke(display);
} catch (Exception e) {
realDisplayWidth = 1000;
}
return realDisplayWidth;
}
else {
return realDisplayWidth = 1000;
}
}
//++++++++++++++ GET VERTICAL SCREENSIZE +++++++++
public int getRealScreenHeight(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// TARGETING BUILDVERSIONS GREATER EQUAL API:30
WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
// VERTICAL DISPLAY SIZE INCLUDING INSETS
WindowInsets windowInsets = windowMetrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
int insetsHeight = insets.top + insets.bottom;
// GET THE SIZE OF VERTICAL INSETS
Rect bounds = windowMetrics.getBounds();
realDisplayHeight = bounds.height() - insetsHeight;
// HORIZONTAL SCREEN SIZE WITHOUT INSETS
return realDisplayHeight;
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// TARGETING BUILDVERSIONS ABOVE API:17, UNTIL API:30
Display display = this.getWindowManager().getDefaultDisplay();
display.getRealMetrics(realDisplayMetrics);
realDisplayHeight = realDisplayMetrics.heightPixels;
return realDisplayHeight;
}
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
//REFLECTION FOR BUILDVERSIONs ABOVE API:14 UNTIL API:17
Display display = this.getWindowManager().getDefaultDisplay();
try {
Method getVerticalSize = Display.class.getMethod("getHeight");
realDisplayHeight = (Integer) getVerticalSize.invoke(display);
} catch (Exception e) {
realDisplayHeight = 1500;
}
return realDisplayHeight;
}
else {
return realDisplayHeight = 1500;
}
}
public void getLog(){
Log.i("screenWide:", String.valueOf(getRealScreenWidth()));
Log.i("screenHeight:", String.valueOf(getRealScreenHeight()));
}
更改布局参数:
//++++++++++++++ EXAMPLE METHOD FOR CHANGING PARAMS IN ONCREATE() ++++++++++
public void changingLayoutParams(){
// EXAMPLE FOR CHANGING HORIZONTAL LAYOUT PARAMS FOR API ABOVE 17:
Button number1 = (Button) findViewById(R.id.number1);
Button sidebar_v_1 = (Button) findViewById(R.id.sidebar_v_1);
if (getRealScreenWidth() >= 1000){
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) number1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params.setMarginStart((int) getResources().getDimension(R.dimen.levelSymbolLeftMargin));
params.setMargins(params.getMarginStart(), params.topMargin, params.getMarginEnd(), params.bottomMargin);
}
ViewGroup.MarginLayoutParams params2 = (ViewGroup.MarginLayoutParams) sidebar_v_1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.setMarginStart((int) getResources().getDimension(R.dimen.levelSymbolLeftMargin));
params2.setMargins(params2.getMarginStart(), params2.topMargin, params2.getMarginEnd(), params2.bottomMargin);
}
}
else if (getRealScreenWidth() < 1000){
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) number1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params.setMarginStart((int) getResources().getDimension(R.dimen.lockerMarginLeft));
params.setMargins(params.getMarginStart(), params.topMargin, params.getMarginEnd(), params.bottomMargin);
}
ViewGroup.MarginLayoutParams params2 = (ViewGroup.MarginLayoutParams) sidebar_v_1.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.setMarginStart((int) getResources().getDimension(R.dimen.lockerMarginLeft));
params2.setMargins(params2.getMarginStart(), params2.topMargin, params2.getMarginEnd(), params2.bottomMargin);
}
}
}
我构建了一个ConstraintLayout
,里面有几个嵌套布局,大致结构如下(减少了里面的元素数量):
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/outerBlock"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="@dimen/nestedScroll_mR"
android:layout_marginEnd="@dimen/nestedScroll_mR"
android:layout_marginLeft="@dimen/nestedScroll_mL"
android:layout_marginStart="@dimen/nestedScroll_mL"
android:layout_marginTop="@dimen/nestedScroll_mT"
android:layout_marginBottom="@dimen/nestedScroll_mB"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerBlock0"
android:layout_width="match_parent"
android:layout_height="@dimen/firstInnerBlockH"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerBlock1"
android:layout_width="match_parent"
android:layout_height="@dimen/innerBlockH"
app:layout_constraintTop_toBottomOf="@id/innerBlock0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent">
<Button
android:id="@+id/number1"
android:layout_width="@dimen/levelSymbol"
android:layout_height="@dimen/levelSymbol"
android:background="@drawable/number1"
android:layout_marginTop="@dimen/numberMarginTop"
android:layout_marginLeft="@dimen/numberMarginLeft"
android:layout_marginStart="@dimen/numberMarginLeft"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/sidebar_v_1"
android:layout_width="@dimen/sidebarVWidth"
android:layout_height="@dimen/sidebarVHeight"
android:background="@drawable/side_v"
android:layout_marginLeft="@dimen/sideMarginLeft"
android:layout_marginStart="@dimen/sideMarginLeft"
app:layout_constraintTop_toBottomOf="@id/number1"
app:layout_constraintLeft_toLeftOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerBlock2"
android:layout_width="match_parent"
android:layout_height="@dimen/innerBlockH"
app:layout_constraintTop_toBottomOf="@id/innerBlock1">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
通过更改 marginLeft
和 marginStart
LayoutParam
布局将更好地适应显示。一开始我只是为1个屏幕尺寸设计的。
我注意到您正试图在 onCreate() 中更改 2 个按钮的边距值。这与更改 activity_main.xml 文件中的边距值具有相同的效果。
如果您尝试执行其他操作,例如,在单击按钮时更改这些值,您只需将 onClickListener 设置为另一个按钮,然后将此代码放入该 onClick 侦听器中。希望这可以帮助。谢谢。