抓住人生中的一分一秒,胜过虚度中的一月一年!
背景
项目开发中会经常用到webview,当我们每次写webview时候,都会写一堆重复的代码,这样对于高效开发来说成了累赘,今天给大家分享一个通用的webview,目的是为了使用简单化,本文章实现了webview通用的功能,如果构建复杂的交互功能,可选择扩展或者用GitHub一些开源的第三方类库
实现目标
1、webview基本功能实现
2、进度条实现
说明
为了扩展性高一些,封装的WebViewWrapper选择不继承WebView,而是继承RelativeLayout,在父控件中重新构造webview
1、新建Xml布局,创建webview和ProgressBar
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/frameLayout" android:layout_width="match_parent" android:layout_height="match_parent" /> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent"/> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="2dp" android:progressDrawable="@drawable/progressbar_orange_selector"/> </RelativeLayout>
2、新建WebViewWrapper类,继承RelativeLayout
public class WebViewWrapper extends RelativeLayout
3、在WebViewWrapper类中创建webview并对其配置属性
WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); // 默认false,设置true后我们才能在WebView里与我们的JS代码进行交互 settings.setJavaScriptCanOpenWindowsAutomatically(true); // 设置JS是否可以打开WebView新窗口 settings.setSupportZoom(true); // 支持缩放 settings.setBuiltInZoomControls(true); // 支持手势缩放 settings.setDisplayZoomControls(false); // 不显示缩放按钮 settings.setDatabaseEnabled(true);//数据库存储API是否可用,默认值false。 settings.setSaveFormData(true);//WebView是否保存表单数据,默认值true。 settings.setDomStorageEnabled(true);//DOM存储API是否可用,默认false。 settings.setGeolocationEnabled(true);//定位是否可用,默认为true。 settings.setAppCacheEnabled(true);//应用缓存API是否可用,默认值false, 结合setAppCachePath(String)使用。 settings.setUseWideViewPort(true); // 将图片调整到适合WebView的大小 settings.setLoadWithOverviewMode(true); // 自适应屏幕 webView.setHorizontalScrollBarEnabled(false);//去掉webview的滚动条,水平不显示 webView.setScrollbarFadingEnabled(true); webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); webView.setOverScrollMode(View.OVER_SCROLL_NEVER); // 取消WebView中滚动或拖动到顶部、底部时的阴影
4、重新webView方法,对进度条进行监听
private void initListener() { webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return super.shouldOverrideUrlLoading(view, request); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressBar.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); progressBar.setVisibility(View.GONE); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); progressBar.setVisibility(View.GONE); } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress >= 100) { progressBar.setVisibility(View.GONE); } else { if (progressBar.getVisibility() == View.GONE) { progressBar.setVisibility(View.VISIBLE); } progressBar.setProgress(newProgress); } super.onProgressChanged(view, newProgress); } }); }
5、对外开放一些常用的属性和方法
public void loadUrl(String url) { mUrl = url; webView.loadUrl(url); } public void setProgressDrawable(@DrawableRes int id) { progressBar.setProgressDrawable(progressBar.getContext().getResources().getDrawable(id)); } public WebView getWebView() { return webView; } public String getUrl() { return mUrl; } public boolean goBack() { if (webView.canGoBack()) { webView.goBack(); return true; } return false; } public void onResume() { webView.getSettings().setJavaScriptEnabled(true); webView.onResume(); } public void onPause() { webView.getSettings().setJavaScriptEnabled(false); webView.onPause(); } public void onDestroy() { webView.setVisibility(GONE); webView.destroy(); }
下边介绍下如何使用
<com.yuyaofang.customview.WebViewWrapper android:id="@+id/webViewWrapper" android:layout_width="match_parent" android:layout_height="match_parent" /> @BindView(R.id.webViewWrapper) WebViewWrapper mWebViewWrapper; public void getData(String s) { mWebViewWrapper.loadUrl(s); } @Override public void onResume() { super.onResume(); mWebViewWrapper.onResume(); } @Override public void onPause() { super.onPause(); mWebViewWrapper.onPause(); } @Override public void onDestroy() { mWebViewWrapper.onDestroy(); super.onDestroy(); }
有网友提出视频全屏怎么设置,封装类只配置最基本的,用到了在当前页面扩展,下边演示下视频全屏配置
public class EswVideoActivity extends Activity { @BindView(R.id.back) LinearLayout mBack; @BindView(R.id.tv_title) TextView mTvTitle; @BindView(R.id.tv_right) TextView mTvRight; @BindView(R.id.rlt_base) RelativeLayout mRltBase; @BindView(R.id.webview) WebViewWrapper mWebview; private CustomViewCallback customViewCallback; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_esw_video); ButterKnife.bind(this); mWebview.getWebView().setWebChromeClient(new DefaultWebChromeClient()); // 播放视频 mWebview.getWebView().loadUrl("http://www.iqiyi.com/fun/20130304/8d2c9f0e9505369e.html"); } private class DefaultWebChromeClient extends WebChromeClient { // 进入全屏的时候 @Override public void onShowCustomView(View view, CustomViewCallback callback) { // 赋值给callback customViewCallback = callback; // 设置webView隐藏 mWebview.getWebView().setVisibility(View.GONE); // 将video放到当前视图中 mWebview.getFragment().addView(view); // 横屏显示 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // 设置全屏 setFullScreen(); } // 退出全屏的时候 @Override public void onHideCustomView() { if (customViewCallback != null) { // 隐藏掉 customViewCallback.onCustomViewHidden(); } // 用户当前的首选方向 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // 退出全屏 quitFullScreen(); // 设置WebView可见 mWebview.getWebView().setVisibility(View.VISIBLE); } } /** * 设置全屏 */ private void setFullScreen() { mRltBase.setVisibility(View.GONE); // 设置全屏的相关属性,获取当前的屏幕状态,然后设置全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 全屏下的状态码:1098974464 // 窗口下的状态吗:1098973440 } /** * 退出全屏 */ private void quitFullScreen() { mRltBase.setVisibility(View.VISIBLE); // 声明当前屏幕状态的参数并获取 final WindowManager.LayoutParams attrs = getWindow().getAttributes(); attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().setAttributes(attrs); getWindow() .clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } // 手机返回键监听 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_BACK: // 如果是全屏状态 按返回键则变成非全屏状态,否则执行返回操作 if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); quitFullScreen(); } else { if (mWebview.getWebView().canGoBack()) { mWebview.getWebView().goBack(); } else { finish(); } } return true; default: break; } return false; } @Override public void onResume() { super.onResume(); mWebview.onResume(); } @Override public void onPause() { super.onPause(); mWebview.onPause(); } @Override public void onDestroy() { mWebview.onDestroy(); super.onDestroy(); } }
全部代码如下
import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.support.annotation.DrawableRes; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.FrameLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; import com.yuyaofang.R; /** * Created by lp on 2017/2/15. */ @SuppressLint("SetJavaScriptEnabled") public class WebViewWrapper extends RelativeLayout { private WebView webView; private ProgressBar progressBar; private FrameLayout frameLayout; private String mUrl; public WebViewWrapper(Context context) { this(context, null); } public WebViewWrapper(Context context, AttributeSet attrs) { this(context, attrs, 0); } public WebViewWrapper(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); initWebViewSettings(); initListener(); } private void initView(Context context) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.layout_webview, this); webView = (WebView) view.findViewById(R.id.webView); progressBar = (ProgressBar) view.findViewById(R.id.progressBar); frameLayout = (FrameLayout) view.findViewById(R.id.frameLayout); } private void initWebViewSettings() { WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); // 默认false,设置true后我们才能在WebView里与我们的JS代码进行交互 settings.setJavaScriptCanOpenWindowsAutomatically(true); // 设置JS是否可以打开WebView新窗口 settings.setSupportZoom(true); // 支持缩放 settings.setBuiltInZoomControls(true); // 支持手势缩放 settings.setDisplayZoomControls(false); // 不显示缩放按钮 settings.setDatabaseEnabled(true);//数据库存储API是否可用,默认值false。 settings.setSaveFormData(true);//WebView是否保存表单数据,默认值true。 settings.setDomStorageEnabled(true);//DOM存储API是否可用,默认false。 settings.setGeolocationEnabled(true);//定位是否可用,默认为true。 settings.setAppCacheEnabled(true);//应用缓存API是否可用,默认值false, 结合setAppCachePath(String)使用。 settings.setUseWideViewPort(true); // 将图片调整到适合WebView的大小 settings.setLoadWithOverviewMode(true); // 自适应屏幕 webView.setHorizontalScrollBarEnabled(false);//去掉webview的滚动条,水平不显示 webView.setScrollbarFadingEnabled(true); webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); webView.setOverScrollMode(View.OVER_SCROLL_NEVER); // 取消WebView中滚动或拖动到顶部、底部时的阴影 } private void initListener() { webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return super.shouldOverrideUrlLoading(view, request); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressBar.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); progressBar.setVisibility(View.GONE); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); progressBar.setVisibility(View.GONE); } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress >= 100) { progressBar.setVisibility(View.GONE); } else { if (progressBar.getVisibility() == View.GONE) { progressBar.setVisibility(View.VISIBLE); } progressBar.setProgress(newProgress); } super.onProgressChanged(view, newProgress); } }); } public void loadUrl(String url) { mUrl = url; webView.loadUrl(url); } public void setProgressDrawable(@DrawableRes int id) { progressBar.setProgressDrawable(progressBar.getContext().getResources().getDrawable(id)); } public WebView getWebView() { return webView; } public FrameLayout getFragment() { return frameLayout; } public String getUrl() { return mUrl; } public boolean goBack() { if (webView.canGoBack()) { webView.goBack(); return true; } return false; } public void onResume() { webView.getSettings().setJavaScriptEnabled(true); webView.onResume(); } public void onPause() { webView.getSettings().setJavaScriptEnabled(false); webView.onPause(); } public void onDestroy() { webView.setVisibility(GONE); webView.destroy(); } }
进度条样式如下
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape> <gradient android:endColor="@color/colorTransparent" android:startColor="@color/colorTransparent"/> </shape> </item> <item android:id="@android:id/progress"> <clip> <shape> <gradient android:endColor="@color/colorAccent" android:startColor="@color/colorPrimary"/> </shape> </clip> </item> </layer-list>
最后,祝大家开发顺利!