Skip to content

Commit 373b775

Browse files
Merge pull request #268 from appdevforall/feat/ADFA-4887-webview-nav
ADFA-4887: WebView nav — touch-based auto-hide + Home becomes Fullscreen
2 parents 08aa3ba + 1834a48 commit 373b775

3 files changed

Lines changed: 47 additions & 10 deletions

File tree

‎controller/app/src/main/java/org/iiab/controller/PortalActivity.java‎

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public class PortalActivity extends AppCompatActivity {
6969

7070
private GestureWebView webView;
7171
private org.iiab.controller.redesign.FqrController fqr; // ADFA-4879: FQR maps (only on /maps/)
72+
private static final long AUTO_HIDE_MS = 4000L; // ADFA-4887: nav-bar auto-hide after inactivity
73+
private boolean fullscreenOn = false; // ADFA-4887: Home button toggles fullscreen
74+
private Handler hideHandler; // ADFA-4887: nav-bar auto-hide (cleared in onDestroy)
75+
private Runnable hideRunnable;
7276
// pdf.js builds advertised by /pdfjs/manifest.json (loaded off the main thread).
7377
// Empty until loaded / when the box serves none -> PDFs fall back to download.
7478
private volatile List<PdfViewerBuild> pdfViewerBuilds = Collections.emptyList();
@@ -100,26 +104,30 @@ protected void onCreate(Bundle savedInstanceState) {
100104
Button btnExit = findViewById(R.id.btnExit);
101105
Button btnForward = findViewById(R.id.btnForward);
102106

103-
// --- PERSISTENT BAR ---
104-
// Keep the nav bar (with Exit) visible so a non-technical user always has an
105-
// obvious way out. The handle is only used after a manual hide (btnHideNav).
107+
// --- NAV BAR (auto-hide after inactivity) ---
108+
// Visible on entry; hides after AUTO_HIDE_MS with no interaction, measured from the LAST
109+
// touch. The handle (⌃) brings it back; btnHideNav hides it manually.
106110
bottomNav.post(() -> {
107111
bottomNav.setTranslationY(0);
108112
bottomNav.setVisibility(View.VISIBLE);
109113
});
110114
btnHandle.setVisibility(View.GONE);
111115

112-
// --- AUTO-HIDE TIMER ---
113-
Handler hideHandler = new Handler(Looper.getMainLooper());
116+
hideHandler = new Handler(Looper.getMainLooper());
114117

115-
Runnable hideRunnable = () -> {
118+
hideRunnable = () -> {
116119
bottomNav.animate().translationY(bottomNav.getHeight()).setDuration(250);
117120
btnHandle.setVisibility(View.VISIBLE);
118121
btnHandle.animate().alpha(1f).setDuration(150);
119122
};
120123

121-
// Persistent bar: never auto-hide. Cancel any pending hide; only btnHideNav hides.
122-
Runnable resetTimer = () -> hideHandler.removeCallbacks(hideRunnable);
124+
// Reschedule the hide on every interaction -> auto-hide from the LAST touch, not the first.
125+
Runnable resetTimer = () -> {
126+
hideHandler.removeCallbacks(hideRunnable);
127+
hideHandler.postDelayed(hideRunnable, AUTO_HIDE_MS);
128+
};
129+
webView.setOnUserInteraction(resetTimer); // content touches count as interaction too
130+
resetTimer.run(); // start the initial countdown
123131

124132
// --- HANDLE LOGIC (Show Bar) ---
125133
btnHandle.setOnClickListener(v -> {
@@ -141,8 +149,23 @@ protected void onCreate(Bundle savedInstanceState) {
141149
// Resolve the target URL once (domain), surviving rotation via the ViewModel.
142150
final String finalTargetUrl = vm.targetUrl(getIntent().getStringExtra("TARGET_URL"));
143151

152+
// ADFA-4887: there is no in-WebView home page anymore, so Home is a Fullscreen toggle.
153+
// Enters full immersive (system bars hidden) and hides our bar too — but the bar stays
154+
// recoverable via the handle. Press again to exit.
144155
btnHome.setOnClickListener(v -> {
145-
webView.loadUrl(finalTargetUrl);
156+
fullscreenOn = !fullscreenOn;
157+
androidx.core.view.WindowInsetsControllerCompat wic =
158+
androidx.core.view.WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
159+
if (fullscreenOn) {
160+
wic.setSystemBarsBehavior(
161+
androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
162+
wic.hide(androidx.core.view.WindowInsetsCompat.Type.systemBars());
163+
hideRunnable.run(); // hide our bar too (still recoverable via the handle)
164+
} else {
165+
wic.show(androidx.core.view.WindowInsetsCompat.Type.systemBars());
166+
btnHandle.animate().alpha(0f).setDuration(150).withEndAction(() -> btnHandle.setVisibility(View.GONE));
167+
bottomNav.animate().translationY(0).setDuration(250);
168+
}
146169
resetTimer.run();
147170
});
148171

@@ -387,6 +410,7 @@ protected void onDestroy() {
387410
// ADFA-4879: stop FQR polling + drop its overlay/dialog so we don't leak the activity.
388411
// The durable server job (if any) keeps running and shows up on the next /maps/ reload.
389412
if (fqr != null) fqr.detach();
413+
if (hideHandler != null && hideRunnable != null) hideHandler.removeCallbacks(hideRunnable); // ADFA-4887
390414
super.onDestroy();
391415
}
392416

‎controller/app/src/main/java/org/iiab/controller/portal/presentation/GestureWebView.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public class GestureWebView extends WebView {
2828
public static final String TAG = "IIAB-GestureWV";
2929

3030
private boolean gestureLogging = false;
31+
private Runnable onUserInteraction; // ADFA-4887: notified on each touch (nav-bar auto-hide)
3132

3233
public GestureWebView(Context context) { super(context); }
3334
public GestureWebView(Context context, AttributeSet attrs) { super(context, attrs); }
@@ -36,10 +37,20 @@ public class GestureWebView extends WebView {
3637
/** Enable verbose touch logging (debug builds only). */
3738
public void setGestureLogging(boolean enabled) { this.gestureLogging = enabled; }
3839

40+
/** Called on every touch so the host can reset UI timers (e.g. nav-bar auto-hide from last touch). */
41+
public void setOnUserInteraction(Runnable r) { this.onUserInteraction = r; }
42+
3943
@Override
4044
public boolean onTouchEvent(MotionEvent event) {
4145
final int pointers = event.getPointerCount();
4246

47+
// Reset the host's UI timers on touch start/end only (not every MOVE) so a pan/tilt doesn't
48+
// re-post the auto-hide dozens of times a second; ACTION_UP effectively marks the last touch.
49+
final int action = event.getActionMasked();
50+
if (onUserInteraction != null && (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP)) {
51+
onUserInteraction.run();
52+
}
53+
4354
// Two or more fingers: keep the gesture for the web content (the map),
4455
// so an ancestor (pager/scroll) can't hijack a tilt/rotate/pinch.
4556
if (pointers >= 2) {

‎controller/app/src/main/res/layout/activity_portal.xml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@
6161
style="?android:attr/buttonBarButtonStyle"
6262
android:textColor="?android:attr/textColorPrimary" />
6363

64+
<!-- ADFA-4887: repurposed as a Fullscreen toggle (no in-WebView home page anymore).
65+
Material 3 icon + contentDescription land in ADFA-4886. -->
6466
<Button
6567
android:id="@+id/btnHome"
6668
android:layout_width="0dp"
6769
android:layout_height="wrap_content"
6870
android:layout_weight="1"
69-
android:text="🏠"
71+
android:text="⛶"
7072
android:textSize="20sp"
7173
style="?android:attr/buttonBarButtonStyle"
7274
android:textColor="?android:attr/textColorPrimary" />

0 commit comments

Comments
 (0)