Bola flotante de artículo de WeChat de alta imitación.
En la última versión 6.6.7 de WeChat, se agregó una nueva función de bola flotante para artículos. Mientras lees el artículo, un amigo de repente te envía un mensaje urgente y debes responder de inmediato. O tal vez esté pasando por una cafetería y necesite abrir temporalmente el pago de WeChat o interrumpir temporalmente la lectura. En el pasado, solo podía salir de la página de detalles del artículo y, después de terminar mi trabajo, podía encontrar el artículo original uno al lado del otro. Para los grandes usuarios de WeChat como nosotros, es realmente doloroso cada vez que nos encontramos con esta situación. Por lo tanto, cuando se lanzó esta función, se actualizó inmediatamente a la última versión. Esta función se siente como encontrarse con un amigo cercano y es muy fácil de usar. Puedes sentirlo a través de la animación a continuación.
De hecho, el concepto de bolas flotantes existe desde hace mucho tiempo. Por ejemplo, la bola de monitoreo de tráfico del Asistente 360, el AssistiveTouch del iPhone (esa linda bolita blanca), etc.
Si te gusta la dirección de Github, haz clic en ella ❤️
Después de experimentarlo, me pican las manos y no puedo evitar querer imitarlo. Si su aplicación puede integrar esta función, creo que puede elevarla instantáneamente a un nuevo nivel. Bien, analicemos uno por uno los puntos técnicos centrales del artículo de WeChat sobre la bola flotante:
Cuando usamos el gesto del borde de la pantalla para abrir la vista, habrá un mensaje de esquina redondeada en la esquina inferior derecha, que se mueve con el progreso del gesto. ¿Cómo obtener el progreso de UIScreenEdgePanGestureRecognizer
? Debido a que interactivePopGestureRecognizer
que viene con el sistema está encapsulado, no podemos vincular su acción para que el gesto progrese en su interior. Por lo tanto, necesitamos encontrar otra manera.
self . interactivePopGestureRecognizer ? . delegate = self
func gestureRecognizer ( _ gestureRecognizer : UIGestureRecognizer , shouldRecognizeSimultaneouslyWith otherGestureRecognizer : UIGestureRecognizer ) -> Bool {
return true
}
UIScreenEdgePanGestureRecognizer
al UINavigationController para obtener el progreso del gesto emergente. let gesture = UIScreenEdgePanGestureRecognizer ( target : self , action : #selector ( handleNavigationTransition ( gesture : ) ) )
gesture . edges = . left
self . view . addGestureRecognizer ( gesture )
De esta manera, hay dos UIScreenEdgePanGestureRecognizer
que pueden responder al mismo tiempo. El que viene con el sistema aún mantiene la lógica original, y el nuevo que agregamos se usa para obtener el progreso del gesto pop. armonía y disfrute. Esta técnica mía también se utiliza en este artículo sobre iOS: integrar páginas de perfil de aplicaciones convencionales (como Jianshu, Weibo, etc.) en un minuto.
Dado que la bola flotante se puede suspender en cualquier página, debe colocarse en una nueva UIWindow. Por ejemplo, cuando aparece el teclado del sistema, está alojado en UIRemoteKeyboardWindow
. Entonces el ciclo de vida de esta ventana no depende de una página determinada, por lo que es mejor usar un singleton para implementarlo. Este fragmento de código está relativamente disperso. Puede comprenderlo mirando directamente el código fuente.
override func point ( inside point : CGPoint , with event : UIEvent ? ) -> Bool {
let roundEntryViewPoint = self . convert ( point , to : roundEntryView )
if roundEntryView . point ( inside : roundEntryViewPoint , with : event ) == true {
return true
}
let collectViewPoint = self . convert ( point , to : collectView )
if collectView . point ( inside : collectViewPoint , with : event ) == true {
return true
}
return false
}
UIBezierPath
y luego use el método contains(point)
de CGPath
para determinar. func updateBGLayerPath ( isSmall : Bool ) {
var ratio : CGFloat = 1
if !isSmall {
ratio = 1.3
}
let path = UIBezierPath ( )
path . move ( to : CGPoint ( x : viewSize . width , y : ( 1 - ratio ) * viewSize . height ) )
path . addLine ( to : CGPoint ( x : viewSize . width , y : viewSize . height ) )
path . addLine ( to : CGPoint ( x : ( 1 - ratio ) * viewSize . width , y : viewSize . height ) )
path . addArc ( withCenter : CGPoint ( x : viewSize . width , y : viewSize . height ) , radius : viewSize . width*ratio , startAngle : CGFloat ( Double . pi ) , endAngle : CGFloat ( Double . pi*3 / 2 ) , clockwise : true )
path . close ( )
bgLayer . path = path . cgPath
}
override func point ( inside point : CGPoint , with event : UIEvent ? ) -> Bool {
return bgLayer . path! . contains ( point )
}
Los estudiantes que no sepan mucho sobre este tema pueden consultar este artículo. Un artículo para comprender el uso de entrega de eventos, cadena de respuesta, hitTest y pointInside
Puede ver que el artículo que se abre al hacer clic en la bola flotante se implementa mediante una animación de transición personalizada, comenzando desde la posición de la bola flotante. Hay muchos artículos que explican cómo personalizar la animación de transición, pero le recomiendo que lea este artículo para integrar rápidamente efectos de transición personalizados + controlador de gestos completo con unas pocas líneas de código.
La bola flotante de WeChat utiliza relativamente muchos puntos técnicos y el código está relativamente disperso. Si su aplicación desea integrar esta función, debe empaquetar el código con cuidado. Creo que cómo diseñar un requisito es más importante que cómo implementarlo. En el proceso de imitación, descubrí que hay muchas lógicas detalladas que se entrelazan entre sí, y finalmente se presenta la función de bola flotante que estás utilizando. Se dice que los programadores y los gerentes de producto están enamorados el uno del otro. Aquí quiero darle el visto bueno al gerente de producto de esta función.
Si hay algún problema con el código o si tiene alguna pregunta, puede enviarme sus comentarios y lo solucionaré lo antes posible. Si te gusta la dirección de Github, haz clic en ella ❤️