Make SwiftUI Form wrap contents properly - swift

Swift 5.1
There's a View that contains a Form. When I put that View in any other View, the Form takes up way more space than it needs. For example:
VStack {
Form {
Text("Form")
}
Text("Not form")
Text("Also not form")
}
This results in the entire screen being taken up by the Form (containing only the one Text), save for the two Text squashed way down at the bottom. How do I get Form to shrink-wrap to the size of its contents? .frame(height: 100) (from https://stackoverflow.com/a/59635380/513038) vaguely works, but you have to know how big the contents are, beforehand, which isn't always the case.

Related

Issue with NavigationBarTitle when scrolling List with TextFields inside of it

I have a simple checklist app that uses a SwiftUI List view to display sections with list items inside of it.
Because I want the list items to be editable, each list row has a TextField inside of it with the item name in it. However, if I focus into a text field and scroll the list before hitting the Return Key, the large navigationBarTitle has a bug where it remains frozen in place. For it to work properly, I have to back out of the page and come back.
I'm not seeing any errors, so I'm not sure why this occurring. I have a suspicion using a wrapped UITextField might solve this, but I'm not sure.
I was able to fix my own issue while trying to create a reproducible example.
The bug was the result of a background color I was applying to the parent Group that contained the List. Removing the background color fixed my issue!
struct ChecklistView: View {
var body: some View {
Group {
if empty {
EmptyView()
} else {
ListView()
}
}
.background(Color(.tertiarySystemBackground).edgesIgnoringSafeArea(.all)) // removing this line fixed my issue
.navigationBarTitle("My title")
}
}

Multiple ui elements break WidgetExtension

I'm trying to dynamically build a view using SwiftUI for my widget. However, when multiple views are stacked, the widget no longer works.
I want to loop my Widget over an array of fetched data, like so:
VStack {
ForEach(entry.layers.indices) { index in
let layer = entry.layers[index]
Text(layer)
}
}
but this doesnt work properly when the forEach loops more than about 5 times (it works fine when only looping once or twice!). I contacted Apple Code Level Support about this and they told me this is a 'bug'. See the example project I provided: https://github.com/swifty-on-me/Widget-Example
This is the data I'm trying to render: https://github.com/swifty-on-me/Widget-Example/blob/main/Data/FakeData.swift
I tried something like converting a view to image but the solution doesn't work in Extensions.
So I found this 'workaround' on the Apple Developer Forums but I'm unsure how to implement it:
https://developer.apple.com/forums/thread/665935
Could someone explain or guide me to this workaround? (I'm not so at home with Swift(UI))
I've been messing around with this for ages now and I think I'm going insane about what seems like such a simple task.
See this example (about 28 seconds)
It looks like you are going against how SwiftUI works. You should not have code inside a view declaration. I'm surprised that code even compiled.
Here's where the problem appears to be:
GeometryReader { geo in
ZStack(alignment: .topLeading) {
Color.init("#bf1b49")
VStack {
ForEach(entry.layers.indices) { index in
let layer = entry.layers[index] // < Here
Text(layer)
}
}
}
}
I'm not entirely sure what you are trying to do here, but you don't need two lines of code to do that. You could probably try moving the entry.layers[index] into the Text, because you don't need to store a variable for that. Like this:
GeometryReader { geo in
ZStack(alignment: .topLeading) {
Color.init("#bf1b49")
VStack {
ForEach(entry.layers.indices) { index in
Text(entry.layers[index])
}
}
}
}
Notice how the let layer is gone and the code that makes up layer is now within the text directly. Hopefully this helps!
I too have the same problem. I try to show month view of a calendar in widget (with additional info from my app). I use ForEach and many VStack and HStack. The widget is very unreliable to load. I still try to figure out what causes this issue but I found out one thing… The widget does load successfully when I test it from around 2PM - midnight my local time. (Both when launching app from Xcode and from TestFlight) I know this is weird but it is what happens to me right now.
And yes removing some elements from widget makes widget loads successfully.
Thank you
Boon

How to make TextMeshPro Input Field work in layout?

I'm having odd issues trying to use Unity's Text Mesh Pro Input Field UI element. I don't actually know if the layout is causing it though.
I have a scroll view which uses a vertical layout to organize objects under the content object. Each object in the scroll view has a horizontal layout inside it which fits two input fields next to one another so essentially the Scroll view has two columns of input fields.
However I'm getting odd behavior from the input field. When I start typing it won't show the input until I've entered two characters (i.e. I type '0' and it shows nothing then I type another '0' and it will show '00'). Additionally I have some code that automatically populates the input field with default value, below is an example of how I do this:
gameObject.GetComponent<TMP_InputField>().text = numVal.ToString();
However the values never show up, but I can confirm that they are being populated by checking the inspector window while the game is running. Under the TMP_Input Field component, the 'Text' field shows the correct value but I can't see it in the input box.
I'm getting no errors or warnings.
Is it the scroll view or the layered layouts that are confusing the Input Field's script? Something else? Any advice, help, and questions are appreciated.
EDIT:
I've found that it may have something to do with the way the objects are added to the scroll view. The content of the scroll view (which has the vertical layout) get's objects added to it during run time. This is done through instantiating a prefab.
Instantiate(DoubleInputNodePrefab, contentObject.transform);
This prefab object has the horizontal layout and two children, each an input field. If I add this prefab to content window before I run the game it works fine (expect that none of my intended code works since it relies on modularly adding and removing these objects) but I can give input and it looks fine.
WORK AROUND:
I won't consider this a solution but it is a work around I'm going with for now. Using a 'normal' input field rather than a Text Mesh Pro one doesn't create the same issues and works as intended.

A master/slave panel in Extjs 5 MVC

I'm using Extjs5.1 powered by a MVC oriented code style.
I've got a main view which inherits from Ext.panel.Panel with a border layout.
On the east region, there's a grid with a store containing several records (or "models", I don't really know what terminology I should use here). (the "master grid")
On the center region, there is another view that inherits from a Ext.form.Panel and which is supposed to display the selected item of the grid . (the "slave form")
My goal is to refresh the "slave form" with the selected record of the "master grid".
The only way I found to "communicate" between the grid and the form is to execute a fireEvent('selectRecord', ...) from the main view controller and to listen to him inside the form view controller, but it seems odd as the form view is a child item of the main view.
Is there a more common way to do that?
By corrolary, is it a fine practice to make a view call functions of another view directly or should I make only their respective controllers interact?
What I usually do and I believe is the most common approach for this, is having a selectionchange event listener, that updates your form like this:
listeners : {
selectionchange: function(model, records) {
var rec = records[0];
if (rec) {
formpanel.getForm().loadRecord(rec);
}
}
}
for this to work, the name property of your form fields must match the name of the fields in the grid store model.
There is an example of this here: http://dev.sencha.com/extjs/5.1.0/examples/kitchensink/#form-grid

How to get text of elements in a custom listview?

I have an adroid app where one actrivity cotains Custom listview in which each item or element is implemented as a separate linearlayout textview. I want to get the text of each element.
I'm taking a guess here as your information is lacking a little detail. What you are going to need to do is loop through each element in the listview and then find the text view within the linear layout.
If you look over at the answer I have given over here
you will want a method like:
ListView list = solo.getCurrentListViews().get(0);
for(int i=0; i < list.getAdapter().getCount(); i++){
View view = getViewAtIndex(list, i, getInstrumentation());
//do something with the view here
}
Where the comment is you will want the code that moves you from the top view (linear layout) and gets you to the text view. This will probably involve casting the returned view to a view group and then using getChildAt(x) where x is the correct index (I cannot tell you that as i do not have you application to tell!)
Hope this helps.