Skip to content

Commit

Permalink
Refactor back press processing
Browse files Browse the repository at this point in the history
  • Loading branch information
andreynovikov committed Dec 21, 2023
1 parent d9732d1 commit f89f860
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 213 deletions.
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,15 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test:rules:1.5.0'
implementation "androidx.fragment:fragment:1.6.2"
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation "androidx.preference:preference:1.2.1"
implementation "androidx.work:work-runtime:2.9.0"
implementation 'androidx.core:core-splashscreen:1.0.1'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'androidx.annotation:annotation:1.7.0'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.annotation:annotation:1.7.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'com.github.andreynovikov:androidcolorpicker:v0.0.3'
implementation 'com.github.andreynovikov:Geo-Coordinate-Conversion-Java:v1.0.0'
implementation 'com.caverock:androidsvg:1.4'
Expand Down
221 changes: 127 additions & 94 deletions app/src/main/java/mobi/maptrek/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import android.os.Message;
import android.os.SystemClock;

import androidx.activity.result.ActivityResultCallback;
import androidx.activity.OnBackPressedCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.DrawableRes;
Expand Down Expand Up @@ -194,7 +194,6 @@
import mobi.maptrek.fragments.MapList;
import mobi.maptrek.fragments.MapSelection;
import mobi.maptrek.fragments.MarkerInformation;
import mobi.maptrek.fragments.OnBackPressedListener;
import mobi.maptrek.fragments.OnFeatureActionListener;
import mobi.maptrek.fragments.OnLocationListener;
import mobi.maptrek.fragments.OnMapActionListener;
Expand Down Expand Up @@ -279,7 +278,6 @@ public class MainActivity extends AppCompatActivity implements ILocationListener
MapTrekTileLayer.OnAmenityGestureListener,
PopupMenu.OnMenuItemClickListener,
LoaderManager.LoaderCallbacks<List<FileDataSource>>,
FragmentManager.OnBackStackChangedListener,
AmenitySetupDialog.AmenitySetupDialogCallback, SafeResultReceiver.Callback {
private static final Logger logger = LoggerFactory.getLogger(MainActivity.class);

Expand Down Expand Up @@ -472,7 +470,7 @@ protected void onCreate(Bundle savedInstanceState) {

// find the retained fragment on activity restarts
mFragmentManager = getSupportFragmentManager();
mFragmentManager.addOnBackStackChangedListener(this);
mFragmentManager.registerFragmentLifecycleCallbacks(mFragmentLifecycleCallback, true);

mNativeMapIndex = application.getMapIndex();
mMapIndex = application.getExtraMapIndex();
Expand Down Expand Up @@ -907,6 +905,8 @@ protected void onStart() {
resultReceiver.setCallback(this);
mResultReceiver = new WeakReference<>(resultReceiver);

getOnBackPressedDispatcher().addCallback(this, mBackPressedCallback);
mBackPressedCallback.setEnabled(mFragmentManager.getBackStackEntryCount() == 0);
MapTrek.isMainActivityRunning = true;
}

Expand Down Expand Up @@ -1037,6 +1037,7 @@ protected void onStop() {
logger.debug("onStop()");

MapTrek.isMainActivityRunning = false;
mBackPressedCallback.remove();

mResultReceiver.get().setCallback(null);

Expand Down Expand Up @@ -1134,6 +1135,7 @@ public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
savedInstanceState.putInt("progressBar", mViews.progressBar.getMax());
savedInstanceState.putSerializable("panelState", mPanelState);
savedInstanceState.putBoolean("autoTiltShouldSet", mAutoTiltShouldSet);
savedInstanceState.putBoolean("baseMapWarningShown", mBaseMapWarningShown);
super.onSaveInstanceState(savedInstanceState);
}

Expand All @@ -1153,6 +1155,7 @@ public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
mViews.progressBar.setMax(savedInstanceState.getInt("progressBar"));
}
mAutoTiltShouldSet = savedInstanceState.getBoolean("autoTiltShouldSet");
mBaseMapWarningShown = savedInstanceState.getBoolean("baseMapWarningShown");
setPanelState((PANEL_STATE) savedInstanceState.getSerializable("panelState"));
}

