Android全局设置Activity内边距:避免重复代码实现边缘到边缘布局
统一实现Android边缘到边缘布局的几种方案
下面提供几种无需重复编写代码,让所有Activity自动应用边缘到边缘布局及内边距设置的方案:
方案一:抽象基类Activity(推荐)
创建一个基类Activity,把边缘到边缘的逻辑封装在其中,所有业务Activity继承这个基类即可。
public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 统一设置边缘到边缘 WindowCompat.setDecorFitsSystemWindows(getWindow(), false); } @Override public void setContentView(int layoutResID) { super.setContentView(layoutResID); // 获取根布局并设置Insets监听 View rootView = findViewById(android.R.id.content); applyWindowInsets(rootView); } @Override public void setContentView(View view) { super.setContentView(view); applyWindowInsets(view); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { super.setContentView(view, params); applyWindowInsets(view); } private void applyWindowInsets(View view) { ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); } return windowInsets; }); } }
之后你的业务Activity只需继承BaseActivity:
public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 其他业务逻辑... } }
方案二:全局Activity生命周期监听
通过Application.ActivityLifecycleCallbacks在全局监听所有Activity的创建事件,统一处理边缘到边缘布局。
首先在自定义Application中注册回调:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { // 统一设置边缘到边缘 WindowCompat.setDecorFitsSystemWindows(activity.getWindow(), false); // 延迟获取根布局,避免布局尚未加载完成 activity.getWindow().getDecorView().post(() -> { View rootView = activity.findViewById(android.R.id.content); applyWindowInsets(rootView); }); } private void applyWindowInsets(View view) { ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); } return windowInsets; }); } // 实现其他空方法 @Override public void onActivityStarted(@NonNull Activity activity) {} @Override public void onActivityResumed(@NonNull Activity activity) {} @Override public void onActivityPaused(@NonNull Activity activity) {} @Override public void onActivityStopped(@NonNull Activity activity) {} @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {} @Override public void onActivityDestroyed(@NonNull Activity activity) {} }); } }
记得在AndroidManifest.xml中配置自定义Application:
<application android:name=".MyApp" <!-- 其他配置 --> > <!-- Activity配置 --> </application>
方案三:自定义根布局
将Insets处理逻辑封装到自定义布局中,所有Activity的布局文件使用这个自定义布局作为根节点。
public class EdgeToEdgeLayout extends FrameLayout { public EdgeToEdgeLayout(@NonNull Context context) { super(context); init(); } public EdgeToEdgeLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public EdgeToEdgeLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { // 建议配合方案一或方案二统一设置WindowCompat.setDecorFitsSystemWindows,避免重复 ViewCompat.setOnApplyWindowInsetsListener(this, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); } return windowInsets; }); } }
然后在布局文件中使用:
<com.yourpackage.EdgeToEdgeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/activity_main"> <!-- 你的布局内容 --> </com.yourpackage.EdgeToEdgeLayout>
注意事项
- 如果部分Activity不需要应用该逻辑,可以在基类中添加开关方法,或者在全局回调中判断Activity类型跳过。
- 确保使用
WindowInsetsCompat相关API,兼容Android 10及以下版本。
内容的提问来源于stack exchange,提问作者Dynamic
相关产品推荐
相关产品推荐

