Skip to content

Commit bf2a069

Browse files
graycreateclaude
andauthored
refactor: use BaseActivity's loading indicator for Vshare WebView (#156)
* refactor: use BaseActivity's loading indicator for WebView Replaced custom horizontal ProgressBar with BaseActivity's standard circular loading indicator to maintain UI consistency across the app. Changes: - Removed custom ProgressBar from XML layout - Removed @BindView for mProgressBar - Removed WebChromeClient (no longer needed for progress tracking) - Use showLoading() in onPageStarted() - Use hideLoading() in onPageFinished() This provides a cleaner, more consistent loading experience that matches other activities like TopicActivity, using the app's standard 55dp circular ProgressBar centered on screen. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: prevent white flash when loading WebView in dark mode Fixed the issue where WebView would briefly show white background before the page finishes loading in dark mode. Changes: 1. Set WebView background color to match theme before loading - Dark mode: #1a1a1a (dark gray) - Light mode: white 2. Enable FORCE_DARK on Android Q+ when in dark mode - Automatically applies dark styling to web content - Provides immediate dark appearance This ensures a consistent visual experience from the moment the WebView starts loading, eliminating the jarring white flash that previously occurred in dark mode. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: hide WebView until theme is applied to prevent white flash Changed approach to completely eliminate white flash in dark mode: - Set WebView to INVISIBLE before loading - Apply theme via JavaScript when page finishes loading - Show WebView after 100ms delay to ensure JS executes - Hide loading indicator when WebView becomes visible This ensures users only see the WebView after the correct theme has been fully applied, completely eliminating the white flash that occurred during page load in dark mode. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: improve dark mode loading by setting WebView invisible in XML and increasing delay - Set WebView visibility to invisible in XML layout to prevent initial white flash - Increase delay from 100ms to 300ms to ensure theme JavaScript executes properly - This eliminates the white screen gap during page load in dark mode 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: handle WebView loading errors to prevent persistent spinner Address GitHub Copilot review feedback by adding error handling callbacks to dismiss the loading indicator when page load fails. Changes: - Add onReceivedError() override to hide loading on network/SSL errors - Add onReceivedHttpError() override to hide loading on HTTP errors - Both callbacks also hide the theme overlay to restore UI state This prevents the loading spinner from persisting indefinitely when WebView encounters errors during page load. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * feat: add bottom margin to WebView for navigation bar spacing Apply navigation bar height as bottom margin to prevent content from being hidden under the navigation bar in fullscreen WebView. Changes: - Import Utils to access getNavigationBarHeight() - Update applyStatusBarMargin() to also apply bottom margin - Use Utils.getNavigationBarHeight() for bottom margin calculation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent 10dfdb9 commit bf2a069

File tree

2 files changed

+88
-25
lines changed

2 files changed

+88
-25
lines changed

app/src/main/java/me/ghui/v2er/module/vshare/VshareWebActivity.java

Lines changed: 85 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@
55
import android.content.Context;
66
import android.content.Intent;
77
import android.graphics.Bitmap;
8+
import android.graphics.Color;
89
import android.net.Uri;
10+
import android.os.Build;
911
import android.os.Bundle;
1012
import android.util.Log;
1113
import android.view.View;
1214
import android.view.ViewGroup;
1315
import android.widget.FrameLayout;
14-
import android.webkit.WebChromeClient;
1516
import android.webkit.WebResourceRequest;
1617
import android.webkit.WebSettings;
1718
import android.webkit.WebView;
1819
import android.webkit.WebViewClient;
19-
import android.widget.ProgressBar;
2020
import android.widget.Toast;
2121

2222
import androidx.annotation.Nullable;
@@ -26,6 +26,7 @@
2626
import me.ghui.v2er.module.base.BaseActivity;
2727
import me.ghui.v2er.module.base.BaseContract;
2828
import me.ghui.v2er.util.DarkModelUtils;
29+
import me.ghui.v2er.util.Utils;
2930
import me.ghui.v2er.widget.BaseToolBar;
3031

