From e13f28025fad6724977b0956f57a1091b6514a04 Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:23:06 +0530 Subject: [PATCH 1/9] Implement adaptive icon background with gradient depth - Created a dedicated background layer XML for the adaptive icon implementation. - Implemented a rich linear gradient transitioning from vibrant light blue to a deep navy edge. - Eliminated the flat, single-color background to give the launcher icon a premium, polished aesthetic. --- .../res/drawable/ic_launcher_background.xml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..da555f4 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + From bb8a6d5cd14d964069dbf569ab3657f2ced28e2c Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:24:21 +0530 Subject: [PATCH 2/9] Add unscaled logo asset for in-app action bar - Created an exact duplicate of the cell-tower vector graphic specifically for in-app layouts. - Removed the 75% scaling group from this version so it renders at full 100% size inside the app's UI. - Decoupled the in-app branding from the launcher icon, preventing the action bar logo from appearing artificially small. --- app/src/main/res/drawable/ic_logo_ui.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 app/src/main/res/drawable/ic_logo_ui.xml diff --git a/app/src/main/res/drawable/ic_logo_ui.xml b/app/src/main/res/drawable/ic_logo_ui.xml new file mode 100644 index 0000000..852af25 --- /dev/null +++ b/app/src/main/res/drawable/ic_logo_ui.xml @@ -0,0 +1,13 @@ + + + From e226ca50848a48c568393a8e53da32006e391c53 Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:25:56 +0530 Subject: [PATCH 3/9] Scale and add 3D drop shadow to launcher foreground - Wrapped the core cell-tower vector paths in a scaling group (scaleX="0.75", scaleY="0.75") to add generous padding and negative space around the edges. - Duplicated the main vector path and applied a semi-transparent dark tint (#40001030) with an X/Y offset. - Created a subtle optical drop shadow, giving the white icon a floating, three-dimensional depth over the background. --- .../res/drawable/ic_launcher_foreground.xml | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 852af25..c7c3207 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -4,10 +4,25 @@ android:height="108dp" android:viewportWidth="108" android:viewportHeight="108"> - + + + + + + + + + + + From 859c25c29b3c23ef263ebe8d85b818ca63560bbe Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:28:06 +0530 Subject: [PATCH 4/9] Add adaptive icon wrapper for Android 8.0+ - Created the API 26+ configuration file to support modern Android launcher shapes. - Linked the newly split foreground (ic_launcher_foreground) and background (ic_launcher_background) layers. - Resolved the visual bug on AOSP/Pixel ROMs where the legacy icon was forcibly shrunk inside a white circular background. --- app/src/main/res/drawable-anydpi-v26/ic_launcher.xml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 app/src/main/res/drawable-anydpi-v26/ic_launcher.xml diff --git a/app/src/main/res/drawable-anydpi-v26/ic_launcher.xml b/app/src/main/res/drawable-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6b78462 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + From fc3429eba7332686aea68b5750ad3bcc1348023d Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:30:47 +0530 Subject: [PATCH 5/9] Resolve portrait edge-to-edge layout clipping and Add new icon logo - Added android:fitsSystemWindows="true" to the root LinearLayout to instruct AOSP Window Managers to respect safe insets. - Fixed the bug where the top header clipped into the status bar and the footer hid behind the 3-button navigation bar on stock Android. - Replaced the action bar's ic_launcher_foreground reference with the new unscaled ic_logo_ui drawable. --- app/src/main/res/layout/activity_main.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 8944e11..67f0e0c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,6 @@ From bc5e3082b53f555e60038bc34d34d59699964d0a Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:32:50 +0530 Subject: [PATCH 6/9] Resolve landscape edge-to-edge clipping and icon scaling - Applied android:fitsSystemWindows="true" to the root landscape layout to ensure safe padding across notches and navigation bars when the device is rotated. - Swapped the action bar logo reference to use the unscaled ic_logo_ui asset. - Restored the landscape ImageView dimensions (39dp) to ensure the branding matches the proportions of the portrait layout perfectly. --- app/src/main/res/layout-land/activity_main.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml index a556e89..e7a8b0d 100644 --- a/app/src/main/res/layout-land/activity_main.xml +++ b/app/src/main/res/layout-land/activity_main.xml @@ -1,5 +1,6 @@ From c05dbca93bee32e213f8701fb3f2b006d04e6372 Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:03:12 +0530 Subject: [PATCH 7/9] Fix landscape static cards cut-off spacing by making them responsive - Replaced the hardcoded HorizontalScrollView wrapper around the 3 static guide cards with a fluid LinearLayout configured as match_parent. - Changed the static width (android:layout_width="260dp") of all three individual cards (staticCard1, staticCard2, staticCard3) to 0dp. - Added android:layout_weight="1" to all three cards. - This ensures that instead of cutting off or requiring side-scrolling on large screens, all three cards stretch and evenly distribute themselves to seamlessly fill 100% of the available horizontal space regardless of the device's aspect ratio. --- .../main/res/layout-land/activity_main.xml | 329 ++++++++++++------ 1 file changed, 230 insertions(+), 99 deletions(-) diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml index e7a8b0d..5ccb2ed 100644 --- a/app/src/main/res/layout-land/activity_main.xml +++ b/app/src/main/res/layout-land/activity_main.xml @@ -175,109 +175,240 @@ android:textColor="@color/text_secondary" android:textSize="12sp" /> - + - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:background="@drawable/shape_pill_badge_bg" + android:backgroundTint="@color/card_surface" + android:gravity="center_vertical" + android:paddingHorizontal="12dp" + android:paddingVertical="6dp" + android:layout_marginTop="12dp" + android:clickable="true" + android:focusable="true"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d333de5d6ef3b3fb34db05b4497b2e62cd806bbd Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:06:20 +0530 Subject: [PATCH 8/9] Remove all carousel auto-cycling and timer logic - Stripped the authorizedCarouselRunnable entirely from the codebase, stopping the 7-second automatic swipe timer. - Removed the carouselHandler instantiation entirely since background threads and timers are no longer needed for the UI. - Cleaned up the updateCarouselContext method: it now statically sets currentCarouselIndex = 0 (Page 1) if unauthorized, and statically sets currentCarouselIndex = 1 (Page 2) if authorized. - Updated the onResume lifecycle hook to instantly snap to the 2nd page if isUIAuthorized is true, without trying to attach a timer runnable. - Cleaned up the onPause lifecycle hook to completely empty (removed all handler callbacks and preference savings). - Removed all SharedPreferences logic related to carousel memory state to prevent ghosting or saving incorrect indices across sessions. - Cleaned up the manual touch listener to remove any removeCallbacks or postDelayed timer resets when the user manually swipes left or right. --- .../dhangofa/networktoggle/MainActivity.java | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java b/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java index 4213ddc..b2da717 100644 --- a/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java +++ b/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java @@ -192,6 +192,7 @@ protected void onCreate(Bundle savedInstanceState) { bindSelectionListeners(); updateSeparatorVisibility(); setupCarousel(); + setupStaticLandscapeCards(); } private void configureStatusBar() { @@ -247,6 +248,21 @@ private void bindLinks() { } + private void setupStaticLandscapeCards() { + View btn1 = findViewById(R.id.staticCardButton1); + if (btn1 != null) { + btn1.setOnClickListener(v -> openUrl("https://github.com/Dhangofa/NetToggle/wiki/1.-Execution-Mode-Configuration")); + } + View btn2 = findViewById(R.id.staticCardButton2); + if (btn2 != null) { + btn2.setOnClickListener(v -> openUrl("https://github.com/Dhangofa/NetToggle/wiki/2.-Target-SIM-Setup-&-Quick-Tile-Cycle-Guide")); + } + View btn3 = findViewById(R.id.staticCardButton3); + if (btn3 != null) { + btn3.setOnClickListener(v -> openUrl("https://github.com/Dhangofa/NetToggle/wiki/3.-Adding-the-Tile-to-Quick-Settings")); + } + } + private void setupCarousel() { if (carouselBackground == null) return; carouselItems = new CarouselItem[]{ @@ -270,16 +286,17 @@ private void setupCarousel() { case android.view.MotionEvent.ACTION_CANCEL: float deltaX = event.getX() - touchStartX; if (Math.abs(deltaX) > 100) { - carouselHandler.removeCallbacks(carouselAutoRunnable); - if (deltaX > 0 && currentCarouselIndex > 0) { - currentCarouselIndex--; + if (deltaX > 0) { + // Swipe right (previous page) + currentCarouselIndex = (currentCarouselIndex - 1 + carouselItems.length) % carouselItems.length; renderCarouselPage(currentCarouselIndex, true, -1); - } else if (deltaX < 0 && currentCarouselIndex < carouselItems.length - 1) { - currentCarouselIndex++; + } else if (deltaX < 0) { + // Swipe left (next page) + currentCarouselIndex = (currentCarouselIndex + 1) % carouselItems.length; renderCarouselPage(currentCarouselIndex, true, 1); } - // Resume after 10 seconds of inactivity - carouselHandler.postDelayed(carouselAutoRunnable, 10000); + + } else if (event.getAction() == android.view.MotionEvent.ACTION_UP) { v.performClick(); } @@ -343,7 +360,7 @@ private void renderCarouselPage(int index, boolean animate, int direction) { // Prepare for animate in view.setTranslationX(moveInX); - view.animate().translationX(0f).alpha(1f).setDuration(duration) + view.animate().translationX(0f).alpha(1f).setDuration(duration / 2) .setInterpolator(new android.view.animation.DecelerateInterpolator()) .start(); }).start(); @@ -488,22 +505,17 @@ private void bindSelectionListeners() { @Override protected void onResume() { super.onResume(); + if (appPreferences != null) updateAutoSimWarning(); checkAndRequestPermission(); updateErrorBanner(); updateCapabilities(); - if (carouselHandler != null && carouselAutoRunnable != null) { - carouselHandler.removeCallbacks(carouselAutoRunnable); - carouselHandler.postDelayed(carouselAutoRunnable, 5000); - } + } @Override protected void onPause() { super.onPause(); - if (carouselHandler != null && carouselAutoRunnable != null) { - carouselHandler.removeCallbacks(carouselAutoRunnable); - } } private void checkAndRequestPermission() { @@ -733,56 +745,40 @@ private void setStatus(String text, int color) { } - private android.os.Handler carouselHandler = new android.os.Handler(android.os.Looper.getMainLooper()); - private Runnable carouselAutoRunnable = new Runnable() { - @Override - public void run() { - if (carouselItems == null) return; - - int nextIndex; - if (!isUIAuthorized) { - // If unauthorized but user manually swiped away, bring them back to 0 eventually - nextIndex = 0; - } else { - // If authorized, cycle through logically - nextIndex = (currentCarouselIndex == 2) ? 1 : (currentCarouselIndex + 1); - } - - if (nextIndex != currentCarouselIndex) { - int direction = (nextIndex > currentCarouselIndex) ? 1 : -1; - currentCarouselIndex = nextIndex; - renderCarouselPage(currentCarouselIndex, true, direction); - } - carouselHandler.postDelayed(this, 5000); - } - }; + + + + private void updateCarouselContext(boolean authorized) { if (carouselBackground == null || carouselItems == null) return; - carouselHandler.removeCallbacks(carouselAutoRunnable); + + boolean animate = !isFirstCarouselRender; + isFirstCarouselRender = false; if (!authorized) { - if (currentCarouselIndex != 0) { + if (currentCarouselIndex != 0 || !animate) { currentCarouselIndex = 0; - renderCarouselPage(0, true, -1); + renderCarouselPage(0, animate, -1); } - // Will auto-correct to 0 every 5 seconds if user swipes away while unauthorized - carouselHandler.postDelayed(carouselAutoRunnable, 5000); } else { - if (currentCarouselIndex == 0) { + // Always start at 2nd page (index 1) on auth transition + if (currentCarouselIndex != 1 || !animate) { currentCarouselIndex = 1; - renderCarouselPage(1, true, 1); + renderCarouselPage(1, animate, 1); } - carouselHandler.postDelayed(carouselAutoRunnable, 5000); } } private boolean isUIAuthorized = false; + private boolean isFirstCarouselRender = true; + + private void updateAuthorizationUI(boolean authorized) { - updateCarouselContext(authorized); if (isUIAuthorized == authorized) return; isUIAuthorized = authorized; + updateCarouselContext(authorized); float alpha = authorized ? 1.0f : 0.4f; View targetSimCard = findViewById(R.id.targetSimRadioGroup); From 28b88bb25c6306502fa1c27245fbd645e753d709 Mon Sep 17 00:00:00 2001 From: DK <117024745+Dhangofa@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:18:29 +0530 Subject: [PATCH 9/9] Upgrade ic_launcher with depth and gradient background - Added Background Gradient - Added Shadow Effect in main Antenna Icon --- app/src/main/res/drawable/ic_launcher.xml | 45 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/drawable/ic_launcher.xml b/app/src/main/res/drawable/ic_launcher.xml index 99527c8..e422163 100644 --- a/app/src/main/res/drawable/ic_launcher.xml +++ b/app/src/main/res/drawable/ic_launcher.xml @@ -1,17 +1,48 @@ - - + + + + + + + + + + + + + + + - - + + + + + + + +