CALayer render(in context:) rendert komische/keine Inhalte, wenn im darunter liegenden ImageView nichts angezeigt ist

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • CALayer render(in context:) rendert komische/keine Inhalte, wenn im darunter liegenden ImageView nichts angezeigt ist

    Gutem Morgen zusammen,

    ich bin letzte Woche über ein problem gestolpert, zu der ich vorerst auf StackOverflow nach einer Lösung gesucht/gefragt habe. Leider bisher ohne Erfolg. Zum Nachvollziehen (mit Screenshots) hab ich euch den Post mal verlinkt.

    Der Anwendungsfall
    Damit ihr mir grob folgen könnt und versteht, was ich erreichen möchte, skizziere ich euch kurz den konkreten Anwendungsfall.
    1. Das Modul der App ist als SplitView aufgebaut und am iPad wurde mit hilfe von UIDrag- und UIDropInteraction eine Drag & Drop Funktion von einer Liste (links - Master) auf ein UIImageView (rechts - Detail) geschaffen.
    2. Damit der Nutzer besser erkennt, wo er das Element auf dem angezeigten Bild platziert, haben wir ein Lupen-Lösung umgesetzt, bei der mit render(in context:) ein vergrößerter Ausschnitt vom Ziel-View dargestellt wird. Die Lupen-Position ist immer unter dem Finger.


    Der Ablauf
    Leider ist es so, dass es aktuell in zwei Fällen zu Darstellungsproblemen kommt.
    1. Drag&Drop Geste beginnt in der Liste => Keine Lupe zu sehen, da diese zum detailView gehört
    2. Drag&Drop Geste 'betritt' den DetailView => Lupe erscheint im DetailView, aber mit schwarzem Inhalt da an der Touch-Position kein Bild-Inhalt angezeigt wird
    3. Drag&Drop Geste 'betritt' Bild-Inhalt vom UIImageView => Lupe zeigt den Inhalt korrekt und vergrößert an.
    4. Drag&Drop Geste 'verlässt' den Bild-Inhalt wieder => Lupe zeigt wiederholt den letzten BildInhalt an


    Frage
    Hat hier von euch jemand schon mal ein solches problem gehabt und erfolgreich gelöst? Am liebsten würde ich erkennen, ob es Inhalt gibt, der gerendert werden kann und ansonsten eine Platzhalter-Farbe anzeigen. Ist soetwas möglich?

    Danke & Gruß,
    Daniel
    Man kann alles schaffen. Man muss es nur wollen ;)
    www.regetskcob.github.io

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von DBocksteger ()

  • So ganz verstehe ich die Beschreibung und das daraus resultierende Problem nicht. Es gibt links eine Liste, also ein TableView? und rechts im Detailbereich einen ImageView, richtig?

    Wird in dem ImageView im Detailbereich bereits ein Bild angezeigt, welches dann in der Lupe für die aktuelle Position angezeigt werden soll?

    Was ist mit "Bereiche vom UIImageView, in denen kein Inhalt dargestellt wird" gemeint? Handelt es sich bei dem angezeigten Bild um ein PNG mit Transparenzen?

    In updateMagnifier() sehe ich kein setNeedsDisplay() oder befindet sich dies in der updateMagnifier() Funktion?

    Ich tippe jetzt mal, dass es sich bei dem Layer von WWMagnifierView um den default CALayer handelt, richtig?
  • Hey MCDan, danke für dein Feedback.

    Ich habe mal versucht die beiden Anwendungsfälle visuell zu verdeutlichen.

    Legende
    • grün: UITableView
    • blau: UIImageView
    • rot: sichtbares Bild (aufgrund von contentMode (aspectFit) und Zoom/Skalierung
    • gelb: Anderer, unwichtiger Bereich
    • weißer Kreis mit Zahl: Position vom Finger bei Drag&Drop


    Case 1.png

    Case 2.png

    Bilder der Lupe

    Hier noch passend zu den Touch-Positionen Screenshots der Lupe im jeweiligen Zustand.

    Bild zu 2)
    uCrTC.png

    Bild zu 3)
    gDZYj.png

    Bild zu 4)
    4w0h1.png

    Code

    @Admin: kann ich leider nicht hinzufügen. Öffne ich mit dem 'Code-Tool' den entsprechenden Editor und drücke speichern, öffnet er sich erneut... (Safari, aktuellstes offizielles macOS)

    Bitte für den Code einen Blick in StackOverflow werfen, habe ihn dort ergänzt...

    Grüße,
    Daniel
    Man kann alles schaffen. Man muss es nur wollen ;)
    www.regetskcob.github.io

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von DBocksteger ()

  • MCDan schrieb:

    Hast Du mal probiert den Bereich vorher per

    Quellcode

    1. UIColor.clearColor.setFill()
    2. context.fill(self.bounds)

    zu löschen?

    Tritt das Problem dann auch auf?
    Spannende Idee, das teste ich mal, Danke!

    EDIT: Nein leider nicht. Meine draw(: rect:) Funtkion sieht nun wie folgt aus.


    Quellcode

    1. override open func draw(_ rect: CGRect) {
    2. super.draw(rect)
    3. guard let magnifyingView = viewToMagnify else { fatalError("class WWMagnifierView seems to be used without having set a view to magnify.") }
    4. if touchPoint != CGPoint.zero {
    5. let context = UIGraphicsGetCurrentContext()
    6. UIColor.clear.setFill()
    7. context?.fill(self.bounds)
    8. context?.translateBy(x: 1 * (self.frame.size.width * 0.5), y: 1 * (self.frame.size.height * 0.5))
    9. context?.scaleBy(x: 1.65, y: 1.65) // 1.5 is the zoom scale
    10. context?.translateBy(x: -1 * (touchPoint.x), y: -1 * (touchPoint.y))
    11. magnifyingView.layer.render(in: context!)
    12. }
    13. }
    Alles anzeigen
    Man kann alles schaffen. Man muss es nur wollen ;)
    www.regetskcob.github.io
  • Hm, scheint dann wohl ein Problem im Renderer vom UIImageView zu sein.

    Alternativ könnte Du mal folgende Lösung probieren:

    Ich tippe mal, dass WWMagnifierView den Rahmen als Layer Border und masksToBounds verwendet, richtig?

    Du könntest jetzt diesem WWMagnifierView mal einen UIImageView als Subview hinzufügen und die Position dieses UIImageViews passend zur Position des WWMagnifierView über dem anderen UIImageView verschieben.

    Die Größe des UIImageViews musst Du halt passend zum anderen UIImageView inkl. Zoom-Faktor wählen. Dieser sollte dann 1,5 mal so groß sein.

    Dies sollte eigentlich auch funktionieren.