如何在Android WebView中连接PhotoSwipe画廊

尽管我是一名程序员,但我不是专业的开发人员。 现在,我以系统管理员的身份工作,并计划移交给开发人员。 我正在为自己编写一个应用程序,该应用程序可以解析与IT相关的热门网站之一,并在本机android应用程序中显示文章。 我希望像habr移动应用程序一样,在画廊中打开文章中的所有图片。

手册很可能会变得很简单,但是我想获得反馈,并且很可能该手册对某人有用。

我尝试了几个插件。 有些没有启动,有些则需要jQuery,这减慢了应用程序中页面的加载速度。 最后,我选择了PhotoSwipe插件。 该插件不需要jQuery,它可以快速运行并且几乎没有重量。

首先,您需要考虑在应用程序中的哪个位置放置插件的源文件更好。 首先,由于经验不足,我将文件放在原始文件夹中,但最好将它们放在资产文件夹中。 右键单击应用程序→新建→文件夹→资产文件夹

标记将是一个简单的WebView:

代号
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent"></WebView> </android.support.constraint.ConstraintLayout> 


接下来,您需要从PhotoSwipe下载或克隆存储库(插件网站上的链接),然后将dist文件夹的全部内容复制到资产(可以将dist重命名为PhotoSwipe。也可以在css文件夹中创建style.css文件,以便图像占据整个宽度。

 img { width: 100%; height: auto; } 

对于图库,您需要连接样式,javascipt文件和外观样式文件。 您可以生成html:

这是用于webview的html的去向
 public String getHTML() { String header = "<!DOCTYPE HTML><HTML><head><title>test</title>"; //  ,      //     . String headerEnd = "</head><body onload=\"init();\">"; String footer = "</body></HTML>"; String charset = "<meta charset=\"utf-8\">"; String style = "<link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\" />"; String pscss = "<link rel=\"stylesheet\" href=\"PhotoSwipe/photoswipe.css\">"; String psdscss = "<link rel=\"stylesheet\" href=\"PhotoSwipe/default-skin/default-skin.css\">"; // ,        String script = "<script type=\"text/javascript\" src=\"js/script.js\"></script>"; String psjs = "<script src=\"PhotoSwipe/photoswipe.js\"></script> "; String psuijs = "<script src=\"PhotoSwipe/photoswipe-ui-default.min.js\"></script>"; StringBuilder stringBuilder = new StringBuilder(); //  head stringBuilder.append(header); stringBuilder.append(charset); stringBuilder.append(style); stringBuilder.append(pscss); stringBuilder.append(psdscss); stringBuilder.append(script); stringBuilder.append(psjs); stringBuilder.append(psuijs); stringBuilder.append(headerEnd); stringBuilder.append("<img src=\"https://ps.denko.me/images/linux1.jpg\" />"); stringBuilder.append("<img src=\"https://ps.denko.me/images/linux2.jpg\" />"); stringBuilder.append("<img src=\"https://ps.denko.me/images/linux3.jpeg\" />"); stringBuilder.append(getPhotoSwipeHTML()); stringBuilder.append(footer); return stringBuilder.toString(); 


为了使插件正常工作,您还需要将图库的容器插入页面的源中。 文档说这不是一个简单的插件,您需要自己做一些工作。

建议在结束标记之前插入代码

画廊容器
 public String getPhotoSwipeHTML() { return "<!-- Root element of PhotoSwipe. Must have class pswp. -->\n" + "<div class=\"pswp\" tabindex=\"-1\" role=\"dialog\" aria-hidden=\"true\">\n" + "\n" + " <!-- Background of PhotoSwipe. \n" + " It's a separate element as animating opacity is faster than rgba(). -->\n" + " <div class=\"pswp__bg\"></div>\n" + "\n" + " <!-- Slides wrapper with overflow:hidden. -->\n" + " <div class=\"pswp__scroll-wrap\">\n" + "\n" + " <!-- Container that holds slides. \n" + " PhotoSwipe keeps only 3 of them in the DOM to save memory.\n" + " Don't modify these 3 pswp__item elements, data is added later on. -->\n" + " <div class=\"pswp__container\">\n" + " <div class=\"pswp__item\"></div>\n" + " <div class=\"pswp__item\"></div>\n" + " <div class=\"pswp__item\"></div>\n" + " </div>\n" + "\n" + " <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->\n" + " <div class=\"pswp__ui pswp__ui--hidden\">\n" + "\n" + " <div class=\"pswp__top-bar\">\n" + "\n" + " <!-- Controls are self-explanatory. Order can be changed. -->\n" + "\n" + " <div class=\"pswp__counter\"></div>\n" + "\n" + " <button class=\"pswp__button pswp__button--close\" title=\"Close (Esc)\"></button>\n" + "\n" + " <button class=\"pswp__button pswp__button--share\" title=\"Share\"></button>\n" + "\n" + " <button class=\"pswp__button pswp__button--fs\" title=\"Toggle fullscreen\"></button>\n" + "\n" + " <button class=\"pswp__button pswp__button--zoom\" title=\"Zoom in/out\"></button>\n" + "\n" + " <!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->\n" + " <!-- element will get class pswp__preloader--active when preloader is running -->\n" + " <div class=\"pswp__preloader\">\n" + " <div class=\"pswp__preloader__icn\">\n" + " <div class=\"pswp__preloader__cut\">\n" + " <div class=\"pswp__preloader__donut\"></div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + "\n" + " <div class=\"pswp__share-modal pswp__share-modal--hidden pswp__single-tap\">\n" + " <div class=\"pswp__share-tooltip\"></div> \n" + " </div>\n" + "\n" + " <button class=\"pswp__button pswp__button--arrow--left\" title=\"Previous (arrow left)\">\n" + " </button>\n" + "\n" + " <button class=\"pswp__button pswp__button--arrow--right\" title=\"Next (arrow right)\">\n" + " </button>\n" + "\n" + " <div class=\"pswp__caption\">\n" + " <div class=\"pswp__caption__center\"></div>\n" + " </div>\n" + "\n" + " </div>\n" + "\n" + " </div>\n" + "\n" + "</div>"; } 


该文档提供了有关如何通过单击图像来启用插件的示例,但是请注意,PhotoSwipe并不在乎其启动的确切程度。 结果,我写了我的脚本。 我正在应用程序中显示别人网站上的文章,所以我准备了现成的html。 为了不动态处理布局,在我的脚本中,我更改了所有图像的类(因为在文章中肯定没有多余的图像),分配了一个事件处理程序(单击时传递了url-它用作图库的标识符,并且插件启动)。

插件需要知道图像的大小。 由于画廊是在加载整个页面时连接的,因此很容易通过图像的naturalWidth和naturalHeight属性找出图像的最终尺寸。

脚本代码。 首先,在页面加载时,init()函数启动; 然后,当您单击图像上的openGallery()。

代号
 //         function init() { var images = document.images; for (var i = 0; i < images.length; i++) { images[i].className = "photoSwipe"; images[i].onclick = function () { openGalery(this.attributes["src"].value); } } } //    function openGalery(url) { var images = document.getElementsByClassName("photoSwipe"); var items = new Array(); for (var i = 0; i < images.length; i++) { items.push(getAttributes(images[i])); } startPhotoSwipe(items, getIndex(images, url)); } //    function getAttributes(image) { return { src: image.attributes["src"].value, w: image.naturalWidth, h: image.naturalHeight } } //   ,    function getIndex(images, url) { for(var i = 0; i < images.length; i++) { if (url == images[i].attributes["src"].value) return i; } return false; } //   function startPhotoSwipe(items, index) { var pswpElement = document.querySelectorAll('.pswp')[0]; // define options (if needed) var options = { // optionName: 'option value' // for example: index: index, // start at index slide bgOpacity: 0.9, pinchToClose: false, fullscreenEl: false, closeEl:false, zoomEl: false, shareEl: false, indexIndicatorSep: '  ', tapToClose: true }; callAndroid.setGallery(true); //     Java  ,    // Initializes and opens PhotoSwipe var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options); gallery.init(); } 


接下来,您需要配置WebView并加载页面。

 webView = findViewById(R.id.webView); webView.setWebViewClient(new WebViewClient()); webView.setWebChromeClient(new WebChromeClient()); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setDomStorageEnabled(true); 

在此阶段,页面加载完成,当您单击图像时,插件将启动,但是在图库打开的情况下按返回按钮时,整个应用程序将关闭,而不是插件。

为了解决这个问题,我做了一个Javascipt桥。

首先,您需要使图库状态为单例。

代号
 package me.denko.photoswipe; class GalleryState { private static final GalleryState ourInstance = new GalleryState(); static GalleryState getInstance() { return ourInstance; } private GalleryState() { } private boolean isGallery = false; public boolean isGallery() { return isGallery; } public void setGallery(boolean gallery) { isGallery = gallery; } } 


从WebView调用的进一步接口

代号
 package me.denko.photoswipe; import android.webkit.JavascriptInterface; public class JavascriptFromWebView { @JavascriptInterface public static void setGallery(boolean bool) { GalleryState.getInstance().setGallery(bool); } } 


您需要将此接口连接到WebView

 webView.addJavascriptInterface(new JavascriptFromWebView(), "callAndroid"); 

在打开图库的脚本中,您需要添加
 callAndroid.setGallery(true); 


photoswipe.js文件中的画廊关闭脚本

代号
 close: function() { if(!_isOpen) { return; } callAndroid.setGallery(false); //    _isOpen = false; _isDestroying = true; _shout('close'); _unbindEvents(); _showOrHide(self.currItem, null, true, self.destroy); }, 


现在,当您打开图库时,状态设置为true,关闭时为false。 剩下的就是添加webview按钮单击器。

代号
 webView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() != KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) { if (GalleryState.getInstance().isGallery()) { webView.reload(); GalleryState.getInstance().setGallery(false); } else onBackPressed(); } return true; } }); 


现在可以打开画廊,然后使用“后退”按钮将其关闭。

完整的github应用代码。

欢迎对代码进行批评。 如果我做错了什么,请在评论中写下。

Source: https://habr.com/ru/post/zh-CN454578/


All Articles