My auto-hide controls kept flickering in ArtPlayer v5: the dual-timer fight and the 1.5s immunity fix

2026-11-04来源 dev.toEnglish

I'm building RKMovies (a tiny 4K player for old phones) — 0.91 MB APK, hardware decode, no accounts, no tracking. The player UI runs on ArtPlayer v5, and I replaced its default controls with my own auto-hide layer. That layer flickered for weeks. Here's why.

ArtPlayer hides its controls on its own timer. Every timeupdate it checks controls.timer; if the controls have been idle for a few seconds it hides them and hides the cursor.

I wanted different rules: never hide while the settings panel is open, while paused, or while the user is scrubbing, plus a minimum visible time of 1s. So I added my own hideTimer (3.5s) with those guards.

Two timers, two sources of truth. ArtPlayer's internal check and my setTimeout disagreed about when to hide, so the controls flickered: my layer showed them, the library's next timeupdate hid them, mine showed them again.

The fix wasn't a second timer fighting the first. It was a 1.5s immunity lock. Every time my layer shows the controls it sets wakeLockUntil = Date.now() + 1500, and hideControls() refuses to run inside that window unless forced (video ended). Then, on every video:timeupdate, if we're inside the immunity window I poke the library's own timer: art.controls.timer = Date.now(). The library thinks the user just interacted and leaves the controls alone. One timer owns hiding; the other just gets told to stay quiet.

const HIDE_TIMEOUT_MS = 3500; let wakeLockUntil = 0; function showControls() { wakeLockUntil = Date.now() + 1500; // immunity lock art.controls.timer = Date.now(); scheduleHide(); } function hideControls(force = false) { if (!force && Date.now() < wakeLockUntil) return; if (!force && Date.now() - lastShowTime < 1000) return; if (!force && isMenuOpen()) return; // settings / context menu if (!force && art.video.paused) return; if (!force && isScrubbing()) return; // ...actually hide } art.on('video:timeupdate', () => { if (Date.now() < wakeLockUntil && art.controls) { art.controls.timer = Date.now(); // keep the library's idle check happy } }); 

Guards that matter in practice: the settings panel (art-setting-show class or clientHeight), the context menu, paused state, and the .art-scrubbing class on the player element. Miss one and the controls vanish mid-drag, which feels broken.

I also overrode art.controls.toggle to route through my show/hide instead of the default flip, so taps behave the same everywhere.

Lesson: when you wrap a player library's internals, don't run a parallel timer. Patch the value the library reads (controls.timer) and keep a single owner for the hide decision. The code lives in setupControlsAutoHide() in the app's player module.

If you want to try it: gesture-controlled video player for Android, the Windows edition for PC.

原文:https://www.a8q9.cn/en/article/my-auto-hide-controls-kept-flickering-in-artplayer-v5-the-dual-timer-fight-and-t-0329c0.html

相关文章