MotionLayout as parent of CoordinatorLayout broke scrolling - android-coordinatorlayout

When CoordinatorLayout is used inside of MotionLayout and while screen scrolling some view requests layout (via requestLayout() function), the rest of the scrolling is broken.
The layout structure is:
<MotionLayout>
<View/> <!-- Animated with motion scene -->
<CoordinatorLayout>
<AppBarLayout>
<ImageView/> <!-- Requests layout -->
</AppBarLayout>
<RecyclerView/>
</CoordinatorLayout>
<MotionLayout>
The MotionScene:
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="#id/end"
app:constraintSetStart="#id/start" />
<ConstraintSet android:id="#+id/start">
<Constraint android:id="#id/background">
<PropertySet android:alpha="0" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#id/background">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
</MotionScene>
The animation progress is calculated like this:
appBarLayout.addOnOffsetChangedListener(OnOffsetChangedListener { _, verticalOffset ->
motionLayout.progress = -verticalOffset / appBarLayout.totalScrollRange.toFloat()
})
The key points are next:
AppBarLayout (as part of Coordinator layout) notifies (thru listener) about scrolling position changes.
MotionLayout changes its progress according to the scrolling position mentioned above.
While scrolling some view should call requestLayout() - in my example it happens on ImageView click
After that, any following scrolling will be broken and the layout looks invalid.
To identify the root cause I've tried to remove the line with MotionLayout.setProgress() with the rest of the code remains unchanged. And after that scrolling has worked as expected. After this I decided to put back MotionLayout.setProgress() and this time I've removed View.requestLayout(). And this time scrolling works as expected too. But when I'm trying to put back both MotionLayout.setProgress() and View.requestLayout() the scrolling broke.
Also I've submitted a bug to the Google issue tracker: https://issuetracker.google.com/u/1/issues/178976381

By default MotionLayout ignores requestLayout during transitions. This is done for performance. To enable in your tag add
layoutDuringTransition="honorRequest"

Related

React Native - Auto scroll down with webview text being input

I'm using react-native-pell-rich-editor which is built upon the WebView component. As soon as I get to the bottom of the visible WebView (after typing about 20 lines) the text that I'm typing into the RichEditor is appearing below the visible area - so the text is being input, but I just can't see it! I have to scroll down every new line to see what I'm typing.
The KeyboardAvoidingView is pushing up my RichEditor (WebView) when the RichEditor is focused.
Is there a way to auto scroll down to where the cursor is when typing? Perhaps there is a better solution?
<ScrollView>
<KeyboardAvoidingView behavior={'padding'}>
<RichToolbar
actions={[ actions.keyboard, actions.setBold, actions.setItalic, actions.setUnderline, actions.setStrikethrough, actions.blockquote, actions.code, actions.alignCenter, actions.alignLeft, actions.alignRight ]}
editor={that.richText}/>
<RichEditor
initialContentHTML={messageBody}
initialFocus={true}
placeholder={'Compose email'}
ref={that.richText}/>
</KeyboardAvoidingView>
</ScrollView>
There are two parts to the way I solved this problem. I did not use KeyboardAvoidingView.
I also placed the RichEditor inside of a ScrollView, but called the ScrollView.scrollToEnd() method after the editor is initialized so that the cursor would be above the keyboard. This happens after a short timeout after calling RichEditor.focusContentEditor in editorInitializedCallback. Note: doing it this way means you do not need to use the initialFocus prop.
For moving the position while the user is typing, call ScrollView.scrollTo() in the ScrollView's onContentSizeChanged prop. You can use the dimension values that are passed to this prop's function to calculate how many pixels to scroll based on the previous dimensions and scroll position stored in the component state.

Xamarin.Forms on iOS: Shrink height of page instead of shifting it up when the softkeyboard appears

Got the problem that the softkeyboard overlaps an entry field placed at the bottom.
XAML code:
<ContentPage.Content>
<AbsoluteLayout VerticalOptions="Fill">
<ScrollView AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,0.9">
<Label Text="Heading" />
</ScrollView>
<Entry x:Name="SearchEntry" AbsoluteLayout.LayoutBounds=".5,1,1,.1" AbsoluteLayout.LayoutFlags="All" Placeholder="Suchen..." ReturnType="Done" />
</AbsoluteLayout>
</ContentPage.Content>
I installed the KeyboardOverlap! plugin via nuget. It shifts the whole page upwards till the entry is visible again. The entry is visible, but the top of the page isn't visible anymore because it's shifted up.
Another often mentioned solution is wrapping the pages's content in a ScrollView. Because I definitively need an AbsoluteLayout as root content, that's unfortunately not a solution.
I'm looking for a solution which shrinks the height of the page and don't just shifts it up when the softkeyboard appears.
Why I need this? The page is filled dynmically with search result based on the entrie's input. If there are only few result, they're not visible because of the page's upward shift. The user could think that there aren't any search results. Displaying a text like 'No search results.' above the entry would be a simple solution but is not an option here.
Using this CustomRenderer class in the iOS project instead of the KeyboardOverlap plugin did the trick.
Don't forget to customize line 14 with your concrete page classname(s) where you need the functionality. Otherwise the renderer is called for all pages in your app!
Many thanks to Jack Hua - MSFT!

