im using Xamarin with MvvmCross.
Ive done a FragmentDialog with a recyclerView inside, the list is populated via bindings on xml file, so i have no adapter and i should keep it this way.
If im not wrong, theres no built in way to make the recyclerView take only the size needed for its content, this should not be a problem, but in this case i need the list to start from bottom...
So i did this (its a custom fullscreen dialog) :
MvxRecyclerView list = Dialog.FindViewById<MvxRecyclerView>(Resource.Id.recyclerview);
list.LayoutChange += List_LayoutChange;
Then in layoutChange
private void List_LayoutChange(object sender, View.LayoutChangeEventArgs e)
{
MvxRecyclerView list = Dialog.FindViewById<MvxRecyclerView>(Resource.Id.recyclerview);
int itemHeight = list.GetChildAt(0).Height;
if (itemHeight != 0)
{
ViewGroup.LayoutParams prms = list.LayoutParameters;
prms.Height = itemHeight * list.GetAdapter().ItemCount;
list.LayoutParameters = prms;
list.LayoutChange -= List_LayoutChange;
list.RequestLayout();
}
}
That was working fine, the list get exactly the height needed and the list looks like it starts from bottom.
Now the client tell me that he doesnt like the fullscreen dialog and wants the status bar, i think that should be easy, just to remove this line at the dialog creation right?
dialog.Window.AddFlags(WindowManagerFlags.Fullscreen);
But looks like its not that easy, when the dialog its not fullscreen the layoutParams change seems to have no effect, it just dont do nothing.
My method is being called and i get the right item height, it just dont change the recyclerview height.
Notice that setting fullscreen at creation and clearing the flag after the recyclerview params change works
So looks like it only works during fullscreen mode.
Can someone throw some light at this?
Thanks in advance.
As you said, RecyclerView was not aware of its size.
Since last update to the support lib, it is !
http://android-developers.blogspot.fr/2016/02/android-support-library-232.html
The RecyclerView widget provides an advanced and flexible base for creating lists and grids as well as supporting animations. This release brings an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. This means that previously unavailable scenarios, such as using WRAP_CONTENT for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.
I would suggest to wait for the Xamarin wrapped lib (there is already a beta https://www.nuget.org/packages/Xamarin.Android.Support.v4/23.2.0-beta1)
Related
I'm creating an OverflowPanel derived from the WPF Panel class. The intent is that it will fill with items in a single direction, and when there are too many items to display, excess items will be removed and replaced with another control to hold the overflow. Think of a website's breadcrumbs, or the address bar in Windows File Explorer. This is a .Net Core 3/C# 8 project.
I have a partially working solution: I've inherited from Panel and overridden MeasureOverride() and ArrangeOverride() to get the behavior I want. My problem now is getting a button or some other control to display in place of the items being removed.
My initial, naive approach was to just create a Button in code and try to Measure/Arrange it.
public class OverflowPanel : Panel
{
// First by itself, but I did also try to host this in a new UIElementCollection
private readonly Button _overflowButton = new Button();
public override Size MeasureOverride(Size availableSize)
{
...
_overflowButton.Measure(availableSize);
// Do stuff with _overflowButton.DerivedSize.
...
}
// Also attempted to draw int in ArrangeOverride()
}
This did give me non-zero result for the measurement. (I put some dummy content in the button.) My algorithm gives me space on the screen where the button should go, however, nothing gets rendered there.
I also confirmed that there wasn't simply a button being drawn with no visual style, by inspecting the Live Visual Tree in Visual Studio.
I tried to make a UIElementCollection and add the button to that to see if it would add it to the visual tree, but this also did not work.
Most Google/StackOverflow results I've seen suggest something along the lines of this.Children.Add(_overflowButton), but this does not work when hosted inside an ItemsControl, as it takes over managing the collection of objects and throws an exception if you attempt to mess with it.
After digging around in the code for Panel and UIElementCollection, I noticed that Panel lets you override
UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent)
to use a derived implementation of UIElemenetCollection. I created a PinningUIElementCollection to trick WPF into rendering the extra element. It stores extra items and then slips them in whenever the iterator is accessed. It also does index mangling to access both the extra collection of items and the automatically generated one.
This actually worked. My button is now displayed (albeit without the correct styling, but that's a separate issue.)
However my issue with this approach is that it seems like a lot of work. It also seems error prone: I could easily miss when it tries to use a numerical index and forget to mangle it, causing unpredictable results.
Is there a simpler/more straightforward way, in my derived Panel implementation, to display an extra button or some other arbitrary control with only a few less hoops?
When I attach a scrollview to a function like this
textScroll.Scrolled += (sender, e) => { onScrolled(); };
Each time I scroll up or down, OnScrolled() is called multiple times. I know I can get the size of the content and compare it to the ScrollY value, obviously the ScrollY value changes each time, but as far as I can see I won't know when the last call happens (per user scroll).
I only want to call this once per scroll, failing that call it each time as is happening now, but only act when I know I'm on the last call.
Is this possible?
thanks
It is possible, but with a custom renderer for each platform.
On iOS: you will want to implement delegates for DecelerationEnded and WillEndDragging. The reason for also implementing DecelerationEnded is to allow for a fling by the user and waiting for the velocity to come to 0.
On Android it is a bit more complicated. Here is a native Android SO post I followed and translated into c# in a renderer. Works pretty well for me.
Android: Detect when ScrollView stops scrolling
After having both implemented, you can call to your Xamarin.Forms view in order to notify that the view has Stopped scrolling (i.e. final call)
I have na uwp app (published in Windows/Microsoft Store), and the app title bar is normally this:
I was doing some tests in my app (to test the fluent design system) and I made some changes and I did not notice, because now it appears like this:
The name of my app has disappeared and the ellipsis (...) that is included in the header of the page also does not appear.
How can I resolve this?
It happened to me too exactly when I was testing fluent design system!
To recreate the issue. Simply Add
// Extend acrylic
extendAcrylicIntoTitleBar(); to OnLaunched at App.xamel.cs
Then add following code to App.xamel.cs
/// Extend acrylic into the title bar.
private void extendAcrylicIntoTitleBar()
{
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
ApplicationViewTitleBar titleBar =
ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
}
Next you need to fix the missing using by hitting Ctrl + . key.
At this point the title bar disappear. Even removing the extendAcrylicIntoTitleBar() function will not solve the issue!
The title bar will appear again if I remove following
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.ApplicationModel.Core;
I am not sure if it is a issue. That seems to be the way fluent design works
Above test is done according to
https://learn.microsoft.com/en-us/windows/uwp/design/style/acrylic#acrylic-theme-resources
The last value is cached in the registry. Try deleting this:
[HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\<GUID_PublisherID>\PersistedTitleBarData\<GUID_PublisherID>!App]
"AppVersion"=hex(b):00,00,00,00,00,00,01,00
"ExtendViewIntoTitleBar"=dword:00000001
Also saved nearby is last window position, and splash screen info.
I have been struggling with printing using the System.Printing namespace. I have finally figured out that the reason I was getting blank results when using portions of the API was because the Visual objects I was trying to print were not Loaded/Initialized. If I display the Visual objects by putting them in an appropriately-sized Windows and calling Show() prior to printing, I then get the expected results.
Thus, the workaround I came up with was to call this method for every Visual
public static void ShowVisual(Visual visual)
{
Window window = new Window
{
Content = visual,
SizeToContent = SizeToContent.WidthAndHeight,
Visibility = Visibility.Hidden
};
window.Show();
window.Close();
}
This seems like a hack, especially since the user briefly sees the Window-frame draw. I figure there must be a different way it is supposed to be done. However, I am not turning up any other solutions. Is using a hidden Window really what is supposed to be done here?
Using a MenuItem as described at WPF - Get size of UIElement in Memory? does not work. I looked at Force rendering of a WPF control in memory but I am not really wanting to render the Visual to a bitmap which seems to be what that is for. Calling ApplyTemplate() on the Image that as described in wpf force to build visual tree did not help.
EDIT: This is the solution that is used instead of ShowVisual from above
/// <remarks>
/// This method needs to be called in order for
// the element to print visibly at the correct size.
/// </remarks>
private static void ArrangeElement(UIElement element)
{
var box = new Viewbox {Child = element};
box.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
box.Arrange(new Rect(box.DesiredSize));
}
The items you want to print need to be added to the visual tree in WPF in order for the Measure and Arrange processes to be called on all the elements in the visual tree you want to show / print or otherwise display.
I haven't done this for a while but you may find that adding these items to a ViewPort in the background and then printing them solves the issue. This should get around the need for actually displaying them on the screen and thus the user seeing them whilst also forcing the Measure / Arrange processes.
I had the same problem. In my case I only call: Visual.UpdateLayout() before trying to work with it. As said by Jammer, it will automatically force Measure / Arrange processes.
I did it on window. If you have any problem, you probably should set the Visual Height and Width before call UpdateLayout().
Eric
I had the same issue. Solved by ApplyTemplate().
It force to builds visual tree of an Framework element.
I would like to hide several textboxes, a label and a button as soon as a button is clicked... however, for some reason, my code doesn't seem to cause this effect. Nothing appears to happen. I'm using WPF.
Here is my code:
private void doSomething_Click(object sender, RoutedEventArgs e)
{
Name.Visibility = Visibility.Hidden;
}
This code doesn't seem to work.. any ideas?
I believe Visibility.Collapsed is what you need and not Visibility.Hidden.
EDIT: Did you try follow up this code with UpdateLayout() method of parent element/component?
Your code seems to work fine, the "Signing in..." label appears after everything else disappear. I suggest you to just copy all your code from the .xaml.cs file and the .xaml file into a new project, but make sure you don't copy the first line"<Window x:Class="..." because it could generate an error if the class name isn't the same in the new project.
For the xaml code I suggest you not think the same as you design windows forms applications. WPF has the layout system, which re-orientates or re-sizes its elements when re-sizing the window. So you should not specify exact numbers in the margin property as if they where coordinates. Create a grid, create rows or columns for each element and then just set the horizontal or vertical alignment or margins. Think different than the old windows forms way.
I've run your code... and it's working great for me. I've not changed anything (except the variable names) so I guess it's a bug from VS.
As said nikolamm94 try to add this.UpdateLayout(); at the end of connect_Click it might help. I tried and it is still working fine. Or maybe create a new VS projet, it already worked for me a few times.
Sorry my answer is not the most helpful, I wanted to put a comment instead but I don't have enough reputation :/
Please refer: https://msdn.microsoft.com/en-us/library/ms748821(v=vs.85).aspx
Set to Visible: tb1.Visibility = System.Windows.Visibility.Visible;
Set to Hide: tb1.Visibility = System.Windows.Visibility.Hidden;
You can hide a textbox by going to properties->appearance->visibility, then setting it to "hidden"