Expand Down Expand Up @@ -1347,7 +1350,6 @@ public boolean onMenuItemClick(MenuItem item) {
ft.replace(R.id.contentPanel, fragment, "ruler");
ft.addToBackStack("ruler");
ft.commit();
mCrosshairLayer.lock(Color.RED);
return true;
} else if (action == R.id.actionAddGauge) {
mViews.gaugePanel.onLongClick(mViews.gaugePanel);
Expand Down Expand Up @@ -3460,10 +3462,8 @@ private void showExtendPanel(PANEL_STATE panel, String name, Fragment fragment)
FragmentManager.BackStackEntry bse = mFragmentManager.getBackStackEntryAt(0);
//TODO Make it properly work without "immediate" - that is why exit transitions do not work
mFragmentManager.popBackStackImmediate(bse.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (name.equals(bse.getName())) {
setPanelState(PANEL_STATE.NONE);
if (name.equals(bse.getName()))
return;
}
}
mViews.extendPanel.setForeground(null);

Expand Down Expand Up @@ -3589,8 +3589,6 @@ private void setPanelState(PANEL_STATE state) {
mPanelState = state;
}

private final Set<WeakReference<OnBackPressedListener>> mBackListeners = new HashSet<>();

@Override
public FloatingActionButton enableActionButton() {
if (mViews.listActionButton.getVisibility() == View.VISIBLE)
Expand Down Expand Up @@ -3619,37 +3617,9 @@ public void disableListActionButton() {
mViews.listActionButton.setVisibility(View.GONE);
}

@Override
public void addBackClickListener(OnBackPressedListener listener) {
mBackListeners.add(new WeakReference<>(listener));
}

@Override
public void removeBackClickListener(OnBackPressedListener listener) {
for (Iterator<WeakReference<OnBackPressedListener>> iterator = mBackListeners.iterator();
iterator.hasNext(); ) {
WeakReference<OnBackPressedListener> weakRef = iterator.next();
if (weakRef.get() == listener) {
iterator.remove();
}
}
}

@Override
public void popCurrent() {
logger.debug("popCurrent()");
int count = mFragmentManager.getBackStackEntryCount();
if (count > 0) {
FragmentManager.BackStackEntry bse = mFragmentManager.getBackStackEntryAt(count - 1);
String fragmentName = bse.getName();
if ("baseMapDownload".equals(fragmentName)) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
HelperUtils.showTargetedAdvice(MainActivity.this, Configuration.ADVICE_ENABLE_LOCATIONS, R.string.advice_enable_locations, mViews.locationButton, false);
}
} else if ("trackProperties".equals(fragmentName)) {
HelperUtils.showTargetedAdvice(this, Configuration.ADVICE_RECORDED_TRACKS, R.string.advice_recorded_tracks, mViews.recordButton, false);
}
}
mFragmentManager.popBackStack();
}

Expand All @@ -3665,73 +3635,98 @@ public CoordinatorLayout getCoordinatorLayout() {
return mViews.coordinatorLayout;
}

