I've implemented a simple list model and list delegate in QML, and now curious if it feasible to make the underlying list cyclic.
Here is the code snippet:
Common.MarketsListView {
id: markets
anchors.top: logoImage.bottom
anchors.topMargin: 5
cacheBuffer: 20000
NumberAnimation on x {
running: runtime.isActiveWindow
loops: Animation.Infinite
from: 0
to: -300
duration: 20000
}
Currently, the list slowly moves to the left, but as it reaches the end only few last items are shown. So I shall either make the underlying list cyclic, or hard-code the jump to the first list item :(
You can't do this with a ListView, but you may be able to get the bahavior you want using PathView, e.g. https://doc.qt.io/archives/qt-4.7/declarative-ui-components-spinner.html
Related
I'm noticing some unexpected behavior when working with the SwiftUI TextField axis property in iOS 16. The code snippet below shows I have a TextField with a vertical axis set (I expect this should expand the text field to unlimited entry, scrolling down), and I've added a .lineLimit(5, reservesSpace: true) modifier to set the TextField's "box size" to 5 lines, but continue to scroll if I'm beyond 5 lines.
The image below shows the unexpected behavior. Scrolling works as expected until I hit line 10 on an iPhone 14 Pro. Then, even though the TextField box remains the same size, it pushes down any elements below it in the List. You can see the "Completed" Toggle moving down slightly. It's also curious that the "push" happens not when I paste in a line, but when I backspace to type a new number - for example the third image shows the Completed area after I pasted in a new line (the 13th line, but starts saying "Line 10", and when I backspace over the "0" in "10" to write "13", that's when the "push" is triggered (it can be seen in the 4th image). This push will continue until the Views below the TextField are eventually pushed off screen (you can see this happening in the last image). Since I'm in a List, I can, of course, scroll to access the last items, but I hadn't expected the TextField to push items lower, even more so that it starts with Line 10 in a 5 line-limited TextField. Am I misunderstanding these Views and modifiers, or is there a bug in the implementation? Thanks for insight!
List {
Group {
...
Text("Notes:")
.padding(.top)
TextField("Notes", text: $notes, axis: .vertical)
.lineLimit(5, reservesSpace: true)
.textFieldStyle(.roundedBorder)
Toggle("Completed:", isOn: $isCompleted)
.padding(.top)
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
I don't think that this approach will work, because .textLimit() modifier is used only for Text() view and not for TextField() as you are trying to do.
I wonder if someone can help me with something that’s driving me up the wall.
I’m very new to flutter and the dart language. Working on a basic personal project as I progress through a Udemy course.
It’s called ‘Bushy Bingo’ – The below is the UI (set aside the layout issues for now)
What I want is for the order of the animals to shuffle when the user clicks the shuffle button. So you get a randomized game each time.
The animals are all custom widgets I’ve created which sit within a ‘Table’ widget, 4 Table Rows, 4 children a piece to create the 4 x 4 grid.
My thinking is that I need to
Assign a ‘positionNumber’ value as an into to each cell of the
grid
Create an ‘animalIndex’ map containing my 16 animals
Write a for loop function, which creates a tableOrder from
scratch on the following logic..
A - For 16 times...
B - Generate a random number between zero and the length of my animalIndex
C - Take the corresponding entry from my animalIndex and add it as a new entry to my tableOrder list
D - Remove the entry from the animalIndex
Assuming that's reasonable logic, i cannot get it to work with dart. Please see the below screenshot to see the issue
If anyone could let me know where I'm going wrong it would be massively appreciated. Maybe my whole approach is wrong. (I've been wrong before ;))
EDIT: I'm really sorry, I didnt mean to step on any toes. You probably put alot of work into what you have already. Your approach could be used obviously, but its a bit over the top for what you wanted to achieve. That's how I came to my answer. If that is not what you are looking for then I hope someone else can help you with the generation of your numbers etc..
I dont have enough reputation yet to comment, so I'm doing it like this. The best way would be to make an animal class and build a list from there.
import 'package:flutter/material.dart';
class Animal {
String name;
Image animalImage;
Animal({this.name, this.animalImage});
}
Then use that to make a list:
List getAnimals() {
return [
Animal(
name: "duck",
animalImage: Image.network('https://picsum.photos/250?image=9'),
),
Animal(
name: "elephant",
animalImage: Image.network('https://picsum.photos/250?image=9'),
),
];
}
Once you have that you can put that in your listviewBuilder. After they press the button you can make a function that takes that list and shuffles it:
example: shuffle docs
example: other shuffle stuff
This way you can always add or remove animals. With the class you can add or remove extra data. And since it's a list it will have its own index id's so you can order it, shuffle it, do whatever you want.
ListviewBuilder example. There are ways to make a gridviewbuilder so that's covered too. You can style the widget anyway you want. Gridview example
ListView.builder(
itemCount: getAnimals().length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
var _data = getAnimals()[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.red,
child: ListTile(
title: Text(_data.name),
),
),
);
})
struct ContentView: View {
#State private var favoriteColor = 0
var body: some View {
VStack {
Picker(selection: $favoriteColor, label: Text("What is your favorite color?")) {
Text("Red").tag(0)
Text("Green").tag(1)
Text("Blue").tag(2)
}.pickerStyle(SegmentedPickerStyle())
Text("Value: \(favoriteColor)")
}
}
}
You are already nearly there!
First, you make a variable called favoriteColor. You intend to use this variable to get the value from the Picker, aren't you?
Then, you pass that variable to the Picker. Not just as a variable, but as a Binding, with the $ sign in front of it. This will make sure that your variable always stays in sync with the Picker. Briefly said, what Binding does, is that there's actually only one variable, which is shared by your View and the Picker. If you want to know more about this, I believe that there are hundreds of tutorials on this on the internet, so it would not really make sense if I would explain it here yet another time!
So what will happen, is that the Picker updates your variable when a selection is made. But what value will it give your variable for which option?
Well, that's the value you specified in those .tag(...)s. So when the user selects "Red", favoriteColor gets a value of 0, for "Green" it gets 1, for "Blue" it gets 2.
What about updating the UI when the selection changes? Well, SwiftUI manages this automatically -- this is one of the best things of SwiftUI!
But one more thing. When you use the value in a Text like you are doing, you will see something like "Value: 1" at runtime. It would be nice if we could display the name of the color, isn't it?
There's a lot of ways to do this, but one would be to replace Text("Value: \(favoriteColor)") with:
Text("Favorite Color: \(["Red", "Green, "Blue"][favoriteColor])")
What this does, is that it creates an array and takes the value out of it that corresponds with the index of the selected color. So when favoriteColor is 0, the first element of the array is taken , which is "Red".
Hope this is helpful for you!!
I'm trying to create a view with two nested List Views. That means the main view has rows and each row also has rows. Because of a reordering requirement (edit mode) and swipe to delete (inner rows only), I can't just use ForEach-loops with a scroll view.
The problem is the following: the inner rows don't show when I tap "+add set" although debugging shows they are actually added. the reason might be that view of the outer row doesn't adapt its height. I know this because if I only use ForEach and no List, the rows do appear. but then I can't use swipe to delete. this is the code for the inner rows (as List view) :
List {
ForEach(self.exercise.sets) { set in
SetRow(set: set, exercise: self.exercise)
}.onDelete { (offsets) in
self.exercise.sets.remove(atOffsets: offsets)
}
}
each outer row has VStack before this List (for the exercise name and the column titles) and a button below. see the screen shots
seems I found a workaround... The outer list looks like this in code:
List() {
Text("New workout").font(.title)
ForEach(self.workoutModel.exercises) {exercise in
ExerciseWorkoutView(exercise: exercise)
}
}
I simply added the following frame modifier to the ExerciseWorkoutView (which is a VStack with a List view in it:
.frame(height: self.minFrameHeight + self.setRowHeight * CGFloat(self.exercise.sets.count)).animation(.default)
minFrameHeight and setRowHeight are constants I set.
self.exercise is an observed object with a sets array as #Published instance variable. that's why the frame height adapts automatically...
if anyone knows a better solution, thanks for posting. I tried several variations of .fixedSize(...) already but it didn't work.
If I want to change the focus item in the ListView control I do the following:
BOOL setListFocusItem(CListCtrl* pList, int nIndex)
{
return !!pList->SetItemState(nInd, LVIS_FOCUSED, LVIS_FOCUSED);
}
Is this the way you do it?
Because the focus itself changes but there's one issue that this creates. For instance, if the list had 100 items and the focus was on item 1. If I then call my method as such setListFocusItem(99); the focus changes to item 99, but then if I shift-click on item 90, I would expect the list to have items 90 through 99 to be selected. But instead the list selects items 1 through 90. So obviously my setListFocusItem() method does not change the shift-click "first" location. So question is how to make it do it?
Short answer : use the LVM_SETSELECTIONMARK message.
(In MFC-ese, CListCtrl::SetSelectionMark).