- Automatic scroll on Input focus in Modals doesn’t work on Android Chrome #17338
- Comments
- Domtaholic commented Aug 26, 2015
- kkirsche commented Aug 26, 2015
- cvrebert commented Aug 26, 2015
- Domtaholic commented Aug 27, 2015
- Domtaholic commented Sep 2, 2015
- cvrebert commented Sep 2, 2015
- cvrebert commented Mar 16, 2016
- twbs-lmvtfy commented Mar 16, 2016
- Custom View, скроллинг и жесты в Android на примере простого вьювера картинок
- Scrolling Behavior for Appbars in Android
- Basic Setup
- Standard App bar scrolling with only Toolbar
- App bar scrolling with tabs
- App bar scrolling with Flexible space
- App bar scrolling with image in Flexible space
- App bar scrolling with overlapping content in Flexible space
Automatic scroll on Input focus in Modals doesn’t work on Android Chrome #17338
Comments
Domtaholic commented Aug 26, 2015
we got a couple of longer modals with forms. When you focus a input the browser automatically scrolls to a position where you can see the input and the keyboard.
That works on the Nexus 6 like a charm on our normal inputs, but on the inputs inside a modal it doesn´t do anything on the first focus when the keyboard gets visible.
The text was updated successfully, but these errors were encountered:
kkirsche commented Aug 26, 2015
Per CONTRIBUTING.md, bug reports should include an isolated example of the problem with instructions (as necessary) for us to reproduce the problem. The following can be used as a template on JSBin if that would be helpful.
Thanks for your understanding and cooperation!
cvrebert commented Aug 26, 2015
What version of Android and what version of Chrome?
Domtaholic commented Aug 27, 2015
Thx for the reply,
i updated the jsbin:
Now if you focus one of the inputs the browser scrolls to a position where the keyboard is below the input field so you can see it while you typing.
Now open the Modal and try the same, on the Nexus that doesn´t work as expected.
Android Version: 5.1.0
Chrome: 40.0.2214.89
Domtaholic commented Sep 2, 2015
Is there any news about this? Can you confirm the issue?
cvrebert commented Sep 2, 2015
@twbs/team Anyone have an Android device to test this with?
That said, we’re kinda at the mercy of the browser here. Besides filing a Chrome bug, I’m uncertain there’s much we’ll be able to do much here that wouldn’t either be super-hacky or necessitate a complete rework of our modals.
cvrebert commented Mar 16, 2016
twbs-lmvtfy commented Mar 16, 2016
You appear to have posted a live example (http://jsbin.com/milofi/1/edit), which is always a good first step. However, according to Bootlint, your example has some Bootstrap usage errors, which might potentially be causing your issue:
- line 24, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 27, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 30, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 33, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 36, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 39, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 42, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 45, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 48, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 51, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 54, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 56, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 59, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 62, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 65, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 68, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 71, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 90, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 93, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 96, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 99, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 102, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 105, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 108, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 111, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 114, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 117, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 120, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 122, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 125, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 128, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 131, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 134, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
- line 137, column 14: E013: Only columns ( .col-*-* ) may be children of .row s
You’ll need to fix these errors and post a revised example before we can proceed further.
Thanks!
(Please note that this is a fully automated comment.)
Источник
Custom View, скроллинг и жесты в Android на примере простого вьювера картинок
В статье описываются детали реализации простого вьювера картинок и показываются некоторые тонкости имплементации скроллинга и обработки жестов.
И так, начнем. Ми будем разрабатывать приложения для просмотра картинок. Готовое приложение выглядит так (хотя скриншоты, конечно, слабо передают функционал):
Установить приложение можно либо из Маркета, либо установив вручную отсюда. Исходный код доступен здесь.
Главным элементом нашего приложения является класс ImageViewer который мы и будем разрабатывать. Но нужно также отметить, что для выбора файла для просмотра я не стал изобретать велосипед и взял готовый «компонент» здесь.
Компонент представляет собой activity, который вызывается при старте из главного activity. После выбора файла, мы его загружаем и показываем на экране с помощью класса ImageViewer. Рассмотрим класс более подробно.
Класс является наследником класса View и переопределяет только один его метод onDraw. Также класс содержит конструктор и метод загрузки изображения:
Если мы загрузим картинку по размерам больше чем экран смартфона, то отобразится только часть ее и у нас не будет способа ее подвинуть или уменьшить.
Добавим теперь возможность скроллинга. Скроллинг по своей сути представляет собой жест, при котором пользователь дотрагивается пальцем к экрану, передвигает его не отрывая, и отпускает. Для того чтоб иметь возможность обрабатывать события связанные с тач-скрином, нужно переопределить метод onTouchEvent. Метод принимает один параметр типа MotionEvent и должен возвратить true в случае обработки события. Через этот метод можно реализовать поддержку любого жеста, включая скроллинг.
Для распознавания скроллинга нам нужно зафиксировать момент дотрагивания, перемещения и отпускания. К счастью нету необходимости делать это вручную так как в Android SDK есть класс делающий всю работу за нас. Таким образом для того чтоб распознать жест скроллинга, нужно добавить в наш класс поле типа GestureDetector которое инициализируется объектом реализующим интерфейс OnGestureListener (именно этот объект будет получать события скроллинга). Также нужно переопределить метод onTouchEvent в классе ImageViewer и передавать обработку событий из него в наш объект типа OnGestureListener. Измененный класс ImageViewer (без неизмененных методов) представлен ниже:
Как видно на самом деле ми наследуем MyGestureListener не от OnGestureListener, а от SimpleOnGestureListener. Последний класс просто реализует интерфейс OnGestureListener с помощью пустых методов. Этим мы избавляем себя от реализации всех методов, выбирая только те, что нужно.
Теперь если загрузить большую картинку, мы, по крайней мере, сможем скролить ее. Но: во первых мы можем проскроллить за рамки картинки, во вторых нету скроллбаров, которые бы подсказали нам где мы находимся и сколько еще осталось до краев.
Решим для начала вторую проблему. Поиск в Интернет приводит нас к тому, что нужно переопределить методы computeHorizontalScrollRange и computeVerticalScrollRange. Эти методы должны возвратить реальные размеры картинки (на самом деле есть еще методы которые имеют отношение к скроллбарам – это методы computeHorizontalScrollExtent, computeHorizontalScrollOffset и такая же пара для вертикального скроллбара. Если переопределить и их, то тогда возвращать можно более произвольные значения). Но этого оказывается недостаточно – скроллбары в первых нужно включить, во вторых проинициализировать. Включаются они методами setHorizontalScrollBarEnabled и setVerticalScrollBarEnabled, инициализируются методом initializeScrollbars. Но вот незадача – последний метод принимает немного непонятный параметр типа TypedArray. Этот параметр должен содержать в себе набор стандартных для View атрибутов. Список можно увидеть здесь в таблице «XML Attributes». Если бы мы создавали наш view из XML, Android runtime бы автоматически составил такой список. Но так как мы создаем класс программно, нужно также создать этот список программно. Для этого нужно создать файл attrs.xml в каталоге res\values с таким содержимым:
В файле просто перечислены все атрибуты, которые были указаны в таблице, упомянутой выше (кроме некоторых на которые указывает компилятор как на ошибку – видимо в документации список приведен самый последний). Измененный класс ImageViewer (кроме неизменных методов):
Не хотелось бы на этом останавливаться, поэтому давайте добавим поддержку жеста «бросок» (fling). Этот жест есть просто дополнение к жесту скроллинга, но учитывается скорость перемещения пальца в последние моменты (перед отпусканием), и если она не нулевая, скроллинг продолжается с постепенным затуханием. Поддержка этого жеста уже заложена в GestureDetector – поэтому нам нужно всего лишь переопределить метод onFling в классе MyGestureListener. Отловив это событие нам нужно еще некоторое время изменять положение скроллинга. Конечно, это можно сделать «вручную» с помощью таймеров или еще как, но опять же в Android SDK уже есть класс, реализующий нужный функционал. Поэтому нужно добавить в класс ImageViewer еще одно поле типа Scroller, которое и будет заниматься «остаточным» скроллингом – для старта скроллинга нужно вызвать его метод fling. Также нужно показать скроллбары (они ведь прячутся когда не нужны) вызовом метода awakenScrollBars. И последнее что нужно сделать – это переопределить метод computeScroll, который должен непосредственно делать скроллинг с помощью метода scrollTo (класс Scroller сам не занимается скроллингом – он просто работает с координатами). Код измененного класса ImageViewer представлен ниже:
В завершения разговора о жесте fling надо сделать одну мелочь – при прикосновении пальцем во время скроллинга от броска, нужно остановить скроллинг. На этот раз мы это сделаем «вручную» в методе onTouchEvent. Измененный метод представлен ниже:
Уже можно любоваться достаточно интересной физикой, но можно увидеть некоторые «глюки» при скроллинге за пределы картинки. Это происходит из-за того, что fling работает только в пределах картинки, а скроллинг без броска работает везде. Т.е. мы сможем выйти за рамки картинки только если очень плавно скролить (чтоб не срабатывал fling). Исправить этот «косяк» можно путем введения ограничение на обработку в метод onFling и обрабатывать бросок только если он не выходит за границы картинки. Измененный метод представлен ниже:
Теперь мы опять можем беспрепятственно скролить за рамки картинки. Кажется, эту проблему мы уже вспоминали… У нее есть элегантное решение, лежащее в том, что при отпускании пальца (при завершении скроллинга за рамками картинки) нужно картинку плавно вернуть в «положенное» место. И опять мы это сделаем «вручную» в методе onTouchEvent:
Вот теперь с уверенностью можно сказать что со скроллингом мы разобрались. Можем переходить к последнему жесту который хотелось бы реализовать – это жест pinch zoom.
Со стороны жест выглядит как растягивание или сжатие чего-то воображаемого на экране смартфона двумя пальцами. Пошагово жест происходит так: нажатие одним пальцем, нажатие вторым пальцем, изменение положения одного или двух пальцев не отпуская, отпускание второго пальца. Для определения величины масштабирования нужно вычислить соотношение между расстояниями между пальцами в момент начала жеста и в момент окончания жеста. Расстояние между пальцами находится по формуле sqrt(pow(x2 – x1, 2) + pow(y2 – y1, 2)). Также нужно отметить некоторое положение скроллинга которое нужно сохранять – ведь если жестом увеличить картинку, то положение скроллинга изменится (из-за измененного размера картинки). Это положение – а точнее точка, положение которой нужно сохранить, в терминологии Android SDK называется фокальной точкой, и находиться она посередине между двумя пальцами.
Реализовать жест как всегда можно самому, но и это к счастью уже реализовано в Android SDK (правда, только начиная с версии 2.2). Поможет в этом класс ScaleGestureDetector, инстанс которого добавим в наш класс. ScaleGestureDetector инициализируется обьектом, поддерживающим интерфейс OnScaleGestureListener, поэтому создадим также внутренний класс MyScaleGestureListener, который реализует методы onScaleBegin, onScale и onScaleEnd. Не забываем передать управление ScaleGestureDetector из метода onTouchEvent. Ну и самое главное – нужно как-то использовать данные масштабирования: их нужно учитывать во всех местах, где раньше фигурировали ширина и высота картинки (т.е. фактически нужно умножить эти параметры на коэффициент масштабирования). Финальный код класса ImageViewer можно посмотреть в исходниках.
На этом все. Надеюсь статься окажется полезной.
Источник
Scrolling Behavior for Appbars in Android
Jan 1, 2017 · 5 min read
App bars contains four main aspects, that plays huge role in scrolling behavior. They are,
AppBar scrolling behavior enriches the way contents in a page presented.
I am going to share my experience about how easily we can understand and use the elevation in scrolling, sizing the flexible spaces, how to anchor specific elements.
App Bar has following scrolling options,
- Standard App bar scrolling with only Toolbar
- App bar scrolling with tabs
- App bar scrolling with Flexible space
- App bar scrolling with image in Flexible space
- App bar scrolling with overlapping content in Flexible space
If you wish to jump into the code directly, Here is the Github repository link.
Basic Setup
Before we start jumping in and see all types of scrolling behavior, we needs to be clear about the basic setup and implementation.
Us e design support library to achieve AppBar scrolling behavior. This library provides many of the material design components.
In app build.gradle,
Extend android.support.v7.app.AppCompatActivity in the Activity class.
In the layout xml, we need to have CoordinatorLayout in the top. Add Toolbar inside AppBarLayout and the AppBarLayout needs to be inside the CoordinatorLayout. CoordinatorLayout is the one, which gives proper scrolling and material animations to the views attached with it like FloatingButtons, ModalSheets and SnackBar.
That’s it. We have done with the basic implementation and after this, there are some flags that will decide the scrolling behavior.
Standard App bar scrolling with only Toolbar
- scroll off-screen with the content and returns when the user reverse scrolls.
- stay fixed at the top with content scrolling under it.
To achieve this, apart from the above basic setup code implementation:
The Toolbar needs to have app:layout_scrollFlags
scroll -will be scrolled along with the content.
enterAlways -when content is pulled down, immediately app bar will appear.
snap -when the AppBar is half scrolled and content scrolling stopped, this will allow the AppBar to settle either hidden or appear based on the scrolled size of Toolbar.
Once app:layout_scrollFlags added to Toolbar, the content view (Either a NestedScrollView or RecyclerView) needs to have app:layout_behavior tag.
That’s it these two tags along with basic setup is enough to achieve the Standard AppBar with Toolbar scrolling behavior. We can get different behaviors by playing with app:layout_scrollFlags.
Here is clear explanation from Android docs for the flags,
App bar scrolling with tabs
- TabBar stays anchored at the top, while the Toolbar scrolls off.
- Whole AppBar stays anchored at the top, with the content scrolling underneath.
- Both the toolbar and tab bar scroll off with content. The TabBar returns on reverse-scroll, and the Toolbar returns on complete reverse scroll.
To achieve this, we need to add TabLayout inside the AppBarLayout and provide the layout_scrollFlags inside TabLayout. That will be enough to achieve this and we can play around with the scrolling behavior like above examples by just altering the layout_scrollFlags.
App bar scrolling with Flexible space
- The flexible space shrinks until only the toolbar remains. The title shrinks to 20sp in the navigation bar. When scrolling to the top of the page, the flexible space and the title grow into place again.
- The whole app bar scrolls off. When the user reverse scrolls, the toolbar returns anchored to the top. When scrolling all the way back, the flexible space and the title grow into place again.
To get Flexible space for AppBar, we need to use CollapsingToolbarLayout around the ToolBar tag. Which means CoordinatorLayout in the top and AppBarLayout, CollapsingToolbarLayout, ToolbarLayout inside the order.
We need to add height for the AppBarLayout and need to specify app:layout_scrollFlags for CollapsingToolbarLayout.
Also we need to add app:layout_collapseMode=”pin” tag in Toolbar.
exitUntilCollapsed -flag will make the Flexible space scrolled down while scrolling back to position along with the content.
App bar scrolling with image in Flexible space
- Similar to the above Flexible space behavior. When scrolling image will pushed up with slight animation and the color changes to primary color.
- While reversing the scrolling primary color fades away to leave way for the image been pulled down with a slight animation.
It is very much similar to the Flexible Space implementation with the below changes,
- ImageView needs to added inside CollapsingToolbarlayout.
- AppBarLayout height specified 200dp will be applied to image.
App bar scrolling with overlapping content in Flexible space
- In this scrolling, the AppBar with Flexible space will be placed behind the content. Once content starts scrolling, the app bar will scroll faster than the content until it gets out of the overlapping content view. Once the content reaches top, app bar comes upside of the content and content goes underneath and scrolls smoothly.
- The whole AppBar can scroll off-screen along with content and can be returned while reverse scrolling.
- There will not be any TabBar placement in this behavior.
This can be achieved by using app:behaviour_overlapTop in the NestedScrollView or RecyclerView. Also in this case we are specifying height value for CollapsingToolbarLayout .
Also we can implement and specify the scrollFlags dynamically through java code.
Hopefully this article will help you to implement scrolling behaviors for AppBar.
I posted this article originally on my blog.
Code for demo app is available on Github.
If you like the article, follow me on Medium and Twitter. You can also find me on LinkedIn.
Источник