private boolean backKeyIntercepted() {
boolean intercepted = false;
for (WeakReference<OnBackPressedListener> weakRef : mBackListeners) {
OnBackPressedListener onBackClickListener = weakRef.get();
if (onBackClickListener != null) {
boolean isFragIntercept = onBackClickListener.onBackClick();
if (!intercepted)
intercepted = isFragIntercept;
}
}
return intercepted;
}
private final OnBackPressedCallback mBackPressedCallback = new OnBackPressedCallback(false) {
final Handler mBackHandler = new Handler();

final Handler mBackHandler = new Handler();

@Override
public void onBackPressed() {
logger.debug("onBackPressed()");
if (backKeyIntercepted())
return;

int count = mFragmentManager.getBackStackEntryCount();
if (count > 0) {
FragmentManager.BackStackEntry bse = mFragmentManager.getBackStackEntryAt(count - 1);
String name = bse.getName();
if ("ruler".equals(name))
mCrosshairLayer.unlock();
else if ("settings".equals(name))
HelperUtils.showTargetedAdvice(this, Configuration.ADVICE_MAP_SETTINGS, R.string.advice_map_settings, mViews.mapsButton, false);
else if ("trackProperties".equals(name))
HelperUtils.showTargetedAdvice(this, Configuration.ADVICE_RECORDED_TRACKS, R.string.advice_recorded_tracks, mViews.recordButton, false);
super.onBackPressed();
if (count == 1 && mPanelState != PANEL_STATE.NONE)
setPanelState(PANEL_STATE.NONE);
} else {
@Override
public void handleOnBackPressed() {
if (secondBack) {
mBackToast.cancel();
finish();
this.setEnabled(false);
getOnBackPressedDispatcher().onBackPressed();
} else {
secondBack = true;
mBackToast.show();
mBackHandler.postDelayed(() -> secondBack = false, 2000);
}
}
}
};

@SuppressLint("UseCompatLoadingForDrawables")
@Override
public void onBackStackChanged() {
logger.debug("onBackStackChanged()");
int count = mFragmentManager.getBackStackEntryCount();
if (count == 0) {
if (mPanelState != PANEL_STATE.NONE)
private final FragmentManager.FragmentLifecycleCallbacks mFragmentLifecycleCallback = new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentPreAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
logger.error("onFragmentPreAttached({})", f.getClass().getName());
}

@Override
public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
logger.error("onFragmentAttached({})", f.getClass().getName());
mBackPressedCallback.setEnabled(false);
}

@Override
public void onFragmentPreCreated(@NonNull FragmentManager fm, @NonNull Fragment f, @Nullable Bundle savedInstanceState) {
logger.error("onFragmentPreCreated({})", f.getClass().getName());
}

@Override
public void onFragmentCreated(@NonNull FragmentManager fm, @NonNull Fragment f, @Nullable Bundle savedInstanceState) {
logger.error("onFragmentCreated({})", f.getClass().getName());
}

@Override
public void onFragmentViewCreated(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull View v, @Nullable Bundle savedInstanceState) {
logger.error("onFragmentViewCreated({})", f.getClass().getName());
}

@Override
public void onFragmentStarted(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentStarted({})", f.getClass().getName());
}

@Override
public void onFragmentResumed(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentResumed({})", f.getClass().getName());
if (f.getClass() == Ruler.class)
mCrosshairLayer.lock(Color.RED);
}

@Override
public void onFragmentPaused(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentPaused({})", f.getClass().getName());
if (f.getClass() == Ruler.class)
mCrosshairLayer.unlock();
}

@Override
public void onFragmentStopped(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentStopped({})", f.getClass().getName());
if (mFragmentManager.getBackStackEntryCount() == 0 && mPanelState != PANEL_STATE.NONE)
setPanelState(PANEL_STATE.NONE);
return;
}
FragmentManager.BackStackEntry bse = mFragmentManager.getBackStackEntryAt(count - 1);
Fragment f = mFragmentManager.findFragmentByTag(bse.getName());
if (f == null)
return;
View v = f.getView();
if (v == null)
return;
final ViewGroup p = (ViewGroup) v.getParent();
if (p.getForeground() != null) {
p.setForeground(getDrawable(R.drawable.dim));
p.getForeground().setAlpha(0);

@Override
public void onFragmentSaveInstanceState(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Bundle outState) {
logger.error("onFragmentSaveInstanceState({})", f.getClass().getName());
}

@Override
public void onFragmentViewDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentViewDestroyed({})", f.getClass().getName());

int count = mFragmentManager.getBackStackEntryCount();
if (count == 0)
return;
FragmentManager.BackStackEntry bse = mFragmentManager.getBackStackEntryAt(count - 1);
Fragment fr = mFragmentManager.findFragmentByTag(bse.getName());
if (fr == null)
return;
View fv = fr.getView();
if (fv == null)
return;
final ViewGroup p = (ViewGroup) fv.getParent();
if (p == null || p.getForeground() == null)
return;
ObjectAnimator anim = ObjectAnimator.ofInt(p.getForeground(), "alpha", 255, 0);
anim.addListener(new Animator.AnimatorListener() {
@Override
Expand All @@ -3755,7 +3750,45 @@ public void onAnimationRepeat(@NonNull Animator animation) {
anim.setDuration(500);
anim.start();
}
}

@Override
public void onFragmentDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentDestroyed({})", f.getClass().getName());
}

@Override
public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
logger.error("onFragmentDetached({})", f.getClass().getName());
mBackPressedCallback.setEnabled(mFragmentManager.getBackStackEntryCount() == 0);

Class<? extends Fragment> cls = f.getClass();
if (cls == BaseMapDownload.class) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
HelperUtils.showTargetedAdvice(
MainActivity.this,
Configuration.ADVICE_ENABLE_LOCATIONS,
R.string.advice_enable_locations,
mViews.locationButton,
false
);
} else if (cls == Settings.class)
HelperUtils.showTargetedAdvice(
MainActivity.this,
Configuration.ADVICE_MAP_SETTINGS,
R.string.advice_map_settings,
mViews.mapsButton,
false
);
else if (cls == TrackProperties.class)
HelperUtils.showTargetedAdvice(
MainActivity.this,
Configuration.ADVICE_RECORDED_TRACKS,
R.string.advice_recorded_tracks,
mViews.recordButton,
false
);
}
};

private void hideDownloadButton() {
if (mViews.mapDownloadButton.getVisibility() == View.VISIBLE) {
Expand Down
Loading

0 comments on commit f89f860

Please sign in to comment.