{"id":331844,"date":"2022-04-12T15:01:19","date_gmt":"2022-04-12T15:01:19","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=331844"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=331844","title":{"rendered":"<span>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435 \u043d\u0430 Android<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0435\u043d\u0438\u0441 \u0417\u0430\u0433\u0443\u043c\u0435\u043d\u043d\u043e\u0432, \u044f \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043b\u0435\u043d\u0442\u044b \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435. \u041c\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u043d\u043e\u0439 \u043b\u0435\u043d\u0442\u043e\u0439, \u0441\u0442\u0435\u043d\u043e\u0439, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438, \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u043c\u0438, VK Donut, \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u0433\u0440\u0430\u0444\u043e\u043c \u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0435\u0439.<\/p>\n<p>\u0412 \u0430\u0432\u0433\u0443\u0441\u0442\u0435 2021-\u0433\u043e \u043c\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0443 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0443\u0433\u0443\u0431\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439, \u0434\u043b\u044f Android-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ebb\/6bb\/3fd\/ebb6bb3fd9d14a9d1c4775d8d5b7c493.jpeg\" width=\"1770\" height=\"996\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ebb\/6bb\/3fd\/ebb6bb3fd9d14a9d1c4775d8d5b7c493.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435:<\/h3>\n<ul>\n<li>\n<p>\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u0438 \u0432\u044b\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0424\u0430\u0441\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 ReactionsView \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043f-\u0430\u043f \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u0447\u0435\u0439 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f, \u0432\u044b\u0431\u043e\u0440\u0430, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0436\u0438\u043c \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u0430 (TalkBack).<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0413\u0434\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u0438 \u0432\u044b\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u044f \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0432\u044b\u0440\u0430\u0436\u0430\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u043a \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u043e \u043e\u0434\u043d\u043e\u0439 \u044d\u0442\u043e\u0439 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0431\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u044d\u043c\u043e\u0446\u0438\u0438. \u0410 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435\u0443\u043c\u0435\u0441\u0442\u043d\u043e.\u00a0<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0430\u043a\u0446\u0438\u0439: \u0442\u0435\u043f\u0435\u0440\u044c \u0438\u0445 \u0448\u0435\u0441\u0442\u044c. \u0422\u0430\u043a \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0442\u043e\u0447\u043d\u0435\u0435 \u0438 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0447\u0443\u0432\u0441\u0442\u0432\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c.\u00a0<\/p>\n<p>\u0412 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0442\u0430\u043a: \u0434\u043e\u043b\u0433\u0438\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043f-\u0430\u043f \u0441 \u0440\u0435\u0430\u043a\u0446\u0438\u044f\u043c\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u0442\u0430\u0432\u0438\u0442 \u043d\u0443\u0436\u043d\u0443\u044e \u2014 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c, \u043d\u0435 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u044f \u043f\u0430\u043b\u0435\u0446. \u041e\u0431 \u044d\u0442\u043e\u0439 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432 Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<h3>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<p>\u0412 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043b\u0435\u043d\u0442\u044b \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c MVP, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0412\u043e <strong>View<\/strong> \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u0434\u043b\u044f <strong>RecyclerView<\/strong>, \u0430 <strong>Presenter<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u2014 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u044f\u0447\u0435\u0439\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u041a\u0430\u0436\u0434\u043e\u0439 \u0442\u0430\u043a\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0434\u0438\u043d ViewHolder.<\/p>\n<p>\u041c\u044b \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0438, \u0447\u0442\u043e\u0431\u044b <strong>RecyclerView<\/strong> \u043c\u043e\u0433 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u044c\u044e\u0445\u0438, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e \u0432\u044b\u0441\u043e\u0442\u0435.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u043c \u0438\u0437 VK Team (\u043a\u0430\u0436\u0434\u0430\u044f \u0432\u044c\u044e\u0445\u0430 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0430 \u0441\u0438\u043d\u0438\u043c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u043c):<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u0430\u0432\u0430\u0442\u0430\u0440\u043a\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0430 \u0438 \u0434\u0430\u0442\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u043a\u0441\u0442 \u043c\u043e\u0435\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043b\u043e\u0436\u0435\u043d\u0438\u0435-\u0441\u0442\u0430\u0442\u044c\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0424\u0443\u0442\u0435\u0440 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b43\/76d\/28e\/b4376d28e0cc245b756a1254bad91420.png\" width=\"1160\" height=\"1600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b43\/76d\/28e\/b4376d28e0cc245b756a1254bad91420.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f \u0434\u043e\u043b\u0433\u0438\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u044c\u044e\u0445\u0443 \u0444\u0443\u0442\u0435\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u0435\u0430\u043a\u0446\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p>\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u0432 \u043a\u043d\u043e\u043f\u043a\u0435 \u0444\u0443\u0442\u0435\u0440\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0444\u0443\u0442\u0435\u0440\u0430, \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 <strong>ReactionsFacade<\/strong>: \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0443, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440 \u0444\u0443\u0442\u0435\u0440\u0430 \u043c\u043e\u0433 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u044d\u0442\u0438\u043c \u0444\u0430\u0441\u0430\u0434\u043e\u043c.<\/p>\n<p>\u0412 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <strong>ReactionsFacade<\/strong>, \u044d\u0442\u043e\u0442 \u0444\u0430\u0441\u0430\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u0430\u0434\u0430\u043f\u0442\u0435\u0440.<\/p>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440\u044b \u0444\u0443\u0442\u0435\u0440\u0430 \u043f\u043e\u0441\u0442\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0444\u0430\u0441\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.\u00a0<\/p>\n<h3>\u0424\u0430\u0441\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/23d\/ba2\/939\/23dba2939278988d4999691a292c8bea.png\" width=\"1400\" height=\"826\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/23d\/ba2\/939\/23dba2939278988d4999691a292c8bea.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsFacade<\/strong> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u042d\u0442\u043e \u0444\u0430\u0441\u0430\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043a\u0440\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b: \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0435\u043c\u0443 \u0438\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>\u0424\u0430\u0441\u0430\u0434 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044c\u044e\u0445\u0443 <strong>ReactionsView<\/strong> \u0438 \u043a\u043e\u043d\u0444\u0438\u0433 \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u2014 <strong>ReactionsConfig<\/strong>.\u00a0<\/p>\n<p>\u041a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430: \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u043a\u0430\u0441\u0430\u043d\u0438\u0439 (\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <strong>setOnTouchListener<\/strong>); \u0430 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043d\u043e\u043f\u043a\u0443, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>View.OnTouchListener<\/strong>. \u0423 <strong>ReactionsView<\/strong> \u0435\u0441\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <strong>onTouch<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u0432\u044c\u044e\u0445\u0430, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u0451\u043b \u0442\u0430\u0447;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0442\u0430\u0447\u0430 <strong>MotionEvent<\/strong>;\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440, \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u044c\u044e\u0445\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0431\u044a\u0435\u043a\u0442, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>Reactionable<\/strong> (\u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u0441\u0442).<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 <strong>ReactionsFacade<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f <strong>ReactionsConfig<\/strong> \u2014 \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsView<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 ReactionsView \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438<\/h3>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/02f\/7a3\/70c\/02f7a370c74066c143d6c69b7b7fb9e1.png\" width=\"1600\" height=\"762\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/02f\/7a3\/70c\/02f7a370c74066c143d6c69b7b7fb9e1.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsView<\/strong> \u2014 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0432\u044c\u044e\u0445\u0430\u043c\u0438 \u0434\u043b\u044f <strong>ReactionsFacade<\/strong>.<\/p>\n<p>C\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u043a\u0430\u0437 \u043f\u043e\u043f-\u0430\u043f\u0430 <strong>ReactionsPopupWindow<\/strong> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 <strong>ShowReactionRunnable<\/strong>. ReactionsPopupWindow \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0432\u044c\u044e\u0445\u0443 ReactionsPopupView. \u0412 \u043d\u0435\u0439 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0431\u0430\u0431\u043b \u043f\u043e\u043f-\u0430\u043f\u0430 \u0438 \u0432\u0441\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<pre><code class=\"kotlin\">inner class ShowReactionRunnable(         private val reactionSet: ReactionSet ) : Runnable {     override fun run() {         val view = getAnchorView() ?: return         view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)         openPopup(view, reactionSet)     } }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u0442\u0430\u0447\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432\u043e \u0432\u044c\u044e\u0445\u0443 <strong>ReactionsPopupView<\/strong> \u2014 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u0434\u043b\u0438\u043d\u043d\u043e\u0433\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0440\u0435\u0430\u043a\u0446\u0438\u0438, \u043d\u0435 \u043e\u0442\u0440\u044b\u0432\u0430\u044f \u043f\u0430\u043b\u0435\u0446 \u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ReactionsPopupWindow<\/strong> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a <strong>PopupWindow<\/strong>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432\u044c\u044e\u0445\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 <strong>ReactionsPopupView<\/strong> \u043a \u043e\u043a\u043d\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>ReactionsPresenter<\/strong> (\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0440\u043e\u043b\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u0430) \u2014 \u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsButtonTouchDelegate<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0436\u0435\u0441\u0442\u043e\u0432 \u0441 \u043a\u043d\u043e\u043f\u043a\u0438.\u00a0<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0436\u0435\u0441\u0442\u044b:<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0421\u043a\u0440\u043e\u043b\u043b \u2014 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0442, \u0442\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0442\u0430\u0447\u0435\u0439, \u0447\u0442\u043e\u0431\u044b \u0442\u0430\u0447\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438\u0441\u044c <strong>RecyclerView<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0434\u0438\u043d\u043e\u0447\u043d\u043e\u0435 \u0438 \u0434\u043e\u043b\u0433\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u2014 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043f-\u0430\u043f \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0430\u0447\u0438 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0443\u0436\u0435 \u0432 \u0435\u0433\u043e \u0432\u044c\u044e\u0445\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e, \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 <strong>onTouch<\/strong> \u0432 <strong>ReactionsButtonTouchDelegate<\/strong>.<\/p>\n<ul>\n<li>\n<p>\u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <strong>MotionEvent.ACTION_DOWN<\/strong> \u2014 \u043c\u0435\u0442\u043e\u0434 <strong>onTouchDown<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchDown(         view: View,         viewHolder: ReactionableViewHolder,         event: MotionEvent,         model: Reactionable ): Boolean {     val activePointerId = event.getPointerId(FIRST_POINTER_INDEX)     this.view.setActivePointerId(activePointerId)     this.view.setAnchor(view, viewHolder)     scrollTouchDelegate.setEvent(event)     presenter.setModel(model)     (view.parent as? ViewGroup)?.requestDisallowInterceptTouchEvent(true)     startTime = System.currentTimeMillis()     this.view.showDelayed(model)     this.view.showRipple(event.x, event.y)     return true }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>MotionEvent.ACTION_UP<\/strong> \u2014 <strong>onTouchUp<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchUp(): Boolean {     performClickIfNeeded()     view.closePopup()     return true }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>MotionEvent.ACTION_CANCEL<\/strong><em> \u2014 <\/em><strong>onTouchCancel<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchCancel(): Boolean {     view.closePopup()     return true }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>MotionEvent.ACTION_MOVE<\/strong><em> \u2014 <\/em><strong>onTouchMove<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchMove(event: MotionEvent): Boolean {     val isScrollGesture = scrollTouchDelegate.isScroll(event)     if (isScrollGesture) {         view.closePopup()     }     return !isScrollGesture }<\/code><\/pre>\n<p>\u0418 \u0435\u0449\u0451 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ReactionsStateController<\/strong> \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 UI.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsViewSettings<\/strong> \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430.\u00a0<\/p>\n<p>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c:<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0441 \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u043c \u043e\u0442 \u044f\u043a\u043e\u0440\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0438 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043f-\u0430\u043f;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u0441\u0442\u0443\u043f\u044b \u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0432 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u0438 \u043d\u0435\u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0446\u0432\u0435\u0442 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p><strong>ReactionsCallback<\/strong> \u2014 \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0431 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430, \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0438 \u0435\u0451 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412 <strong>ReactionsView<\/strong> \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0441\u043b\u0430\u0431\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>ReactionViewHolder<\/strong> (\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441). <strong>ReactionViewHolder<\/strong> \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0432\u044c\u044e\u0445\u0443 \u0441 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u0438. \u0412\u0441\u0435 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440\u044b \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u2014 \u044d\u0442\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 <strong>ReactionViewHolder<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u043e\u043f-\u0430\u043f \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8c5\/57f\/5a1\/8c557f5a1ad40362866c5fae3dc86365.png\" width=\"2200\" height=\"1040\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8c5\/57f\/5a1\/8c557f5a1ad40362866c5fae3dc86365.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsPopupWindow<\/strong> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a <strong>PopupWindow<\/strong>. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043a \u043e\u043a\u043d\u0443 \u0432\u044c\u044e\u0445\u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u043b\u0441\u044f \u043f\u043e\u043f-\u0430\u043f \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 <strong>ReactionsPopupView<\/strong>.\u00a0<\/p>\n<p><strong>ReactionsPopupView<\/strong> \u2014 \u0432\u044c\u044e\u0445\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d. \u0412 <strong>onLayout<\/strong> \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u0441\u0430\u043c\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438. \u041f\u043e\u043f-\u0430\u043f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u043e \u0441\u043a\u0440\u043e\u043b\u043b\u043e\u043c \u2014 \u0442\u0430\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u044b. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044c\u044e\u0445\u0438, \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440 <strong>ReactionsPopupViewAnimator<\/strong> \u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0442\u0430\u0447\u0435\u0439 <strong>ReactionsPopupTouchDelegate<\/strong>.<\/p>\n<p><strong>ReactionsViewSettings<\/strong> \u2014 \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.\u00a0<\/p>\n<h3>\u0418\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 <strong>onMeasure<\/strong> \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0432\u044c\u044e\u0445\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0441 \u0440\u0435\u0430\u043a\u0446\u0438\u044f\u043c\u0438.<\/p>\n<pre><code class=\"kotlin\">override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {     val width = MeasureSpec.getSize(widthMeasureSpec)     val height = MeasureSpec.getSize(heightMeasureSpec)      val needUpdateVisibleRect = !isPopupHiding     if (!checkAnchor(needUpdateVisibleRect, width, height)) {         dismissListener?.invoke()         return     }      super.onMeasure(widthMeasureSpec, heightMeasureSpec)      measureTitles()     measurePopupWidth()      if (needUpdateVisibleRect) {         calcPopupCoordinates()     }      val popupWidthMeasureSpec = MeasureUtils.makeSpecExactly(dialogWidth)     val popupHeightMeasureSpec = MeasureUtils.makeSpecExactly(dialogHeight)     scrollView.measure(popupWidthMeasureSpec, popupHeightMeasureSpec) }<\/code><\/pre>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <strong>measureTitles<\/strong> \u0438\u0437\u043c\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432\u044c\u044e\u0445\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0434\u043f\u0438\u0441\u0435\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<pre><code class=\"kotlin\">private fun measureTitles() {     \/\/ \u0418\u0437\u043c\u0435\u0440\u044f\u0435\u043c \u0432\u0441\u0435 textView, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0432 onLayout \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e     for (index in titleViews.indices) {         titleViews[index].measure(0, 0)     } }<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <strong>measurePopupWidth<\/strong> \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u0442 \u0448\u0438\u0440\u0438\u043d\u0443 \u043f\u043e\u043f-\u0430\u043f\u0430. \u0415\u0441\u043b\u0438 \u043e\u043d\u0430 \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432, \u0442\u043e \u0438\u0442\u043e\u0433\u043e\u0432\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"kotlin\">private fun measurePopupWidth() {     when {         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 \u0434\u0438\u0430\u043b\u043e\u0433 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432         originalDialogWidth &lt; this.measuredWidth - settings.screenPaddingStart - settings.screenPaddingEnd -> {             screenPaddingStart = settings.screenPaddingStart             screenPaddingEnd = settings.screenPaddingEnd             dialogWidth = originalDialogWidth         }         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 \u0434\u0438\u0430\u043b\u043e\u0433 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432         originalDialogWidth &lt; this.measuredWidth - settings.screenPaddingSmallStart - settings.screenPaddingSmallEnd -> {             screenPaddingStart = settings.screenPaddingSmallStart             screenPaddingEnd = settings.screenPaddingSmallEnd             dialogWidth = originalDialogWidth         }         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e\u043f-\u0430\u043f \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b, \u0442\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443         \/\/ \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0432\u0438\u0434\u0438\u043c\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0431\u044b\u043b\u043e \u0432\u0438\u0434\u043d\u043e \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443         else -> {             screenPaddingStart = settings.screenPaddingStart             screenPaddingEnd = settings.screenPaddingEnd              val availableWidth = this.measuredWidth - settings.screenPaddingStart - settings.screenPaddingEnd - firstChildMarginStart             val numVisibleReactions = (availableWidth \/ dialogChildWidth - 1).coerceAtLeast(0)             dialogWidth = firstChildMarginStart + dialogChildWidth * numVisibleReactions + dialogChildWidth \/ 2         }     } }<\/code><\/pre>\n<p>\u0412 <strong>calcPopupCoordinates<\/strong> \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u043e\u043f-\u0430\u043f, \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0433\u0440\u0430\u043d\u0438\u0446 \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<pre><code class=\"kotlin\">private fun calcPopupCoordinates() {     calcPopupCoordinatesX()     calcPopupCoordinatesY() }  private fun calcPopupCoordinatesX() {     \/\/ \u041f\u043e\u043f-\u0430\u043f \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443 \u043d\u0430\u0434 \u044f\u043a\u043e\u0440\u0435\u043c     dialogX = anchorViewLocation.left - thisLocation.left + anchorWidth \/ 2 - dialogWidth \/ 2      \/\/ \u041a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c, \u0435\u0441\u043b\u0438 \u0432\u044b\u0448\u043b\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0438\u0446     when {         \/\/ \u0415\u0441\u043b\u0438 \u043b\u0435\u0432\u0430\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b, \u0442\u043e \u0441\u043c\u0435\u0449\u0430\u0435\u043c \u0432\u043f\u0440\u0430\u0432\u043e         dialogX &lt; screenPaddingStart -> {             dialogX = screenPaddingStart         }         \/\/ \u0415\u0441\u043b\u0438 \u043f\u0440\u0430\u0432\u0430\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b, \u0442\u043e \u0441\u043c\u0435\u0449\u0430\u0435\u043c \u0432\u043b\u0435\u0432\u043e         dialogX + dialogWidth > this.measuredWidth - screenPaddingEnd -> {             dialogX = this.measuredWidth - dialogWidth - screenPaddingEnd         }     } }  private fun calcPopupCoordinatesY() {     \/\/ \u0420\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043d\u0430\u0434 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438     dialogY = anchorViewLocation.top - dialogHeight - settings.anchorMarginBottom - thisLocation.top      \/\/ \u0415\u0441\u043b\u0438 \u043d\u0435\u0442 \u043c\u0435\u0441\u0442\u0430, \u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u0434 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438     if (dialogY &lt; settings.offsetTop) {         dialogY = anchorViewLocation.top + anchorHeight + settings.anchorMarginBottom - thisLocation.top     } }<\/code><\/pre>\n<h3>\u0420\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041f\u0440\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438, \u0442\u0435\u043f\u0435\u0440\u044c \u2014 \u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430. \u0412\u0441\u0451 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 <strong>onLayout<\/strong>. \u00a0<\/p>\n<pre><code class=\"kotlin\">override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {     val needUpdateVisibleRect = !isPopupHiding     \/\/ \u0415\u0441\u043b\u0438 \u044f\u043a\u043e\u0440\u044c \u043d\u0435 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0451\u043d \u043a \u043e\u043a\u043d\u0443, \u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f     \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u043d\u0435 \u043d\u0430\u0434\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435     \/\/ \u0415\u0441\u043b\u0438 \u044f\u043a\u043e\u0440\u044c \u043d\u0435 \u0432\u0438\u0434\u0435\u043d, \u0442\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f     if (!checkAnchor(needUpdateVisibleRect, this.measuredWidth, this.measuredHeight)) {         dismissListener?.invoke()         return     }      \/\/ \u0420\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441 \u0440\u0435\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0432 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445 (dialogX, dialogY)     \/\/ \u0412 dialogX \u0438 dialogY \u0443\u0436\u0435 \u0443\u0447\u0442\u0451\u043d RTL, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0443\u0442 \u0443\u0436\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0432 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445     layoutChildLeft(scrollView, dialogX, dialogY)      \/\/ \u0420\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u0438     layoutReactions(needUpdateVisibleRect) }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u043f\u0438\u0448\u0435\u043c, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f.<\/p>\n<ul>\n<li>\n<p>\u0412 <strong>checkAnchor<\/strong> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0432\u0438\u0434\u043d\u0430 \u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0430 \u043b\u0438 \u043e\u043d\u0430 \u043a \u043e\u043a\u043d\u0443:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun checkAnchor(needUpdateVisibleRect: Boolean, width: Int, height: Int): Boolean {     if (!checkAnchorIsAttachedToWindow()) return false     if (!needUpdateVisibleRect) return true     return checkAnchorVisibility(width, height) }  \/**  * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0432\u0438\u0434\u0435\u043d \u043b\u0438 \u044f\u043a\u043e\u0440\u044c  *\/ private fun checkAnchorVisibility(width: Int, height: Int): Boolean {     this.getLocationOnScreen(thisLocation)      val anchorView = view.getAnchorView() ?: return false     anchorView.getLocationOnScreen(anchorViewLocation)     anchorView.getGlobalVisibleRect(rect)     return anchorViewLocation.top >= thisLocation.top &amp;&amp;             anchorViewLocation.top + anchorView.measuredHeight &lt;= thisLocation.top + height &amp;&amp;             anchorViewLocation.left + anchorView.measuredWidth &lt;= thisLocation.left + width &amp;&amp;             anchorViewLocation.left >= thisLocation.left &amp;&amp;             !rect.isEmpty }  \/**  * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0451\u043d \u043b\u0438 \u044f\u043a\u043e\u0440\u044c \u043a \u043e\u043a\u043d\u0443  *\/ private fun checkAnchorIsAttachedToWindow(): Boolean {     val anchorView = view.getAnchorView()     return anchorView != null &amp;&amp; anchorView.isAttachedToWindow }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <strong>layoutChildLeft<\/strong> \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442 <strong>view<\/strong> \u0442\u0430\u043c<em>, <\/em>\u0433\u0434\u0435 \u043b\u0435\u0432\u044b\u0439 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0443\u0433\u043e\u043b \u0432 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445 <strong>(x, y)<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun layoutChildLeft(view: View, x: Int, y: Int) {     if (view.visibility != View.VISIBLE) return      val width = view.measuredWidth     val height = view.measuredHeight     val lp = view.layoutParams as? MarginLayoutParams     val childLeft = x + (lp?.leftMargin ?: 0)     val childTop = y + (lp?.topMargin ?: 0)     view.layout(childLeft, childTop, childLeft + width, childTop + height) }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <strong>layoutReactions<\/strong> \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0432\u044c\u044e\u0445\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0432 \u043d\u0430\u0431\u043e\u0440:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun layoutReactions() {     val thisRect = this.getVisibleRect()     for (index in scrollView.reactionContainerViews.indices) {         val reactionContainerView = scrollView.reactionContainerViews[index]         val reactionRect = reactionContainerView.getVisibleRect()          val reactionView = scrollView.reactionViews[index]         layoutReactionView(reactionView, reactionRect, thisRect)          val titleView = titleViews[index]         layoutTitle(titleView, reactionRect, thisRect)     } }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 <strong>layoutReactionView<\/strong> \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0432\u044c\u044e\u0445\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun layoutReactionView(reactionView: View, reactionRect: Rect, thisRect: Rect) {     \/\/ \u0415\u0441\u043b\u0438 \u0432\u044c\u044e\u0445\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u2014 \u0434\u043e\u0447\u0435\u0440\u043d\u044f\u044f \u0432\u044c\u044e\u0445\u0430 \u044d\u0442\u043e\u0439 \u0432\u044c\u044e-\u0433\u0440\u0443\u043f\u043f\u044b (\u0430 \u043d\u0435 \u0441\u043a\u0440\u043e\u043b\u043b-\u0432\u044c\u044e), \u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0451     if (reactionView.parent !== this) return      reactionView.layout(             reactionRect.left - thisRect.left,             reactionRect.top - thisRect.top,             reactionRect.right - thisRect.left,             reactionRect.bottom - thisRect.top     ) }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>layoutTitle<\/strong> \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442 <strong>titleView<\/strong> \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443 \u043d\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0435\u0439 \u0441 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 reactionRect \u0432 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0432\u044c\u044e-\u0433\u0440\u0443\u043f\u043f\u044b thisRect:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun layoutTitle(titleView: View, reactionRect: Rect, thisRect: Rect) {     val bottomText = reactionRect.top - thisRect.top - nameTextBottomMargin     val topText = bottomText - titleView.measuredHeight     val leftText = calcTextHorizontalOffset(titleView, reactionRect, thisRect)     val rightText = leftText + titleView.measuredWidth     titleView.layout(leftText, topText, rightText, bottomText) }<\/code><\/pre>\n<p>\u0412\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043b\u0435\u0432\u044b\u0439 \u043e\u0442\u0441\u0442\u0443\u043f \u0434\u043b\u044f \u043d\u0430\u0434\u043f\u0438\u0441\u0438 \u043d\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0435\u0439, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u044d\u043a\u0440\u0430\u043d\u0430:<\/p>\n<pre><code class=\"kotlin\">private fun calcTextHorizontalOffset(titleView: View, reactionRect: Rect, thisRect: Rect): Int {     val leftTextOffset = reactionRect.centerX() - thisRect.left - titleView.measuredWidth \/ 2     return when {         leftTextOffset &lt; screenPaddingStart -> screenPaddingStart         leftTextOffset + titleView.measuredWidth > this.measuredWidth - screenPaddingEnd -> {             this.measuredWidth - screenPaddingEnd - titleView.measuredWidth         }         else -> leftTextOffset     } }<\/code><\/pre>\n<h3>\u0420\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043c\u0435\u0442\u043e\u0434 <strong>dispatchDraw<\/strong> \u0432 <strong>ReactionsPopupView<\/strong>:<\/p>\n<pre><code class=\"kotlin\">override fun dispatchDraw(canvas: Canvas) {     layoutPopup()     drawPopup(canvas)     super.dispatchDraw(canvas) }<\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <strong>layoutPopup<\/strong> \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0438 \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u043e\u043f-\u0430\u043f\u0430:<\/p>\n<pre><code class=\"kotlin\">private fun layoutPopup() {     val halfPopupHeight = dialogHeight * (1f - popupScale) \/ 2f     popupRect.set(             dialogX + (-dialogBackgroundPaddingStart \/ popupScale - halfPopupHeight).roundToInt(),             popupTranslationY + dialogY + (halfPopupHeight - dialogBackgroundPaddingTop \/ popupScale).roundToInt(),             dialogX + (dialogBackgroundPaddingEnd \/ popupScale + popupWidth * popupScale - halfPopupHeight).roundToInt(),             popupTranslationY + dialogY + (halfPopupHeight + dialogBackgroundPaddingBottom \/ popupScale + popupHeight * popupScale).roundToInt()     ) }<\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <strong>drawPopup<\/strong> \u0440\u0438\u0441\u0443\u0435\u043c \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0443 \u0438 \u0442\u0435\u043d\u044c \u043f\u043e\u043f-\u0430\u043f\u0430 \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 <strong>layoutPopup<\/strong>:<\/p>\n<pre><code class=\"kotlin\">private fun drawPopup(canvas: Canvas) {     val pivotX = dialogX + (-dialogBackgroundPaddingStart \/ popupScale + dialogBackgroundPaddingEnd \/ popupScale + dialogHeight) \/ 2f     canvas.save()     canvas.scale(popupScale, popupScale, pivotX, popupRect.centerY().toFloat())     drawPopupShadow(canvas)     drawPopupBackground(canvas)     canvas.restore() }  private fun drawPopupBackground(canvas: Canvas) {     popupBackground?.bounds = popupRect     popupBackground?.draw(canvas) }  private fun drawPopupShadow(canvas: Canvas) {     popupShadowBackground?.bounds = popupRect     popupShadowBackground?.draw(canvas) }<\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u0430\u0441\u0430\u043d\u0438\u0439<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0442\u0430\u0447\u0438:<\/p>\n<pre><code class=\"kotlin\">override fun onInterceptTouchEvent(ev: MotionEvent) = true<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0442\u0430\u0447\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 <strong>ReactionsPopupTouchDelegate<\/strong>:<\/p>\n<pre><code class=\"kotlin\">override fun onTouchEvent(event: MotionEvent): Boolean {     touchDelegate.setCanSelect(animator.canSelect())     return touchDelegate.onTouchEvent(event) }<\/code><\/pre>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ReactionsPopupViewAnimator<\/strong> \u2014 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsPopupTouchDelegate<\/strong> \u2014 \u0432 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043c\u044b \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0442\u0430\u0447\u0438 \u043e\u0442 \u0432\u044c\u044e\u0445\u0438 <strong>ReactionsPopupView<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsSet<\/strong> \u2014 \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <strong>ReactionMeta<\/strong>.<\/p>\n<p>\u041c\u044b \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u0432\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439: \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430. \u0418 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0442\u0430\u043a\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438, \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 <strong>Lottie<\/strong>-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 <strong>Reaction<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>Lottie<\/strong>-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435. \u0414\u043b\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438 \u0438 \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u043d\u0430\u0440\u0435\u0437\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0440\u0435\u0430\u043a\u0446\u0438\u0439. \u042d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e, \u0447\u0442\u043e\u0431\u044b \u043a\u043b\u0438\u0435\u043d\u0442 \u0441\u0430\u043c \u0432\u044b\u0431\u0438\u0440\u0430\u043b \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u2014 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043b\u043e\u0442\u043d\u043e\u0441\u0442\u0438 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p><strong>ReactionsScrollView<\/strong> \u2014 \u0441\u043a\u0440\u043e\u043b\u043b-\u0432\u044c\u044e \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsAccessibilityDelegate<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0434\u043b\u044f <strong>TalkBack<\/strong>.\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsViewSettings<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsCallback<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u0447\u0435\u0439 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/428\/ddb\/f92\/428ddbf9296797c839866351780651a2.png\" width=\"1840\" height=\"840\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/428\/ddb\/f92\/428ddbf9296797c839866351780651a2.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsPopupTouchDelegate<\/strong> \u2014 \u0432 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043c\u044b \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0442\u0430\u0447\u0438 \u043e\u0442 \u0432\u044c\u044e\u0445\u0438 <strong>ReactionsPopupView<\/strong>.\u00a0<\/p>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u0447\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 <strong>ReactionsPopupTouchDelegate<\/strong>.<\/p>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <strong>onTouchEvent<\/strong> \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <strong>MotionEvent.ACTION_DOWN<\/strong> \u2014 \u043c\u0435\u0442\u043e\u0434<em> <\/em><strong>onTouchDown<\/strong>.\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u0435. \u0421 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u0442\u0441\u044f, \u043d\u0430 \u043a\u0430\u043a\u0443\u044e \u0432\u044c\u044e\u0445\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0430\u0447. \u041a\u043e\u0433\u0434\u0430 \u0442\u0430\u0447 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0432\u044c\u044e\u0445\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438, \u0442\u043e \u044d\u0442\u0430 \u0432\u044c\u044e\u0445\u0430 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044f\u0441\u044c \u0432 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u0445. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u043b\u0438 \u0442\u0430\u0447 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043b\u0435\u0432\u043e\u043c \u0438 \u043f\u0440\u0430\u0432\u043e\u043c \u043a\u0440\u0430\u044e \u043f\u043e\u043f-\u0430\u043f\u0430 \u0438 \u043d\u0435 \u0432\u0441\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d, \u0442\u043e \u0430\u0432\u0442\u043e\u0441\u043a\u0440\u043e\u043b\u043b \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0442\u0443 \u0441\u0442\u043e\u0440\u043e\u043d\u0443, \u043e\u0442\u043a\u0443\u0434\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0442\u0430\u0447\u0430.<\/p>\n<pre><code class=\"kotlin\">private fun onTouchDown(event: MotionEvent): Boolean {     if (this.activePointerId == INVALID_POINTER_ID) {         this.activePointerId = event.getPointerId(FIRST_POINTER_INDEX)     } else if (!checkPointer(event)) {         return false     }      if (this.startTouchTime == null) {         clearGesture()         this.startTouchTime = System.currentTimeMillis()     }      selectDelegate.setContinuousTouch(false)      callback.onStartTouch()      val isIntersectedScrollView = popupView.isIntersectedScrollView(event.rawX, event.rawY)     this.canScroll = isIntersectedScrollView     this.downEventX = event.rawX     scrollDetector.setEvent(event)     this.lastEventX = event.rawX     this.lastEventY = event.rawY     if (isIntersectedScrollView) {         scrollView.onTouchEvent(event)         selectDelegate.cancel()         selectDelegate.onTouchDown(event)         autoScrollDelegate.scroll(event)     } else {         endTouchAndDismissIfNeeded()     }     return true }<\/code><\/pre>\n<p><strong>startTouchTime<\/strong> \u2014 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043f\u043e\u043f-\u0430\u043f\u043e\u043c, \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u0438\u043a\u043e\u0441\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u043a \u044d\u043a\u0440\u0430\u043d\u0443 (<strong>MotionEvent.ACTION_DOWN<\/strong>) \u0438 \u043e\u0447\u0438\u0449\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u044e\u0437\u0435\u0440 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0430\u043b\u0435\u0446 \u0438\u043b\u0438 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0436\u0435\u0441\u0442 (<strong>MotionEvent.ACTION_UP<\/strong> \u0438\u043b\u0438 <strong>MotionEvent.ACTION_CANCEL<\/strong>).<\/p>\n<ul>\n<li>\n<p>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <strong>MotionEvent.ACTION_MOVE<\/strong> \u2014 \u043c\u0435\u0442\u043e\u0434 <strong>onTouchMove<\/strong>.\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0438\u043b\u0438 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0441\u043a\u0440\u043e\u043b\u043b\u0430, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043d\u0435 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b. \u0410\u0432\u0442\u043e\u0441\u043a\u0440\u043e\u043b\u043b \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0430 \u043a\u0440\u0430\u0439 \u043f\u043e\u043f-\u0430\u043f\u0430.<\/p>\n<pre><code class=\"kotlin\">private fun onTouchMove(event: MotionEvent): Boolean {     val pointerIndex = getPointerIndex(event) ?: return false      this.lastEventX = event.getX(pointerIndex)     this.lastEventY = event.getY(pointerIndex)      return when {         isScroll -> onTouchMoveScroll(event)         else -> {             isScroll = isScroll(event)             if (!isScroll) {                 selectDelegate.onMove(event)                 autoScrollDelegate.scroll(event)                 true             } else {                 onTouchMoveScroll(event)             }         }     } }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <strong>MotionEvent.ACTION_UP<\/strong> \u2014 \u043c\u0435\u0442\u043e\u0434 <strong>onTouchUp<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u043c\u0435\u043d\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u043f\u0430\u043b\u0435\u0446 \u0443\u0436\u0435 \u043d\u0435 \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u044d\u043a\u0440\u0430\u043d\u0430. \u0415\u0441\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d \u0430\u0432\u0442\u043e\u0441\u043a\u0440\u043e\u043b\u043b, \u0442\u043e \u043e\u043d \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<pre><code class=\"kotlin\">private fun onTouchUp(event: MotionEvent): Boolean {     if (!checkPointer(event)) return false      this.lastEventX = null     this.lastEventY = null     this.activePointerId = INVALID_POINTER_ID     return when {         isScroll -> endScrollTouch(event)         else -> {             autoScrollDelegate.cancel()             selectDelegate.select(event.rawX, event.rawY)         }     } }<\/code><\/pre>\n<ol start=\"4\">\n<li>\n<p>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <strong>MotionEvent.ACTION_CANCEL<\/strong> \u2014 \u043c\u0435\u0442\u043e\u0434 <strong>onTouchCancel<\/strong>.\u00a0<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0436\u0435\u0441\u0442 \u043e\u0442\u043c\u0435\u043d\u0451\u043d. \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0441\u043a\u0440\u043e\u043b\u043b, \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u044b\u043b \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d, \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043f-\u0430\u043f.<\/p>\n<pre><code class=\"kotlin\">private fun onTouchCancel(event: MotionEvent): Boolean {     if (!checkPointer(event)) return false      this.lastEventX = null     this.lastEventY = null     this.activePointerId = INVALID_POINTER_ID     return when {         isScroll -> endScrollTouch(event)         else -> {             cancelGesture()             popupView.dismiss()             true         }     } }<\/code><\/pre>\n<ol start=\"5\">\n<li>\n<p><strong>onTouchMoveScroll<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0442\u0430\u0447\u0430 \u0438\u0437 <strong>onTouchMove<\/strong> \u2014 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">private fun onTouchMoveScroll(event: MotionEvent): Boolean {     autoScrollDelegate.cancel()     selectDelegate.idle()     return if (canScroll) {         scrollView.onTouchEvent(event)     } else {         true     } }<\/code><\/pre>\n<ol start=\"6\">\n<li>\n<p><strong>onScroll<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043e\u043a \u0441 \u0438\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043a\u0440\u043e\u043b\u043b \u043e\u0431\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430. \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u043a\u0440\u043e\u043b\u043b \u2014 \u044d\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u043e\u043d \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u044c\u044e\u0445.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">fun onScroll() {     val lastEventX = lastEventX ?: return     val lastEventY = lastEventY ?: return     if (isScroll) return      selectDelegate.onScroll(lastEventX, lastEventY) }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0435\u0451 \u00ab\u043e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u043d\u043e\u0435\u00bb \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435. \u0422\u043e \u0435\u0441\u0442\u044c \u0440\u0435\u0430\u043a\u0446\u0438\u044f \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0435\u0451 \u0443\u0447\u0451\u0442\u043e\u043c \u2014 \u0438 \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043e\u0431 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u041f\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0443 \u00ab\u0438\u0437\u0434\u0430\u0442\u0435\u043b\u044c-\u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u00bb \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0443 \u0432\u0441\u0435\u0445 \u0432\u044c\u044e\u0445, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0445\u0441\u044f \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u044f. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u044d\u043a\u0440\u0430\u043d\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0441\u0442\u0435\u043a\u0435 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440 \u0438 \u0432\u044c\u044e\u0445\u0443, \u043e\u0442\u043a\u0443\u0434\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0432\u044c\u044e\u0445\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<h4>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445 \u0441 \u0432\u044c\u044e<\/h4>\n<ul>\n<li>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043c\u0435\u0436\u0434\u0443 <strong>ACTION_DOWN<\/strong> \u0438 <strong>ACTION_UP<\/strong> \u043f\u0440\u043e\u0448\u043b\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0435\u043c <strong>ViewConfiguration.getLongPressTimeout()<\/strong>, \u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <strong>performClick<\/strong>. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443 \u0432\u044c\u044e\u0445\u0438, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u044b\u043b \u0442\u0430\u0447, \u0438 \u043f\u043e\u043f-\u0430\u043f \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u041f\u043e <strong>ACTION_CANCEL<\/strong> \u043f\u043e\u043f-\u0430\u043f \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u043b\u0438 \u0431\u044b\u043b\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <strong>ACTION_MOVE<\/strong> \u0438 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c \u043d\u0430 <strong>ViewConfiguration.get(context).scaledTouchSlop<\/strong>, \u0442\u043e \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u0441\u043a\u0440\u043e\u043b\u043b. \u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u043f-\u0430\u043f \u043d\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e <strong>ACTION_DOWN<\/strong> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 <strong>Runnable<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>ViewConfiguration.getLongPressTimeout()<\/strong> \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434. \u0415\u0441\u043b\u0438 \u043b\u044e\u0431\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0438 \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u0442\u043e \u044d\u0442\u043e\u0442 <strong>Runnable<\/strong> \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p>\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f-\u0430\u043f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0432\u0441\u0435 \u0442\u0430\u0447\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u043c.<\/p>\n<pre><code class=\"kotlin\">val runnable = ShowReactionRunnable(v, reactionSet) handler.postDelayed(runnable, longPressTimeout)<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u043b\u0438\u043a\u0430-\u0432\u0438\u0431\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 \u0445\u0430\u043f\u0442\u0438\u043a\u0430 <strong><em>view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)<\/em><\/strong>.<\/p>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><strong>AutoScrollDelegate<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u0432 \u043f\u043e\u043f-\u0430\u043f\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>ScrollTouchDetector<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c \u0442\u0430\u0447\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>SelectDelegate<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u044c\u044e\u0445\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 <strong>SelectReactionRunnable<\/strong> \u0447\u0435\u0440\u0435\u0437 \u0432\u0440\u0435\u043c\u044f <strong>tapTimeout<\/strong>.\u00a0<\/p>\n<pre><code class=\"kotlin\">fun selectReactionDelayed(selectedId: Int) {     selectReactionRunnable = SelectReactionRunnable(selectedId).apply {         handler.postDelayed(this, tapTimeout)     } }<\/code><\/pre>\n<p>\u0412 <strong>SelectReactionRunnable<\/strong> \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432 \u2014 \u043d\u0443\u0436\u043d\u044b \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<pre><code class=\"kotlin\">private inner class SelectReactionRunnable(var reactionId: Int) : Runnable {     override fun run() {         popupView.setSelectedPosition(reactionId)         selectReactionRunnable = null         touchDelegate.setCanScroll(false)     } }<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 <strong>reactionId<\/strong> \u2014 \u044d\u0442\u043e <strong>id<\/strong> \u0440\u0435\u0430\u043a\u0446\u0438\u0438; <strong>popupView.setSelectedPosition(reactionId)<\/strong> \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438; <strong>touchDelegate.setCanScroll(false)<\/strong> \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043a\u0440\u043e\u043b\u043b \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435. \u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043d\u0435 \u0432\u043b\u0435\u0437\u0430\u044e\u0442 \u0432 \u044d\u043a\u0440\u0430\u043d, \u0438 \u043f\u0440\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0436\u0435\u0441\u0442\u0430\u043c\u0438.\u00a0<\/p>\n<ul>\n<li>\n<p><strong>ReactionsScrollView<\/strong> \u2014 \u0432\u044c\u044e\u0445\u0430 \u0441 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u043a\u0440\u043e\u043b\u043b\u043e\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsCallback<\/strong> \u2014 \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0431 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430, \u0432\u044b\u0431\u043e\u0440\u0435 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsPopupView<\/strong> \u2014 \u0432\u044c\u044e\u0445\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d \u0438 \u0432 \u043d\u0435\u0439 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043f-\u0430\u043f. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044c\u044e\u0445\u0438, \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440 \u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0442\u0430\u0447\u0435\u0439.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430<\/h3>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c4b\/e21\/4d5\/c4be214d57a6f9a0f2bba7f8b38c3603.png\" width=\"1800\" height=\"680\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c4b\/e21\/4d5\/c4be214d57a6f9a0f2bba7f8b38c3603.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsPresenter<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044c\u044e\u0445 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435.<\/p>\n<h4>\u041e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u043d\u043e\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432\u043e \u0432\u044c\u044e\u0445\u0435<\/h4>\n<p>\u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0432 UI \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0438. \u041f\u043e\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438, \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f. \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0448\u0438\u0431\u043a\u0430, \u0442\u043e UI \u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0434\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439.<\/p>\n<ul>\n<li>\n<p><strong>ReactionsView<\/strong> \u2014 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0432\u044c\u044e\u0445\u0430\u043c\u0438 \u0434\u043b\u044f <strong>ReactionsPresenter<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsModel<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u043e\u0431\u044a\u0435\u043a\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0430\u043a\u0446\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsCallback<\/strong> \u2014 \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0431 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430, \u0432\u044b\u0431\u043e\u0440\u0435 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f, \u0432\u044b\u0431\u043e\u0440\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dd5\/1d2\/e38\/dd51d2e3816ae8cdf736709c0e50df53.png\" width=\"2300\" height=\"686\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dd5\/1d2\/e38\/dd51d2e3816ae8cdf736709c0e50df53.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f, \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 <strong>ReactionsPopupViewAnimator<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430. \u041f\u0440\u0438 \u043e\u0442\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u0432\u044c\u044e\u0445\u0438 \u043e\u0442 \u043e\u043a\u043d\u0430 \u0432\u0441\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043c\u0435\u0442\u043e\u0434 cancel.<\/p>\n<p><strong>\u042d\u0442\u0430\u043f\u044b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430.<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 <strong>ReactionsOpenAnimator<\/strong>. \u0414\u043b\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <strong>AnimatorSet<\/strong>, \u0432\u044b\u0437\u044b\u0432\u0430\u044f <strong>playTogether<\/strong> \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0443 \u0438 \u0442\u0435\u043d\u044c \u043f\u043e\u043f-\u0430\u043f\u0430 \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u043c\u0438, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u0438 <strong>100%<\/strong>;<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043a\u0435\u0439\u043b \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0434\u043e <strong>1<\/strong>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0448\u0438\u0440\u0438\u043d\u0443 \u0438 \u0432\u044b\u0441\u043e\u0442\u0443, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043a\u0440\u0443\u0433\u043b\u043e\u0439 \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0438 \u0438 \u0442\u0435\u043d\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0432 \u043f\u043e\u043f-\u0430\u043f\u0435 \u043f\u043e \u0434\u0432\u0430 \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u0430:<\/p>\n<ul>\n<li>\n<p>\u043e\u0434\u0438\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u043a\u0435\u0439\u043b\u0430 \u0441 <strong>0<\/strong> \u0434\u043e <strong>1<\/strong>,<\/p>\n<\/li>\n<li>\n<p>\u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u0437\u0430 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u043d\u0438\u0437.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0430 \u0438 \u0442\u0435\u043d\u044c \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u0442\u043e \u043e\u043d\u0438 \u0440\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<p>\u0412\u0441\u0435 \u044d\u0442\u0430\u043f\u044b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0438\u0445 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0430 \u0438 \u043a\u043e\u043d\u0446\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0442\u043e\u0440\u044b. \u0422\u0435\u043d\u044c \u0438 \u0431\u0430\u0431\u043b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0440\u0438\u0441\u0443\u0435\u043c \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0439, \u0441\u043a\u0435\u0439\u043b\u0430 \u0438 \u0442\u0435\u043c\u044b. \u0422\u0435\u043d\u044c \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0438 \u2014 \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0430 \u043e\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0446\u0432\u0435\u0442 \u0442\u0435\u043c\u044b, \u0430 \u0442\u0435\u043d\u044c \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 Lottie-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1c7\/187\/c89\/1c7187c896664dc4ea511d36cd8bf0b9.gif\" width=\"640\" height=\"284\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1c7\/187\/c89\/1c7187c896664dc4ea511d36cd8bf0b9.gif\"\/><figcaption><\/figcaption><\/figure>\n<ul>\n<li>\n<p><strong>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430.<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 <strong>ReactionsCloseAnimator<\/strong>.<\/p>\n<p>\u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 <strong>Lottie<\/strong>-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.\u00a0<\/p>\n<p>\u041f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432:\u00a0<\/p>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u044c\u044e\u0445 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043f\u043e \u043e\u0441\u0438 <strong>Y<\/strong> \u043e\u0442 <strong>0<\/strong> \u0434\u043e <strong>36<\/strong> dp \u043a\u0443\u0431\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0435\u0439 \u0411\u0435\u0437\u044c\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u044c\u044e\u0445 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043e\u0442 <strong>0<\/strong> \u0434\u043e <strong>\u221235<\/strong> \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432 \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c \u0432\u044c\u044e\u0445 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043e\u0442 <strong>1<\/strong> \u0434\u043e <strong>0<\/strong> \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043d\u0430 \u0438\u0445 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u043a\u0443\u0431\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0435\u0439 \u0411\u0435\u0437\u044c\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043e\u0442 <strong>1<\/strong> \u0434\u043e <strong>0<\/strong> \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0435\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u044e\u0442\u0441\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f <strong>Lottie<\/strong>-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439. \u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6a8\/990\/c61\/6a8990c6107691de61118298195140af.gif\" width=\"640\" height=\"284\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6a8\/990\/c61\/6a8990c6107691de61118298195140af.gif\"\/><figcaption><\/figcaption><\/figure>\n<ul>\n<li>\n<p><strong>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043f\u0430\u043b\u044c\u0446\u0435\u043c \u043d\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u044e.<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <strong>ReactionsSelectAnimator<\/strong>. \u0412 \u043d\u0451\u043c \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432:\u00a0<\/p>\n<ul>\n<li>\n<p>\u0442\u043e\u0442, \u0447\u0442\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 \u0432\u044c\u044e\u0445\u0430\u043c\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u044e\u0442, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043d\u0438\u0445 \u043d\u0430\u0432\u0435\u0434\u0443\u0442 \u043f\u0430\u043b\u0435\u0446. \u042d\u0442\u043e\u0442 \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0438\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435. \u0410 \u0435\u0449\u0451 \u0437\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435, \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u0438 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u0435\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0430\u043b\u0435\u0446;<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0432\u044c\u044e\u0445\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u0438\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043d\u0438\u0445 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0430\u043b\u0435\u0446.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bff\/d37\/b43\/bffd37b436e78237793d549d23aca6e1.gif\" width=\"514\" height=\"360\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bff\/d37\/b43\/bffd37b436e78237793d549d23aca6e1.gif\"\/><figcaption><\/figcaption><\/figure>\n<ul>\n<li>\n<p><strong>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430 \u044d\u0442\u0443 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <strong>ReactionsSendAnimator<\/strong>.<\/p>\n<p>\u041f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440\u043e\u0432:\u00a0<\/p>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043f\u043e \u043a\u0443\u0431\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438 \u0411\u0435\u0437\u044c\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u043f\u043e \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u0432\u044c\u044e\u0445\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043f\u043e \u043a\u0443\u0431\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438 \u0411\u0435\u0437\u044c\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u044c\u044e\u0445\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043f\u043e \u043a\u0443\u0431\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438 \u0411\u0435\u0437\u044c\u0435.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e55\/b1e\/84a\/e55b1e84afa7536ef120bb0783ce40e4.gif\" width=\"516\" height=\"360\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e55\/b1e\/84a\/e55b1e84afa7536ef120bb0783ce40e4.gif\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0420\u0435\u0436\u0438\u043c \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u0430 (TalkBack)<\/h3>\n<p>\u041c\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u043b\u0438 \u0440\u0435\u0436\u0438\u043c <strong>TalkBack<\/strong> \u2014 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043b\u044e\u0434\u044f\u043c \u0441 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 Android \u043e\u0437\u0432\u0443\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u043d\u043e\u043f\u043e\u043a, \u043d\u0430\u0436\u0430\u0442\u0438\u0439 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432\u043f\u0435\u0440\u0451\u0434 \u0438 \u043d\u0430\u0437\u0430\u0434.<\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 <strong>TalkBack<\/strong> \u0432 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <strong>AcessibiltyDelegateCompat<\/strong>. \u0423 \u043d\u0430\u0441 \u043e\u043d\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>ReactionsAccessibilityDelegate<\/strong>. \u0412 <strong>ReactionsAccessibilityDelegate<\/strong> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 \u0438\u0445 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0433\u0440\u0430\u043d\u0438\u0446.<\/p>\n<p><strong>ReactionsAccessibilityDelegate<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0434\u043b\u044f <strong>TalkBack<\/strong>.\u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6ed\/0c1\/1cb\/6ed0c11cb519ac5d6683345ebbbb8964.png\" width=\"1920\" height=\"1100\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6ed\/0c1\/1cb\/6ed0c11cb519ac5d6683345ebbbb8964.png\"\/><figcaption><\/figcaption><\/figure>\n<ul>\n<li>\n<p><strong>AccessibilityDelegateCompat<\/strong> \u2014 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f <strong>ReactionsAccessibilityDelegate<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>ExploreByTouchHelperImpl<\/strong> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a <strong>ExploreByTouchHelper<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsPopupView<\/strong> \u2014 \u0432\u044c\u044e-\u0433\u0440\u0443\u043f\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d \u0438 \u0432 \u043d\u0435\u0439 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432\u044c\u044e\u0445\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0449\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u043e \u0441\u043b\u0443\u0436\u0431\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043a\u043b\u0430\u0441\u0441\u0430 <strong>ExploreByTouchHelper<\/strong>. \u0415\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.<\/p>\n<p><strong>ExploreByTouchHelper<\/strong> \u2014 \u044d\u0442\u043e \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u043e \u0432\u044c\u044e\u0445\u0435. \u041e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0445, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u0432\u044c\u044e\u0445\u0430\u043c. <strong>ExploreByTouchHelper<\/strong> \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 <strong>AccessibilityNodeProviderCompat<\/strong> \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat)<\/strong> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <strong>ReactionsAccessibilityDelegate<\/strong> \u0434\u043b\u044f \u0432\u044c\u044e\u0445\u0438.<\/p>\n<p>\u0414\u043b\u044f <strong>Talkback<\/strong> \u0432\u0441\u0435 \u0432\u044c\u044e\u0445\u0438, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u044c\u044e\u0445\u0438.<\/p>\n<p>\u041e\u043f\u0438\u0448\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430:<\/p>\n<ul>\n<li>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <strong>getVisibleVirtualViews<\/strong> \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0432\u044c\u044e\u0445. \u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0432 <strong>ids<\/strong> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u0431\u0445\u043e\u0434\u0430 \u0432\u044c\u044e\u0445 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 <strong>TalkBack<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun getVisibleVirtualViews(ids: MutableList&lt;Int>) {     for (i in 0..view.getReactions().size) {         ids.add(i)     } }<\/code><\/pre>\n<p>\u0412\u0441\u0435\u0433\u043e <strong>n\u202f+\u202f1<\/strong> \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u044c\u044e\u0445, \u0433\u0434\u0435 <strong>n<\/strong> \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0430\u043a\u0446\u0438\u0439. <strong>+1<\/strong> \u2014 \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u043d\u0435 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0435\u0433\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f.\u00a0<\/p>\n<ul>\n<li>\n<p><strong>getVirtualViewAt<\/strong> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0432\u044c\u044e\u0445\u0438 \u043f\u043e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435. \u0412\u0441\u0435 \u0432\u044c\u044e\u0445\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043e\u0442 <strong>0<\/strong> \u0434\u043e <strong>n\u202f+\u202f1<\/strong>, \u0433\u0434\u0435 <strong>n<\/strong> \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun getVirtualViewAt(x: Float, y: Float): Int {     val position = view.findPositionByTouch(x, y)     return if (position != WAITING_SELECTION &amp;&amp; position >= 0) {         position     } else {         view.getReactions().size     } }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 <strong>onPopulateEventForVirtualView<\/strong> \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <strong>AccessibilityEvent<\/strong> \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e\u0431 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0435.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onPopulateEventForVirtualView(id: Int, event: AccessibilityEvent) {     val reaction = view.getReaction(id)     event.contentDescription = if (reaction != null) {         view.resources.getString(R.string.reaction_add, reaction.title)     } else {         view.resources.getString(R.string.close)     } }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 <strong>onPopulateNodeForVirtualView<\/strong> \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c <strong>AccessibilityNodeInfoCompat<\/strong> \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435. \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c:<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0444\u043e\u043a\u0443\u0441\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0432\u044c\u044e\u0445\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0451 \u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u044c\u044e\u0445\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043d\u0435\u0439 (<strong>AccessibilityNodeInfoCompat.ACTION_CLICK<\/strong>).<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onPopulateNodeForVirtualView(id: Int, info: AccessibilityNodeInfoCompat) {     val reaction = view.getReaction(id)     info.contentDescription = if (reaction != null) {         view.resources.getString(R.string.reaction_add, reaction.title)     } else {         view.resources.getString(R.string.close)     }     info.isFocusable = true     info.isClickable = true     view.getBoundsForView(id, rect)     info.setBoundsInParent(rect)     info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK) }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0435 <strong>onPerformActionForVirtualView<\/strong> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 (\u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0438\u043b\u0438 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435) \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <strong>action<\/strong> \u2014 \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c <strong>id<\/strong> \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onPerformActionForVirtualView(id: Int, action: Int) = when (action) {     AccessibilityNodeInfoCompat.ACTION_CLICK -> {         val reaction = view.getReaction(id)         if (reaction != null) {             view.select(id)         } else {             view.close()         }         true     }     else -> false }<\/code><\/pre>\n<h3>\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<p>\u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>Lottie<\/strong>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cf6\/c42\/89b\/cf6c4289b44c5f7404aee44509bee475.gif\" width=\"640\" height=\"290\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cf6\/c42\/89b\/cf6c4289b44c5f7404aee44509bee475.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <strong>Lottie<\/strong> \u0432 \u043e\u0431\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>Lottie<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u041a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0432 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438<\/strong> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0448\u0430\u0433\u043e\u0432 (\u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u043e\u0442\u0441\u0447\u0451\u0442\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438: \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0430\u0434\u0440.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0448\u043b\u043e \u0441\u043e \u0441\u0442\u0430\u0440\u0442\u0430. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0430\u0434\u0440, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u043f\u0443\u043d\u043a\u0442\u0443 \u0411.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">deltaMs = timeNowMs - startPointTimeMs startPointId + (deltaMs \/ renderData.frameDurationMs).roundToInt()<\/code><\/pre>\n<p>       \u0410. \u0415\u0441\u043b\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0434\u0440 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438, \u0442\u043e \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0432\u044b\u0437\u043e\u0432\u0435 <strong>onDraw<\/strong> \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0442\u043c\u0430\u043f\u0443 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d, \u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043f\u0443\u043b \u0431\u0438\u0442\u043c\u0430\u043f.<\/p>\n<p>       \u0411. \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 \u043a\u0430\u0434\u0440\u0430 \u0438\u0437 \u0431\u0438\u0442\u043c\u0430\u043f\u044b \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0443 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0433\u043e Lottie \u0432 \u0431\u0438\u0442\u043c\u0430\u043f\u0443:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0431\u0438\u0442\u043c\u0430\u043f\u0443 \u0438\u0437 \u043f\u0443\u043b\u0430 (\u0431\u0438\u0442\u043c\u0430\u043f\u0430 \u0431\u0435\u0440\u0451\u0442\u0441\u044f \u0438\u0437 \u043f\u0443\u043b\u0430, \u0435\u0441\u043b\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u0431\u0438\u0442\u043c\u0430\u043f\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442; \u0435\u0441\u043b\u0438 \u043d\u0435\u0442, \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u043e\u0432\u0430\u044f);<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 <strong>Lottie<\/strong> \u0432 \u0440\u0430\u0441\u0442\u0440\u043e\u0432\u044b\u0439 \u2014 \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0431\u0438\u0442\u043c\u0430\u043f\u0443 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0430\u0434\u0440\u0430 \u043d\u0430 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<p><em>\u0428\u0430\u0433\u0438 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c, \u043f\u043e\u043a\u0430:<\/em><\/p>\n<p><em>\u2014 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430;<\/em><\/p>\n<p><em>\u2014 \u0432\u044c\u044e\u0445\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435;<\/em><\/p>\n<p><em>\u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437 \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043c\u0435\u043d\u044c\u0448\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043e\u0432 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439 (\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043d\u0430\u0434\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437).<\/em><\/p>\n<\/li>\n<\/ul>\n<h4>\u0424\u043e\u0440\u043c\u0430\u0442 Lottie\u00a0<\/h4>\n<p>\u0414\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 <strong>Lottie<\/strong> \u0438\u0437 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0432 \u0440\u0430\u0441\u0442\u0440\u043e\u0432\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 RLottie (<a href=\"https:\/\/github.com\/Samsung\/rlottie\"><u>github.com\/Samsung\/rlottie<\/u><\/a>), \u043e\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 C++. \u0412 Android \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 NDK. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f RLottie \u0431\u0438\u0442\u043c\u0430\u043f\u0430 \u043d\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0430\u0434\u0440\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 <strong>Lottie<\/strong> \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0444\u0440\u0435\u0439\u043c\u0440\u0435\u0439\u0442 \u0438 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0434\u0440\u043e\u0432.<\/p>\n<h4>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<ul>\n<li>\n<p>\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0443\u043b\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f <strong>Lottie<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0431\u0438\u0442\u043c\u0430\u043f\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0443\u043b \u0431\u0438\u0442\u043c\u0430\u043f.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0438, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u043a\u0435\u0448: \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u043f\u0435\u0440\u0451\u0434, \u043f\u043e \u043a\u043e\u043b\u0431\u044d\u043a\u0443 \u0441\u043a\u0440\u043e\u043b\u043b\u0430. \u041a\u043e\u0433\u0434\u0430 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u043e \u0438 \u0431\u0435\u0440\u0451\u0442\u0441\u044f \u0438\u0437 \u043a\u0435\u0448\u0430.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u043a\u043e\u0433\u0434\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043f-\u0430\u043f \u0438 \u0435\u0449\u0451 \u043f\u0440\u043e\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438, \u043c\u044b \u043f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u043e\u0432. \u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043b\u043e\u0436\u0435\u043d\u043e, \u0447\u0442\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0430 \u0441\u0432\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u0441\u0442. \u041d\u043e \u0442\u0430\u043c \u0441\u0442\u043e\u044f\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438: \u0431\u044b\u043b\u0430 \u043b\u0438 \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0440\u0430\u043d\u0435\u0435, \u0438\u043b\u0438 \u043e\u043d\u0430 \u043d\u0435 \u043f\u0440\u043e\u0433\u0440\u0443\u0437\u0438\u043b\u0430\u0441\u044c \u0438\u0437-\u0437\u0430 \u043e\u0448\u0438\u0431\u043a\u0438, \u0438\u043b\u0438 \u043e\u043d\u0430 \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f.<\/p>\n<pre><code class=\"kotlin\"> object ReactionsPreloader {     \/\/ \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e url     private const val ERROR_RETRY_MAX = 3      private val downloading = ArraySet&lt;String>()     private val loaded = ArraySet&lt;String>()     private val errors = ArrayMap&lt;String, Int>()      fun preload(url: String) {         if (loaded.contains(url)) return         if (downloading.contains(url)) return         var errorCounter = errors.getOrDefault(url, 0)         if (errorCounter >= ERROR_RETRY_MAX) return         downloading.add(url)          \/\/ VKAnimationLoader \u043a\u0435\u0448\u0438\u0440\u0443\u0435\u0442 json \u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f         VKAnimationLoader.load(url)             .doOnNext {                 loaded.add(url)             }             .doOnError {                errors[url] = ++errorCounter             }             .doFinally {                 downloading.remove(url)             }             .subscribeEmpty()     } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c <strong>downloading<\/strong> \u2014 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e <strong>url<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441; <strong>loaded<\/strong> \u2014 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 <strong>url<\/strong>; <strong>errors<\/strong> \u2014 \u0441\u043b\u043e\u0432\u0430\u0440\u044c, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 <strong>url<\/strong> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<h3>\u0413\u0434\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f<\/h3>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043a\u0446\u0438\u0439, \u0438\u0445 \u043f\u043e\u043f-\u0430\u043f\u043e\u0432, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u0447\u0435\u0439, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0440\u0435\u0436\u0438\u043c\u043e\u043c \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f <strong>Lottie<\/strong>-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e\u043a\u0430\u0437\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u0447\u0430\u043c\u0438, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u043a\u043e\u0448\u043a\u0438 \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0434\u0438\u0437\u0430\u0439\u043d\u043e\u043c \u0438 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/p>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0436\u0438\u043c\u0430 \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439 \u0441 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u2014 \u0434\u0430\u0436\u0435 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0432\u044c\u044e\u0445, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432 \u0432\u0438\u0434\u0435 <strong>View.setContentDescription<\/strong> \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0437\u0430\u0433\u043b\u0443\u0448\u0435\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<p>\u0410 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0435 <strong>Lottie<\/strong>-\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u0430\u0434\u0440 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u043c\u043e \u00ab\u0442\u044f\u0436\u0451\u043b\u044b\u0439\u00bb \u0438 \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/660281\/\"> https:\/\/habr.com\/ru\/company\/vk\/blog\/660281\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0435\u043d\u0438\u0441 \u0417\u0430\u0433\u0443\u043c\u0435\u043d\u043d\u043e\u0432, \u044f \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043b\u0435\u043d\u0442\u044b \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435. \u041c\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u043d\u043e\u0439 \u043b\u0435\u043d\u0442\u043e\u0439, \u0441\u0442\u0435\u043d\u043e\u0439, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438, \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u043c\u0438, VK Donut, \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u0433\u0440\u0430\u0444\u043e\u043c \u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0435\u0439.<\/p>\n<p>\u0412 \u0430\u0432\u0433\u0443\u0441\u0442\u0435 2021-\u0433\u043e \u043c\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0443 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0443\u0433\u0443\u0431\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439, \u0434\u043b\u044f Android-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435:<\/h3>\n<ul>\n<li>\n<p>\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u0438 \u0432\u044b\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0424\u0430\u0441\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 ReactionsView \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043f-\u0430\u043f \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u0447\u0435\u0439 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u043f-\u0430\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f, \u0432\u044b\u0431\u043e\u0440\u0430, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0436\u0438\u043c \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u0430 (TalkBack).<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0413\u0434\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u0438 \u0432\u044b\u0431\u043e\u0440 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u044f \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0432\u044b\u0440\u0430\u0436\u0430\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u043a \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u043e \u043e\u0434\u043d\u043e\u0439 \u044d\u0442\u043e\u0439 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0431\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u044d\u043c\u043e\u0446\u0438\u0438. \u0410 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435\u0443\u043c\u0435\u0441\u0442\u043d\u043e.\u00a0<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0430\u043a\u0446\u0438\u0439: \u0442\u0435\u043f\u0435\u0440\u044c \u0438\u0445 \u0448\u0435\u0441\u0442\u044c. \u0422\u0430\u043a \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0442\u043e\u0447\u043d\u0435\u0435 \u0438 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0447\u0443\u0432\u0441\u0442\u0432\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c.\u00a0<\/p>\n<p>\u0412 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0442\u0430\u043a: \u0434\u043e\u043b\u0433\u0438\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f\u00bb \u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043f-\u0430\u043f \u0441 \u0440\u0435\u0430\u043a\u0446\u0438\u044f\u043c\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u0442\u0430\u0432\u0438\u0442 \u043d\u0443\u0436\u043d\u0443\u044e \u2014 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c, \u043d\u0435 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u044f \u043f\u0430\u043b\u0435\u0446. \u041e\u0431 \u044d\u0442\u043e\u0439 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432 Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<h3>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<p>\u0412 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043b\u0435\u043d\u0442\u044b \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c MVP, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0412\u043e <strong>View<\/strong> \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u0434\u043b\u044f <strong>RecyclerView<\/strong>, \u0430 <strong>Presenter<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u2014 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u044f\u0447\u0435\u0439\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u041a\u0430\u0436\u0434\u043e\u0439 \u0442\u0430\u043a\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0434\u0438\u043d ViewHolder.<\/p>\n<p>\u041c\u044b \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0438, \u0447\u0442\u043e\u0431\u044b <strong>RecyclerView<\/strong> \u043c\u043e\u0433 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u044c\u044e\u0445\u0438, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e \u0432\u044b\u0441\u043e\u0442\u0435.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u043c \u0438\u0437 VK Team (\u043a\u0430\u0436\u0434\u0430\u044f \u0432\u044c\u044e\u0445\u0430 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0430 \u0441\u0438\u043d\u0438\u043c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u043c):<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u0430\u0432\u0430\u0442\u0430\u0440\u043a\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0430 \u0438 \u0434\u0430\u0442\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u043a\u0441\u0442 \u043c\u043e\u0435\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043b\u043e\u0436\u0435\u043d\u0438\u0435-\u0441\u0442\u0430\u0442\u044c\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0424\u0443\u0442\u0435\u0440 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f \u0434\u043e\u043b\u0433\u0438\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u044c\u044e\u0445\u0443 \u0444\u0443\u0442\u0435\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u0435\u0430\u043a\u0446\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p>\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u0432 \u043a\u043d\u043e\u043f\u043a\u0435 \u0444\u0443\u0442\u0435\u0440\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0444\u0443\u0442\u0435\u0440\u0430, \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 <strong>ReactionsFacade<\/strong>: \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0443, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440 \u0444\u0443\u0442\u0435\u0440\u0430 \u043c\u043e\u0433 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u044d\u0442\u0438\u043c \u0444\u0430\u0441\u0430\u0434\u043e\u043c.<\/p>\n<p>\u0412 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <strong>ReactionsFacade<\/strong>, \u044d\u0442\u043e\u0442 \u0444\u0430\u0441\u0430\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u0430\u0434\u0430\u043f\u0442\u0435\u0440.<\/p>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440\u044b \u0444\u0443\u0442\u0435\u0440\u0430 \u043f\u043e\u0441\u0442\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0444\u0430\u0441\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.\u00a0<\/p>\n<h3>\u0424\u0430\u0441\u0430\u0434 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsFacade<\/strong> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u042d\u0442\u043e \u0444\u0430\u0441\u0430\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043a\u0440\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b: \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0435\u043c\u0443 \u0438\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>\u0424\u0430\u0441\u0430\u0434 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044c\u044e\u0445\u0443 <strong>ReactionsView<\/strong> \u0438 \u043a\u043e\u043d\u0444\u0438\u0433 \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u2014 <strong>ReactionsConfig<\/strong>.\u00a0<\/p>\n<p>\u041a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430: \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u043a\u0430\u0441\u0430\u043d\u0438\u0439 (\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <strong>setOnTouchListener<\/strong>); \u0430 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043d\u043e\u043f\u043a\u0443, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>View.OnTouchListener<\/strong>. \u0423 <strong>ReactionsView<\/strong> \u0435\u0441\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <strong>onTouch<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u0432\u044c\u044e\u0445\u0430, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u0451\u043b \u0442\u0430\u0447;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0442\u0430\u0447\u0430 <strong>MotionEvent<\/strong>;\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440, \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u044c\u044e\u0445\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0431\u044a\u0435\u043a\u0442, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>Reactionable<\/strong> (\u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u0441\u0442).<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 <strong>ReactionsFacade<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f <strong>ReactionsConfig<\/strong> \u2014 \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsView<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 ReactionsView \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438<\/h3>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsView<\/strong> \u2014 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0432\u044c\u044e\u0445\u0430\u043c\u0438 \u0434\u043b\u044f <strong>ReactionsFacade<\/strong>.<\/p>\n<p>C\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u043a\u0430\u0437 \u043f\u043e\u043f-\u0430\u043f\u0430 <strong>ReactionsPopupWindow<\/strong> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 <strong>ShowReactionRunnable<\/strong>. ReactionsPopupWindow \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0432\u044c\u044e\u0445\u0443 ReactionsPopupView. \u0412 \u043d\u0435\u0439 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0431\u0430\u0431\u043b \u043f\u043e\u043f-\u0430\u043f\u0430 \u0438 \u0432\u0441\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<pre><code class=\"kotlin\">inner class ShowReactionRunnable(         private val reactionSet: ReactionSet ) : Runnable {     override fun run() {         val view = getAnchorView() ?: return         view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)         openPopup(view, reactionSet)     } }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u0442\u0430\u0447\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432\u043e \u0432\u044c\u044e\u0445\u0443 <strong>ReactionsPopupView<\/strong> \u2014 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u0434\u043b\u0438\u043d\u043d\u043e\u0433\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0440\u0435\u0430\u043a\u0446\u0438\u0438, \u043d\u0435 \u043e\u0442\u0440\u044b\u0432\u0430\u044f \u043f\u0430\u043b\u0435\u0446 \u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ReactionsPopupWindow<\/strong> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a <strong>PopupWindow<\/strong>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432\u044c\u044e\u0445\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 <strong>ReactionsPopupView<\/strong> \u043a \u043e\u043a\u043d\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>ReactionsPresenter<\/strong> (\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0440\u043e\u043b\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u0430) \u2014 \u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsButtonTouchDelegate<\/strong> \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0436\u0435\u0441\u0442\u043e\u0432 \u0441 \u043a\u043d\u043e\u043f\u043a\u0438.\u00a0<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0436\u0435\u0441\u0442\u044b:<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0421\u043a\u0440\u043e\u043b\u043b \u2014 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0442, \u0442\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0442\u0430\u0447\u0435\u0439, \u0447\u0442\u043e\u0431\u044b \u0442\u0430\u0447\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438\u0441\u044c <strong>RecyclerView<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0434\u0438\u043d\u043e\u0447\u043d\u043e\u0435 \u0438 \u0434\u043e\u043b\u0433\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u2014 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043f-\u0430\u043f \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0430\u0447\u0438 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0443\u0436\u0435 \u0432 \u0435\u0433\u043e \u0432\u044c\u044e\u0445\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e, \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 <strong>onTouch<\/strong> \u0432 <strong>ReactionsButtonTouchDelegate<\/strong>.<\/p>\n<ul>\n<li>\n<p>\u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <strong>MotionEvent.ACTION_DOWN<\/strong> \u2014 \u043c\u0435\u0442\u043e\u0434 <strong>onTouchDown<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchDown(         view: View,         viewHolder: ReactionableViewHolder,         event: MotionEvent,         model: Reactionable ): Boolean {     val activePointerId = event.getPointerId(FIRST_POINTER_INDEX)     this.view.setActivePointerId(activePointerId)     this.view.setAnchor(view, viewHolder)     scrollTouchDelegate.setEvent(event)     presenter.setModel(model)     (view.parent as? ViewGroup)?.requestDisallowInterceptTouchEvent(true)     startTime = System.currentTimeMillis()     this.view.showDelayed(model)     this.view.showRipple(event.x, event.y)     return true }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>MotionEvent.ACTION_UP<\/strong> \u2014 <strong>onTouchUp<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchUp(): Boolean {     performClickIfNeeded()     view.closePopup()     return true }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>MotionEvent.ACTION_CANCEL<\/strong><em> \u2014 <\/em><strong>onTouchCancel<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchCancel(): Boolean {     view.closePopup()     return true }<\/code><\/pre>\n<ul>\n<li>\n<p><strong>MotionEvent.ACTION_MOVE<\/strong><em> \u2014 <\/em><strong>onTouchMove<\/strong>:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">private fun onTouchMove(event: MotionEvent): Boolean {     val isScrollGesture = scrollTouchDelegate.isScroll(event)     if (isScrollGesture) {         view.closePopup()     }     return !isScrollGesture }<\/code><\/pre>\n<p>\u0418 \u0435\u0449\u0451 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p><strong>ReactionsStateController<\/strong> \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 UI.<\/p>\n<\/li>\n<li>\n<p><strong>ReactionsViewSettings<\/strong> \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430.\u00a0<\/p>\n<p>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c:<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0441 \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u043c \u043e\u0442 \u044f\u043a\u043e\u0440\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0438 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043f-\u0430\u043f;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u0441\u0442\u0443\u043f\u044b \u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u043f-\u0430\u043f\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0432 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u0438 \u043d\u0435\u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0446\u0432\u0435\u0442 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p><strong>ReactionsCallback<\/strong> \u2014 \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0431 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f-\u0430\u043f\u0430, \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0438 \u0435\u0451 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412 <strong>ReactionsView<\/strong> \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0441\u043b\u0430\u0431\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>ReactionViewHolder<\/strong> (\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441). <strong>ReactionViewHolder<\/strong> \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0432\u044c\u044e\u0445\u0443 \u0441 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u0438. \u0412\u0441\u0435 \u0432\u044c\u044e\u0445\u043e\u043b\u0434\u0435\u0440\u044b \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u2014 \u044d\u0442\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 <strong>ReactionViewHolder<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u043e\u043f-\u0430\u043f \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439<\/h3>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>ReactionsPopupWindow<\/strong> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a <strong>PopupWindow<\/strong>. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043a \u043e\u043a\u043d\u0443 \u0432\u044c\u044e\u0445\u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u043b\u0441\u044f \u043f\u043e\u043f-\u0430\u043f \u0432\u044b\u0431\u043e\u0440\u0430 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 <strong>ReactionsPopupView<\/strong>.\u00a0<\/p>\n<p><strong>ReactionsPopupView<\/strong> \u2014 \u0432\u044c\u044e\u0445\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d. \u0412 <strong>onLayout<\/strong> \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u0441\u0430\u043c\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0438. \u041f\u043e\u043f-\u0430\u043f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u043e \u0441\u043a\u0440\u043e\u043b\u043b\u043e\u043c \u2014 \u0442\u0430\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u044b. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044c\u044e\u0445\u0438, \u0430\u043d\u0438\u043c\u0430\u0442\u043e\u0440 <strong>ReactionsPopupViewAnimator<\/strong> \u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0442\u0430\u0447\u0435\u0439 <strong>ReactionsPopupTouchDelegate<\/strong>.<\/p>\n<p><strong>ReactionsViewSettings<\/strong> \u2014 \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.\u00a0<\/p>\n<h3>\u0418\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 <strong>onMeasure<\/strong> \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0432\u044c\u044e\u0445\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0441 \u0440\u0435\u0430\u043a\u0446\u0438\u044f\u043c\u0438.<\/p>\n<pre><code class=\"kotlin\">override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {     val width = MeasureSpec.getSize(widthMeasureSpec)     val height = MeasureSpec.getSize(heightMeasureSpec)      val needUpdateVisibleRect = !isPopupHiding     if (!checkAnchor(needUpdateVisibleRect, width, height)) {         dismissListener?.invoke()         return     }      super.onMeasure(widthMeasureSpec, heightMeasureSpec)      measureTitles()     measurePopupWidth()      if (needUpdateVisibleRect) {         calcPopupCoordinates()     }      val popupWidthMeasureSpec = MeasureUtils.makeSpecExactly(dialogWidth)     val popupHeightMeasureSpec = MeasureUtils.makeSpecExactly(dialogHeight)     scrollView.measure(popupWidthMeasureSpec, popupHeightMeasureSpec) }<\/code><\/pre>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <strong>measureTitles<\/strong> \u0438\u0437\u043c\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432\u044c\u044e\u0445\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0434\u043f\u0438\u0441\u0435\u0439 \u0440\u0435\u0430\u043a\u0446\u0438\u0439.<\/p>\n<pre><code class=\"kotlin\">private fun measureTitles() {     \/\/ \u0418\u0437\u043c\u0435\u0440\u044f\u0435\u043c \u0432\u0441\u0435 textView, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0432 onLayout \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e     for (index in titleViews.indices) {         titleViews[index].measure(0, 0)     } }<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <strong>measurePopupWidth<\/strong> \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u0442 \u0448\u0438\u0440\u0438\u043d\u0443 \u043f\u043e\u043f-\u0430\u043f\u0430. \u0415\u0441\u043b\u0438 \u043e\u043d\u0430 \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432, \u0442\u043e \u0438\u0442\u043e\u0433\u043e\u0432\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"kotlin\">private fun measurePopupWidth() {     when {         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 \u0434\u0438\u0430\u043b\u043e\u0433 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432         originalDialogWidth &lt; this.measuredWidth - settings.screenPaddingStart - settings.screenPaddingEnd -> {             screenPaddingStart = settings.screenPaddingStart             screenPaddingEnd = settings.screenPaddingEnd             dialogWidth = originalDialogWidth         }         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 \u0434\u0438\u0430\u043b\u043e\u0433 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432         originalDialogWidth &lt; this.measuredWidth - settings.screenPaddingSmallStart - settings.screenPaddingSmallEnd -> {             screenPaddingStart = settings.screenPaddingSmallStart             screenPaddingEnd = settings.screenPaddingSmallEnd             dialogWidth = originalDialogWidth         }         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e\u043f-\u0430\u043f \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b, \u0442\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-331844","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/331844","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=331844"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/331844\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=331844"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=331844"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=331844"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}