Bola flutuante de artigo WeChat de alta imitação
Na última versão 6.6.7 do WeChat, um novo artigo sobre a função de bola flutuante foi adicionado. Enquanto você lê o artigo, um amigo envia de repente uma mensagem urgente e você precisa responder imediatamente. Ou talvez você esteja passando por uma lanchonete e precise abrir temporariamente o pagamento do WeChat ou interromper temporariamente a leitura. No passado, eu só conseguia sair da página de detalhes do artigo e, após terminar meu trabalho, encontrava o artigo original um ao lado do outro. Para usuários frequentes do WeChat como nós, é muito doloroso cada vez que nos deparamos com essa situação. Portanto, quando esta função foi lançada, ela foi imediatamente atualizada para a versão mais recente. Esta função é como encontrar um amigo próximo e é muito fácil de usar. Você pode sentir isso através da animação abaixo
Na verdade, o conceito de bolas flutuantes já existe há muito tempo. Por exemplo, a bola de monitoramento de tráfego do 360 Assistant, o AssistiveTouch do próprio iPhone (aquela bolinha branca fofa), etc.
Se você gostou do endereço do Github, clique nele ❤️
Depois de experimentar isso, minhas mãos coçam e não posso deixar de querer imitá-lo. Se o seu APP puder integrar essa função, acho que ele poderá elevar instantaneamente o seu APP a um novo nível. Ok, vamos dissecar os principais pontos técnicos da bola flutuante do artigo do WeChat, um por um:
Quando usamos o gesto de borda da tela para abrir a visualização, haverá um prompt de canto arredondado no canto inferior direito, que se move com o progresso do gesto. Como obter o progresso do UIScreenEdgePanGestureRecognizer
? Como interactivePopGestureRecognizer
que vem com o sistema é encapsulado, não podemos vincular sua ação para obter o progresso do gesto dentro dele. Portanto, precisamos encontrar outro caminho.
self . interactivePopGestureRecognizer ? . delegate = self
func gestureRecognizer ( _ gestureRecognizer : UIGestureRecognizer , shouldRecognizeSimultaneouslyWith otherGestureRecognizer : UIGestureRecognizer ) -> Bool {
return true
}
UIScreenEdgePanGestureRecognizer
ao UINavigationController para obter o progresso do gesto pop. let gesture = UIScreenEdgePanGestureRecognizer ( target : self , action : #selector ( handleNavigationTransition ( gesture : ) ) )
gesture . edges = . left
self . view . addGestureRecognizer ( gesture )
Desta forma, existem dois UIScreenEdgePanGestureRecognizer
que podem responder ao mesmo tempo. O que acompanha o sistema ainda mantém sua lógica original, e o novo que adicionamos é utilizado para obter o andamento do gesto pop. harmonia entre si e são felizes. Esta minha técnica também é usada neste artigo no iOS: Integrar páginas de perfil de APP convencionais (como Jianshu, Weibo, etc.) em um minuto
Como a bola flutuante pode ser suspensa em qualquer página, ela deve ser colocada em uma nova UIWindow. Por exemplo, quando o teclado do sistema aparece, ele é hospedado por UIRemoteKeyboardWindow
. Então o ciclo de vida desta janela não depende de uma determinada página, então é melhor usar um singleton para implementá-la. Este trecho de código está relativamente disperso. Você pode entendê-lo olhando diretamente para o código-fonte.
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
e, em seguida, use o 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 )
}
Os alunos que não sabem muito sobre este tópico podem consultar este artigo. Um artigo para entender o uso de entrega de eventos, cadeia de resposta, hitTest e pointInside
Você pode ver que o artigo aberto ao clicar na bola flutuante é implementado por meio de uma animação de transição personalizada, começando na posição da bola flutuante. Existem muitos artigos explicando como personalizar a animação de transição, mas recomendo que você leia este artigo para integrar rapidamente efeitos de transição personalizados + driver de gesto completo com algumas linhas de código
A bola flutuante do WeChat usa relativamente muitos pontos técnicos e o código é relativamente disperso. Se o seu APP quiser integrar essa função, você precisará empacotar o código com cuidado. Acho que como projetar um requisito é mais importante do que como implementá-lo. No processo de imitação, descobri que existem muitas lógicas detalhadas, que estão interligadas e, finalmente, é apresentada a função de bola flutuante que você está usando. Diz-se que programadores e gerentes de produto estão apaixonados. Quero dar um sinal de positivo ao gerente de produto desta função.
Se houver algum problema no código ou se você tiver alguma dúvida, pode me dar um feedback e eu tratarei disso o mais rápido possível. Se você gostou do endereço do Github, clique nele ❤️