How can I change a vaadin grid filter and the layout at the same time?

I have a vaadin grid with some filters on top and the filters can be displayed/hidden by a button.
The problem now is that if the data source of a grid is modified and at the same time the position of the grid changes the grid is not properly redrawn. The grid only shows 5 out of 10 items and a empty line at the top.
The button action is setting setVisible to false and reseting the filters.
filter.addClickListener(event -> {
if (filters.isVisible()) {
location.setValue(null);
filter.setCaption("Filter");
filters.setVisible(false);
} else {
filter.setCaption("Show all");
filters.setVisible(true);
}
});
Is there a way to mark the layout as dirty or to demand a rebuild?
PS: I have a full blown example app with the problem at https://github.com/jansauer/vaadin/tree/filtergrid/
It appears the bug is caused by a bug in Vaadin UI. Simply moving your horizontal-layout with id="filters" behind the grid does the trick.
<v-vertical-layout size-full>
<v-horizontal-layout>
<v-button _id="filter" style-name="borderless-colored">Filtern</v-button>
</v-horizontal-layout>
<v-grid _id="grid" size-full :expand />
<v-horizontal-layout _id="filters" style-name="filters" margin spacing width-full>
<v-text-field _id="name" caption="Name" width="220px" />
<v-combo-box _id="location" caption="Standort" />
<v-css-layout :expand />
</v-horizontal-layout>
</v-vertical-layout>
From my almost 2 years experience with Vaadin I would discourage you from using Vaadin views based on *.html's since I often find weird bugs like this one.

How to scroll to the last appended piece of text on a TextView?

So I have a multi-line TextView on my C# Android application. I'm using this as a kind of "status" logger..
So, I might have things like this:
Probing widgets
Proper widget found
Configuring widget
Where each line might take a few seconds to appear because it's something relatively slow.
So, I have a TextView inside of a ScrollView like so:
<ScrollView
p1:minWidth="100px"
p1:minHeight="100px"
p1:layout_width="fill_parent"
p1:layout_height="match_parent"
p1:id="#+id/scrollView1">
<TextView
p1:id="#+id/terminalOutput"
p1:layout_width="fill_parent"
p1:layout_height="fill_parent" />
</ScrollView>
This works fine and I can just append to the TextView using the .Append method. However, the problem is that eventually there are so many status messages that the text goes down and off the screen. At this point, you have to manually drag in the scroll view to read the latest status messages.
I want it so that whenever a piece of text is appended and it goes off screen for it to scroll the scrollview down so that users can read the latest message without manual scrolling.
How can I do this?
This is what I've tried so far:
Logger = new TextLogger((s) =>
{
RunOnUiThread(() =>
{
var textview=FindViewById<TextView>(Resource.Id.terminalOutput);
textview.Append(s + "\n");
var scrollview=FindViewById<ScrollView>(Resource.Id.scrollView1);
scrollview.ScrollTo(0,scrollview.Bottom);
textview.ScrollTo(0, textview.Bottom);
});
});
This kind of works, but it seems like it never quite scrolls to the actual bottom. It scrolls down, but is always like 2 lines away from the bottom, leaving some text still hidden
Try using ScrollView.FullScroll method instead:
scrollview.FullScroll(Android.Views.FocusSearchDirection.Down)

Silverlight: Restrict RowDetailsTemplate width to it's parent DataGrid's width

I'd like to bind the Width of my RowDetailsTemplate to the Width of my DataGrid, so that the row details are not surrounded with scroll bars.
Here's the problem:
Notice that the RowDetailsTemplate contains hidden content that must be scrolled into view - which is terrible. The user must drag the scroll bar at the very bottom bottom of the DataGrid in order to see the rest of the row's details - which is very unintuitive. I really want the row details to layout its content such that no scrolling is necessary.
Any suggestions?
Thanks,
Charles
I did find the solution for a similar problem in WPF, you can find it here: DataGrid RowDetails Width problem
I don't know if it works in silverlight, but give it a try.
The answers here felt like a workaround so I did some research and did
find the solution on the Telerik forums, since we use their
RadGridView. Turned out the solution worked for DataGrid as well.
The key is to set the ScrollViewer.HorizontalScrollBarVisibility
property to Disabled, see example below.
<DataGrid ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border>
<TextBlock Foreground="White" Text="{Binding RowDetails}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate> </DataGrid>
Setting the AreRowDetailsFrozen property on my DataGrid to true solved my problem. Example:
<data:DataGrid AreRowDetailsFrozen="True" />

Resources