So verbinden Sie die PhotoSwipe-Galerie in der Android-Webansicht

Ich bin kein professioneller Entwickler, obwohl ich als Programmierer studiert habe. Jetzt arbeite ich als Systemadministrator und plane, zu den Entwicklern zu wechseln. Ich schreibe für mich selbst eine Anwendung, die eine der beliebtesten IT-bezogenen Websites analysiert und Artikel in der nativen Android-Anwendung anzeigt. Ich wollte, dass alle Bilder im Artikel in der Galerie geöffnet werden, wie in der mobilen Anwendung von habr.

Höchstwahrscheinlich wird sich das Handbuch als einfach herausstellen, aber ich möchte Feedback erhalten, und höchstwahrscheinlich wird dieses Handbuch für jemanden nützlich sein.

Ich habe mehrere Plugins ausprobiert. Einige wurden nicht gestartet, andere erfordern jQuery, was das Laden der Seite in der Anwendung verlangsamt. Am Ende habe ich das PhotoSwipe-Plugin gewählt. Das Plugin benötigt kein jQuery, es funktioniert schnell und wiegt fast nichts.

Zuerst müssen Sie sich überlegen, wo es besser ist, die Plugin-Quelldateien in der Anwendung zu platzieren. Aus Unerfahrenheit habe ich die Dateien zunächst im Rohordner abgelegt, aber es ist besser, sie im Assets-Ordner abzulegen. Klicken Sie mit der rechten Maustaste auf App → Neu → Ordner → Assets-Ordner

Das Markup ist eine einfache WebView:

Code
<?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> 


Als Nächstes müssen Sie das Repository von PhotoSwipe herunterladen oder klonen (Link auf der Plugin-Website) und den gesamten Inhalt des dist-Ordners in Assets kopieren (dist kann in PhotoSwipe umbenannt werden. Sie können auch eine style.css-Datei im css-Ordner erstellen, sodass die Bilder die gesamte Breite einnehmen.

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

Für die Galerie müssen Sie Stile, Javascipt-Dateien und eine Stildatei für den Skin verbinden. Sie können HTML generieren:

Hier geht HTML für Webview hin
 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(); 
.

Damit das Plugin funktioniert, müssen Sie auch den Container für die Galerie in die Quelle der Seite einfügen. Die Dokumentation besagt, dass dies kein einfaches Plugin ist und Sie einen Teil der Arbeit selbst erledigen müssen.

Es ist ratsam, den Code vor dem schließenden Tag einzufügen

Galerie-Container
 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>"; } 


Die Dokumentation enthält ein Beispiel für die Aktivierung des Plugins durch Klicken auf das Bild. Es wird jedoch darauf hingewiesen, dass es PhotoSwipe egal ist, wie genau es gestartet wird. Als Ergebnis habe ich mein Skript geschrieben. Ich zeige einen Artikel von einer anderen Website in der Anwendung an, damit ich vorgefertigtes HTML erhalte. Um nicht dynamisch mit dem Layout zu arbeiten, ändere ich in meinem Skript die Klasse für alle Bilder (da der Artikel definitiv keine Exzesse enthält), weise einen Ereignishandler zu (beim Klicken wird die URL übergeben - sie dient als Kennung für die Galerie und das Plug-In startet).

Das Plugin muss die Größe des Bildes kennen. Da die Galerie beim Laden der gesamten Seite verbunden ist, können Sie die endgültigen Bildgrößen anhand der Eigenschaften naturalWidth und naturalHeight des Bildes leicht ermitteln.

Skriptcode. Wenn die Seite geladen wird, wird zunächst die Funktion init () gestartet. Wenn Sie dann auf das Bild klicken, öffnen Sie die Galerie ().

Code
 //         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(); } 


Als Nächstes müssen Sie WebView konfigurieren und die Seite laden.

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

In diesem Stadium wird die Seite geladen, das Plugin startet, wenn Sie auf das Bild klicken. Wenn Sie jedoch bei geöffneter Galerie auf die Schaltfläche "Zurück" klicken, wird die gesamte Anwendung geschlossen, nicht das Plugin.

Um dies zu beheben, habe ich eine Javascipt-Brücke gebaut.

Zuerst müssen Sie Singleton mit dem Status der Galerie erstellen.

Code
 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; } } 


Weitere Schnittstelle zum Aufrufen von WebView

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


Sie müssen diese Schnittstelle mit WebView verbinden

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

Im Skript zum Öffnen der Galerie müssen Sie hinzufügen
 callAndroid.setGallery(true); 


Das Skript zum Schließen der Galerie in der Datei photoswipe.js

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


Wenn Sie jetzt die Galerie öffnen, wird der Status auf true gesetzt, wenn er geschlossen ist, auf false. Sie müssen lediglich den Back-Button-Handler WebView hinzufügen.

Code
 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; } }); 


Jetzt kann die Galerie mit der Zurück-Taste geöffnet und dann geschlossen werden.

Vollständiger Github- App-Code.

Kritik am Kodex ist willkommen. Wenn ich etwas falsch gemacht habe, schreibe bitte in den Kommentaren darüber.

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


All Articles