如何在多个Fragment中复用布局及Java代码并自定义点击逻辑
实现方案
核心思路
抽象出公共基类Fragment,将所有公用布局、公共控件初始化、通用按钮点击逻辑全部封装在基类中,仅将差异化的按钮点击逻辑定义为抽象方法,由两个子Fragment各自实现。基类中所有控件成员声明为protected权限,子类实现独有方法时可直接访问所有View。
步骤1:实现抽象基类Fragment
import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; // 抽象基类 public abstract class BaseCommonFragment extends Fragment { // 所有控件声明为protected,子类可直接访问 protected TextView commonTv; protected Button commonBtn1; protected Button commonBtn2; protected Button differBtn; // 差异化点击的按钮 @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // 加载公用布局,即你现有两个Fragment共用的布局,两个子类无需重复加载布局 return inflater.inflate(R.layout.fragment_common, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 基类统一初始化所有控件 initViews(view); // 绑定通用按钮的点击事件 initCommonClickListeners(); // 绑定差异化按钮的点击事件,回调子类实现的方法 differBtn.setOnClickListener(v -> onDifferButtonClick(v)); } private void initViews(View rootView) { commonTv = rootView.findViewById(R.id.common_tv); commonBtn1 = rootView.findViewById(R.id.btn_common1); commonBtn2 = rootView.findViewById(R.id.btn_common2); differBtn = rootView.findViewById(R.id.btn_differ); } private void initCommonClickListeners() { // 所有通用按钮的逻辑统一写在基类,子类无需重复实现 commonBtn1.setOnClickListener(v -> { // 公共逻辑,比如跳转、通用弹窗等 }); commonBtn2.setOnClickListener(v -> { // 公共逻辑 }); } // 抽象方法,子类必须实现,用来写差异化的点击逻辑 protected abstract void onDifferButtonClick(View view); }
步骤2:实现两个子Fragment
仅需要继承基类,实现抽象方法即可,无需重复写布局加载、控件初始化、公共按钮逻辑:
第一个子Fragment
public class FirstFragment extends BaseCommonFragment { @Override protected void onDifferButtonClick(View view) { // 第一个Fragment独有的逻辑,可直接访问基类的所有protected成员 commonTv.setText("第一个Fragment的差异化按钮被点击"); // 其他独有逻辑 } }
第二个子Fragment
public class SecondFragment extends BaseCommonFragment { @Override protected void onDifferButtonClick(View view) { // 第二个Fragment独有的逻辑,可直接访问基类的所有protected成员 commonTv.setText("第二个Fragment的差异化按钮被点击"); // 其他独有逻辑 } }
步骤3:正常使用Fragment
在Navigation Drawer的切换逻辑中直接实例化对应子Fragment即可,和原有使用方式完全兼容:
// 切换到第一个Fragment示例 getSupportFragmentManager().beginTransaction() .replace(R.id.nav_host_fragment, new FirstFragment()) .commit(); // 切换到第二个Fragment示例 getSupportFragmentManager().beginTransaction() .replace(R.id.nav_host_fragment, new SecondFragment()) .commit();
方案优势
- 布局仅需维护1份,修改公共布局无需同步多份文件
- 公共逻辑全部收敛到基类,后续修改通用行为仅需调整基类代码
- 子类仅需要实现差异化逻辑,代码冗余度极低,符合开闭原则
- 基类控件声明为
protected,子类独有方法可直接访问所有View,无需额外传参或绑定
内容的提问来源于stack exchange,提问作者Moises
相关产品推荐
相关产品推荐

