我创建了一个基础片段类,用于处理工具栏标题的设置,片段附加时的注册,菜单图标的设置以及其他一些操作。我的问题是我决定将PreferencesFragmentCompat用于我的设置片段,并且我无法同时扩展BaseFragment和android的PreferencesFragmentCompat。在这里使用接口无济于事,因为我的BaseFragment具有很多功能,并且我不想将其复制到我的每个片段类中。通常,要扩展两个类,您只需在两个单独的文件中执行此操作,但是由于两者都已经扩展了Android的Fragment类,因此我看不到这是怎么可能的。有更好的方法吗?
BaseFragment:
public abstract class BaseFragment extends Fragment {
protected View rootView;
protected AppSettings settings;
protected LayoutInflater inflater;
public static void startFragment(Activity activity, BaseFragment newFragment) {
FragmentManager fragManager = ((AppCompatActivity) activity).getSupportFragmentManager();
BaseFragment currentFragment = (BaseFragment) fragManager.findFragmentById(R.id.fragment_container);
// Start the transactions
FragmentTransaction transaction = fragManager.beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
// If there is already a fragment then we want it on the backstack
if (currentFragment != null) {
transaction.addToBackStack(null);
}
// Show it
transaction.commit();
}
@TargetApi(21)
private void lockMode(boolean start) {
if (android.os.Build.VERSION.SDK_INT >= 16) {
if (start) {
getActivity().startLockTask();
} else {
getActivity().stopLockTask();
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a reference to the app settings
settings = AppSettings.getInstance(getActivity());
// Don't want keyboard to stay open between fragments
hideKeyboard();
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
if (toolbarElevation()) {
actionBar.setElevation(4 * getActivity().getResources().getDisplayMetrics().density);
} else {
actionBar.setElevation(0);
}
}
setHasOptionsMenu(true);
}
@Override
public void onResume() {
super.onResume();
// Set the title up
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
toolbar.setTitle(getTitle());
// Enable the home button in the action bar
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayShowHomeEnabled(true);
// Change the home button icon for menu or back
if (showUpNavigation()) {
toolbar.setNavigationIcon(R.drawable.ic_navigation_back_white);
} else {
toolbar.setNavigationIcon(R.drawable.ic_menu_white);
}
if (isAppInLockTaskMode() == true && pinnedMode() == false) {
lockMode(false);
}
setDrawerMenu();
}
public boolean getAuthRequired() {
return true;
}
public boolean isBackAllowed() {
return true;
}
public boolean toolbarElevation() {
return true;
}
public String getTitle() {
return "ISOPED";
}
public boolean pinnedMode() {
return false;
}
public boolean showUpNavigation() {
return false;
}
public void hideKeyboard() {
InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
// check if no view has focus:
View v = getActivity().getCurrentFocus();
if (v == null) {
return;
}
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
public void setDrawerMenu() {
NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.drawer_navigation);
Integer menuID = null;
Integer currentMenuId = null;
if (settings.isType(AppSettings.TYPES.PERSONAL)) {
menuID = R.menu.drawer_personal;
} else if (settings.isType(AppSettings.TYPES.PROFESSIONAL)) {
if (getAuthRequired() == true) {
menuID = R.menu.drawer_professional_locked;
} else {
menuID = R.menu.drawer_professional_unlocked;
}
}
if (menuID != null) {
if (navigationView.getTag() != null) {
currentMenuId = (Integer) navigationView.getTag();
}
if (currentMenuId == null || navigationView.getMenu().size() == 0 || currentMenuId != menuID) {
navigationView.getMenu().clear();
navigationView.inflateMenu(menuID);
navigationView.setTag(Integer.valueOf(menuID));
}
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
if (settings.isType(AppSettings.TYPES.PROFESSIONAL) && pinnedMode() && false == isAppInLockTaskMode()) {
inflater.inflate(R.menu.pin_menu, menu);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
switch (item.getItemId()) {
case android.R.id.home:
if (showUpNavigation()) {
getActivity().onBackPressed();
} else {
drawer.openDrawer(GravityCompat.START);
}
return true;
case R.id.menu_pin:
if (isAppInLockTaskMode()) {
PinDialog dialog = new PinDialog((AppCompatActivity) getActivity(), new NavigationCallback((AppCompatActivity) getActivity()) {
@Override
public void run() {
lockMode(false);
}
});
dialog.show();
} else {
lockMode(true);
}
return true;
}
return super.onOptionsItemSelected(item);
}
private boolean isAppInLockTaskMode() {
ActivityManager activityManager;
activityManager = (ActivityManager)
getActivity().getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// For SDK version 23 and above.
return activityManager.getLockTaskModeState()
!= ActivityManager.LOCK_TASK_MODE_NONE;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// When SDK version >= 21. This API is deprecated in 23.
return activityManager.isInLockTaskMode();
}
return false;
}
}
最佳答案
这是一个很好的示例,您应在其中应用Joshua Bloch的"Favor composition over inheritance"习惯用法。
您可以将已应用于BaseFragment
的所有逻辑委托给某个类FragmentHelper
:
public class FragmentHelper {
private final Fragment fragment;
public FragmentHelper(Fragment fragment) {
this.fragment = fragment;
}
public void create(Bundle bundle) {
// `BaseFragment`'s code goes here
}
public void resume() {
// `BaseFragment`'s code goes here
}
...
}
现在在您的BaseFragment中:
public class BaseFragment {
private FragmentHelper fragmentHelper;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
fragmentHelper = new FragmentHelper(this);
fragmentHelper.create(savedInstanceState);
}
@Override
public void onResume() {
fragmentHelper.resume();
}
}
同样,这应应用于扩展
PreferenceFragment
的类。因此,您可以避免代码重复。
参考:
Joshua Bloch-有效的Java 2nd Edition,项目16。