Cómo conectar la galería PhotoSwipe en la vista web de Android

No soy un desarrollador profesional, aunque estudié como programador. Ahora trabajo como administrador del sistema y planeo pasar a los desarrolladores. Estoy escribiendo para mí una aplicación que analiza uno de los sitios web populares relacionados con TI y muestra artículos en la aplicación nativa de Android. Quería que todas las imágenes del artículo se abrieran en la galería, como en la aplicación móvil habr.

Lo más probable es que el manual resulte simple, pero quiero recibir comentarios y, muy probablemente, este manual será útil para alguien.

Probé varios complementos. Algunos no comenzaron, otros requieren jQuery, y esto ralentiza la carga de la página en la aplicación. Al final, elegí el complemento PhotoSwipe. el complemento no requiere jQuery, funciona rápidamente y no pesa casi nada.

Primero debe pensar en qué parte de la aplicación es mejor colocar los archivos fuente del complemento. Primero, por inexperiencia, puse los archivos en la carpeta sin procesar, pero es mejor colocarlos en la carpeta de activos. Haga clic derecho en la aplicación → nueva → carpeta → Carpeta de activos

El marcado será un simple WebView:

Código
<?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> 


A continuación, debe descargar o clonar el repositorio de PhotoSwipe (enlace en el sitio web del complemento) y copiar todo el contenido de la carpeta dist a los activos (dist puede renombrarse a PhotoSwipe. También puede crear un archivo style.css en la carpeta css para que las imágenes ocupen todo el ancho.

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

Para la galería, necesita conectar estilos, archivos javascipt y un archivo de estilo para el skin. Puedes generar html:

Aquí es donde va el html para webview
 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(); 
.

Para que el complemento funcione, también debe insertar el contenedor de la galería en la fuente de la página. La documentación dice que este no es un complemento simple y que usted debe hacer parte del trabajo usted mismo.

Es recomendable insertar el código antes de la etiqueta de cierre

Contenedor de galería
 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>"; } 


La documentación proporciona un ejemplo de cómo habilitar el complemento haciendo clic en la imagen, pero se observa que a PhotoSwipe no le importa cómo comienza exactamente. Como resultado, escribí mi guión. Estoy mostrando un artículo del sitio de otra persona en la aplicación, así que obtengo html listo. Para no trabajar dinámicamente con el diseño, en mi script cambio la clase para todas las imágenes (porque definitivamente no hay excesos en el artículo), asigno un controlador de eventos (cuando se hace clic, se pasa la url; sirve como un identificador para la galería y se inicia el complemento).

El complemento necesita saber el tamaño de la imagen. Dado que la galería está conectada cuando se carga toda la página, es fácil encontrar los tamaños finales de las imágenes a través de las propiedades naturalWidth y naturalHeight de la imagen.

Código de script Primero, cuando se carga la página, se inicia la función init (); Luego, cuando haces clic en la imagen, abre Galería ().

Código
 //         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(); } 


A continuación, debe configurar WebView y cargar la página.

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

En esta etapa, la página se carga, el complemento comienza cuando hace clic en la imagen, pero cuando presiona el botón Atrás con la galería abierta, se cierra toda la aplicación, no el complemento.

Para arreglar esto, hice un puente Javascipt.

Primero necesitas hacer singleton con el estado de la galería.

Código
 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; } } 


Interfaz adicional para llamar desde WebView

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


Necesita conectar esta interfaz a WebView

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

En el script para abrir la galería, debe agregar
 callAndroid.setGallery(true); 


El script de cierre de la galería en el archivo photoswipe.js

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


Ahora, cuando abre la galería, el estado se establece en verdadero, cuando está cerrado, falso. Todo lo que queda es agregar el controlador de botón de retroceso para WebView.

Código
 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; } }); 


Ahora la galería se puede abrir y luego cerrar con el botón Atrás.

Código completo de la aplicación github .

Las críticas al código son bienvenidas. Si hice algo mal, escríbalo en los comentarios.

Source: https://habr.com/ru/post/454578/


All Articles