タイトルだけだと分かりにくいと思うので・・・
こういうことを実現したかったんですよ。
- AndroidアプリにWebViewを組み込み
- WebView内で上から下にスワイプ
- その時にWebViewをリロードする
ChromeとかTwitterでもよく見かけるアレです。
こういうのはSwipeRefreshLayoutで実装できます。
その実装方法を忘備録として残しておきます。
※ 以下はAndroid Studioでの手順
このページの目次
手順1.build.gradleにswiperefreshlayoutを追加する
まずはアプリレベルのbuild.gradleを開きます。
▼ そしたら dependencies 以下に次を追加
1 2 |
/// SwipeRefreshLayoutを追加 implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" |
こうしないと使えないみたいなので注意。
そしたら【Sync now】を押して同期させればOKです。
手順2.WebViewのあるレイアウトをすこし改良する
お次はレイアウト側で少し細工をします。
例えば次のレイアウトがあったとしましょう。
▼ 例 : 細工前のactivity_main.xml
1 2 3 4 |
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" /> |
レイアウト中にWebViewだけが存在してます。
これをSwipeRefreshLayoutで囲んであげるんです。
▼ 例 : 細工後のactivity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swiper_for_webview" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/nonVideoLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:windowSoftInputMode="adjustResize"> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
このように WebView を RelativeLayout で囲んでおき、さらに SwipeRefreshLayout で囲むような形ですね。(ちなみにビューIDには "swiper_for_webview" を指定)
手順3.スワイプ更新の処理をActivity側に追加する
そしたらActivity側でスワイプ更新を実装してきます。
ここではこのようなコードで実現してみました。
▼ Activity側の実装コード例(Kotlin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
class MainActivity : AppCompatActivity() { private lateinit var webView : WebView; private lateinit var swipeRefreshLayout : SwipeRefreshLayout; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) webView = findViewById(R.id.webview_main); swipeRefreshLayout = findViewById(R.id.swiper_for_webview_main); webView.webViewClient = object : WebViewClient(){ override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url); /// 読み込みのグルグルマークを消す swipeRefreshLayout.isRefreshing = false; } } /// ページ読み込み webView.loadUrl("/assets/index.html"); /// WebViewのスワイプ更新 swipeRefreshLayout.setOnRefreshListener { /// リロード webView.reload(); }; swipeRefreshLayout.viewTreeObserver.addOnScrollChangedListener( object : ViewTreeObserver.OnScrollChangedListener { /// WebViewの一番上でスクロールされた時のみ、SwipeRefreshを有効にする。 /// こうしておかないとページスクロールの邪魔をしてしまう override fun onScrollChanged() { if (webView.getScrollY() == 0) swipeRefreshLayout.setEnabled(true); else swipeRefreshLayout.setEnabled(false); } } ) } } |
こういう感じで実装ができました。
ただしいくつか注意点があります。
- ページスクロールの邪魔をさせない
上コードのように ViewTreeObserver.OnScrollChangedListener{...} を実装し、WebView一番上でスワイプされたときだけ更新させるようにしている
- 再読み込み後にグルグルを消す
ページ再読み込み後は swipeRefreshLayout.isRefreshing = false; を呼び出すこと。そうしないとグルグルマークがずっと表示されたままになってしまう
この2点が大事なポイントですね。
実際のSwipeRefreshLayoutの挙動(Gif)
このような挙動になりました。
▼ WebView内でスワイプしたときの挙動
上から下にスワイプすると再読み込みマークがニュッと出てきて、読み込み中はグルグルマークが回り続けるような挙動になってます。
工夫すればアイコンをカスタマイズしたり、挙動を変えたりもできるみたいですが、下手にアレンジすりょり元からある方が洗練されてますね。
以上、WebViewでスワイプ再読み込みの実装でした。
もちろんWebView以外でも使える方法です。ではまた