Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support predictive back design #857

Merged
merged 1 commit into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
android:theme="@style/Hydra.Material"
android:localeConfig="@xml/locales_config"
android:networkSecurityConfig="@xml/network_security_config"
android:enableOnBackInvokedCallback="true"
tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute"
tools:replace="android:supportsRtl">

Expand Down
90 changes: 35 additions & 55 deletions app/src/main/java/be/ugent/zeus/hydra/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.*;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.core.view.GravityCompat;
Expand Down Expand Up @@ -58,14 +59,15 @@
import be.ugent.zeus.hydra.resto.menu.RestoFragment;
import be.ugent.zeus.hydra.schamper.SchamperFragment;
import be.ugent.zeus.hydra.urgent.UrgentFragment;
import be.ugent.zeus.hydra.wpi.EnableManager;
import be.ugent.zeus.hydra.wpi.WpiActivity;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.shape.MaterialShapeDrawable;
import com.google.android.material.tabs.TabLayout;
import be.ugent.zeus.hydra.wpi.EnableManager;
import be.ugent.zeus.hydra.wpi.WpiActivity;
import dev.chrisbanes.insetter.Insetter;
import jonathanfinerty.once.Once;
import org.jetbrains.annotations.NotNull;

import static be.ugent.zeus.hydra.common.utils.FragmentUtils.requireArguments;

Expand Down Expand Up @@ -260,6 +262,37 @@ private void initialize(@Nullable Bundle savedInstanceState) {
// Register the listener for navigation events from the drawer.
binding.navigationView.setNavigationItemSelectedListener(this);

OnBackPressedCallback drawerCloser = new OnBackPressedCallback(false) {

@Override
public void handleOnBackPressed() {
binding.drawerLayout.closeDrawer(GravityCompat.START);
}
};
getOnBackPressedDispatcher().addCallback(this, drawerCloser);

binding.drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull @NotNull View drawerView, float slideOffset) {
// Do nothing.
}

@Override
public void onDrawerOpened(@NonNull @NotNull View drawerView) {
drawerCloser.setEnabled(true);
}

@Override
public void onDrawerClosed(@NonNull @NotNull View drawerView) {
drawerCloser.setEnabled(false);
}

@Override
public void onDrawerStateChanged(int newState) {
// Do nothing.
}
});

toggle = new ActionBarDrawerToggle(this, binding.drawerLayout, binding.toolbar, R.string.action_drawer_open, R.string.action_drawer_close) {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
Expand Down Expand Up @@ -498,44 +531,6 @@ private void setFragment(Fragment fragment, MenuItem menuItem, @NavigationSource
binding.progressBar.progressBar.setVisibility(View.GONE);
}

/**
* Implements the correct back-button behaviour for the drawer. If the drawer does not consume the back press,
* the parent method is called.
*/
@Override
public void onBackPressed() {
// If the drawer is open, close it.
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START);
return;
}

// The super method handles both the fragment back stack and finishing the activity. To know what was executed,
// we need to add a listener.
FragmentManager.OnBackStackChangedListener listener = () -> {
Fragment current = getSupportFragmentManager().findFragmentById(R.id.content);
Log.w(TAG, "onBackPressed: current fragment is somehow null? Ignoring update for now.");
if (current == null) {
return;
}
MenuItem item = binding.navigationView.getMenu().findItem(getFragmentMenuId(current));
updateDrawer(current, item);
};

// Allow the current fragment to intercept the back press.
Fragment current = getSupportFragmentManager().findFragmentById(R.id.content);
if (current instanceof OnBackPressed && (((OnBackPressed) current).onBackPressed())) {
// The fragment has handled it.
return;
}

// We need to listen to the back stack to update the drawer.
getSupportFragmentManager().addOnBackStackChangedListener(listener);
super.onBackPressed();
// The drawer has been updated, so we abandon the listener.
getSupportFragmentManager().removeOnBackStackChangedListener(listener);
}

/**
* Set the menu ID as argument for a fragment.
*
Expand Down Expand Up @@ -665,21 +660,6 @@ public interface ScheduledRemovalListener {
void onRemovalScheduled();
}

/**
* Allows fragments to listen to and intercept back button presses.
*/
@FunctionalInterface
public interface OnBackPressed {

/**
* Called when the back button is pressed. This function provides the fragment
* with an opportunity to intercept the back press.
*
* @return True if consumed, false otherwise. Consumed events are not propagated.
*/
boolean onBackPressed();
}

private static final class TutorialEndEvent implements Event {
@Nullable
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
Expand Down Expand Up @@ -68,7 +69,7 @@
* @author ellen
* @author Niko Strijbol
*/
public class EventFragment extends Fragment implements MainActivity.ScheduledRemovalListener, MainActivity.OnBackPressed {
public class EventFragment extends Fragment implements MainActivity.ScheduledRemovalListener {

private static final String TAG = "EventFragment";

Expand Down Expand Up @@ -194,6 +195,30 @@ protected void onSuccess(@NonNull AssociationRequest.EventItemsAndAssociations d
.setOnClickListener(v -> viewModel.onRefresh());
view.<Button>findViewById(R.id.events_no_data_button_filters)
.setOnClickListener(v -> showSheet());

var callback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
hideSheet();
}
};
var behavior = BottomSheetBehavior.from(bottomSheet);
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull @NotNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN || newState == BottomSheetBehavior.STATE_COLLAPSED) {
callback.setEnabled(false);
} else if (newState == BottomSheetBehavior.STATE_EXPANDED || newState == BottomSheetBehavior.STATE_HALF_EXPANDED) {
callback.setEnabled(true);
}
}

@Override
public void onSlide(@NonNull @NotNull View bottomSheet, float slideOffset) {
// Do nothing.
}
});
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), callback);
}

private void setupBottomSheet() {
Expand Down Expand Up @@ -262,14 +287,4 @@ private void hideSheet() {
private void showSheet() {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}

@Override
public boolean onBackPressed() {
if (behavior.getState() != BottomSheetBehavior.STATE_HIDDEN) {
Log.d(TAG, "onBackPressed: hiding sheet");
hideSheet();
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MenuItem;
import androidx.annotation.Nullable;

import java.util.Objects;
Expand All @@ -53,6 +52,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
binding.apiTap.setText(AccountManager.getTapKey(this));
binding.apiUsername.setText(AccountManager.getUsername(this));
binding.doorApiKey.setText(AccountManager.getDoorKey(this));
setResult(RESULT_OK, new Intent());
}

@Override
Expand All @@ -73,22 +73,6 @@ protected void onStop() {
binding.doorApiKey.removeTextChangedListener(this);
}

@Override
public void onBackPressed() {
Intent intent = new Intent();
setResult(RESULT_OK, intent);
super.onBackPressed();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent();
setResult(RESULT_OK, intent);
}
return super.onOptionsItemSelected(item);
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Do nothing.
Expand Down