3132
/**
@@ -40,8 +41,8 @@ public class VshareWebActivity extends BaseActivity<BaseContract.IPresenter> {
4041
@BindView(R.id.webview)
4142
WebView mWebView;
4243

43-
@BindView(R.id.progress_bar)
44-
ProgressBar mProgressBar;
44+
@BindView(R.id.theme_overlay)
45+
View mThemeOverlay;
4546

4647
public static void open(Context context) {
4748
Intent intent = new Intent(context, VshareWebActivity.class);
@@ -76,6 +77,9 @@ protected boolean supportSlideBack() {
7677
protected void init() {
7778
super.init();
7879

80+
// Set loading delay to 0 to show loading indicator immediately
81+
setFirstLoadingDelay(0);
82+
7983
// Apply fullscreen flags for edge-to-edge WebView
8084
View decorView = getWindow().getDecorView();
8185
int systemUiVisibility = decorView.getSystemUiVisibility()
@@ -94,6 +98,9 @@ protected void init() {
9498
// Set WebView top margin to status bar height
9599
applyStatusBarMargin();
96100

101+
// Set overlay background color to match theme
102+
setupThemeOverlay();
103+
97104
setupWebView();
98105

99106
// Compute URL with theme parameter based on current app theme
@@ -106,8 +113,34 @@ protected void init() {
106113
mWebView.loadUrl(url);
107114
}
108115

116+
/**
117+
* Setup theme overlay to prevent white flash during page load
118+
*/
119+
private void setupThemeOverlay() {
120+
boolean isDarkMode = DarkModelUtils.isDarkMode();
121+
if (isDarkMode) {
122+
// Dark mode: use dark overlay
123+
mThemeOverlay.setBackgroundColor(Color.parseColor("#1a1a1a"));
124+
} else {
125+
// Light mode: use white overlay
126+
mThemeOverlay.setBackgroundColor(Color.WHITE);
127+
}
128+
// Overlay is visible by default, will be hidden after theme is applied
129+
mThemeOverlay.setVisibility(View.VISIBLE);
130+
}
131+
109132
@SuppressLint("SetJavaScriptEnabled")
110133
private void setupWebView() {
134+
// Set WebView background color to match theme
135+
boolean isDarkMode = DarkModelUtils.isDarkMode();
136+
if (isDarkMode) {
137+
// Dark mode: set dark background
138+
mWebView.setBackgroundColor(Color.parseColor("#1a1a1a"));
139+
} else {
140+
// Light mode: set white background
141+
mWebView.setBackgroundColor(Color.WHITE);
142+
}
143+
111144
WebSettings settings = mWebView.getSettings();
112145

113146
// Enable JavaScript
@@ -116,6 +149,11 @@ private void setupWebView() {
116149
// Enable DOM storage
117150
settings.setDomStorageEnabled(true);
118151

152+
// Force dark mode for WebView content on Android Q+ if app is in dark mode
153+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isDarkMode) {
154+
settings.setForceDark(WebSettings.FORCE_DARK_ON);
155+
}
156+
119157
// Disable file and content access for security
120158
settings.setAllowFileAccess(false);
121159
settings.setAllowContentAccess(false);
@@ -152,7 +190,7 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
152190
@Override
153191
public void onPageStarted(WebView view, String url, Bitmap favicon) {
154192
super.onPageStarted(view, url, favicon);
155-
mProgressBar.setVisibility(View.VISIBLE);
193+
showLoading();
156194
}
157195

158196
@Override
@@ -165,32 +203,61 @@ public void onPageFinished(WebView view, String url) {
165203
"document.documentElement.setAttribute('data-theme', '" + theme + "'); " +
166204
"})()";
167205
mWebView.loadUrl(js);
206+
207+
// Hide overlay after theme is applied (small delay to ensure JS executes)
208+
mWebView.postDelayed(new Runnable() {
209+
@Override
210+
public void run() {
211+
// Fade out the overlay
212+
mThemeOverlay.animate()
213+
.alpha(0f)
214+
.setDuration(200)
215+
.withEndAction(new Runnable() {
216+
@Override
217+
public void run() {
218+
mThemeOverlay.setVisibility(View.GONE);
219+
}
220+
});
221+
hideLoading();
222+
}
223+
}, 100);
168224
}
169-
});
170225

171-
// Set WebChromeClient for progress updates
172-
mWebView.setWebChromeClient(new WebChromeClient() {
173226
@Override
174-
public void onProgressChanged(WebView view, int newProgress) {
175-
mProgressBar.setProgress(newProgress);
176-
if (newProgress == 100) {
177-
mProgressBar.setVisibility(View.GONE);
178-
}
227+
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
228+
super.onReceivedError(view, errorCode, description, failingUrl);
229+
// Hide loading indicator on error to prevent persistent spinner
230+
hideLoading();
231+
mThemeOverlay.setVisibility(View.GONE);
232+
}
233+
234+
@Override
235+
public void onReceivedHttpError(WebView view, android.webkit.WebResourceRequest request,
236+
android.webkit.WebResourceResponse errorResponse) {
237+
super.onReceivedHttpError(view, request, errorResponse);
238+
// Hide loading indicator on HTTP error to prevent persistent spinner
239+
hideLoading();
240+
mThemeOverlay.setVisibility(View.GONE);
179241
}
180242
});
181243
}
182244

183245
/**
184-
* Apply status bar height as top margin to WebView
246+
* Apply status bar height as top margin and navigation bar height as bottom margin to WebView
185247
*/
186248
private void applyStatusBarMargin() {
187249
int statusBarHeight = getStatusBarHeight();
188-
if (statusBarHeight > 0) {
189-
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mWebView.getLayoutParams();
190-
if (params instanceof FrameLayout.LayoutParams) {
250+
int navigationBarHeight = Utils.getNavigationBarHeight();
251+
252+
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mWebView.getLayoutParams();
253+
if (params instanceof FrameLayout.LayoutParams) {
254+
if (statusBarHeight > 0) {
191255
params.topMargin = statusBarHeight;
192-
mWebView.setLayoutParams(params);
193256
}
257+
if (navigationBarHeight > 0) {
258+
params.bottomMargin = navigationBarHeight;
259+
}
260+
mWebView.setLayoutParams(params);
194261
}
195262
}
196263

app/src/main/res/layout/activity_vshare_web.xml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@
99
android:layout_width="match_parent"
1010
android:layout_height="match_parent" />
1111

12-
<ProgressBar
13-
android:id="@+id/progress_bar"
14-
style="?android:attr/progressBarStyleHorizontal"
12+
<View
13+
android:id="@+id/theme_overlay"
1514
android:layout_width="match_parent"
16-
android:layout_height="3dp"
17-
android:layout_gravity="top"
18-
android:progressTint="@color/colorAccent"
19-
android:visibility="gone" />
15+
android:layout_height="match_parent" />
2016

2117
</FrameLayout>

0 commit comments

Comments
 (0)