How to change variable when I slide on TabView in swift - arrays

I've following code for my TabView:
struct CardList: View {
var body: some View {
TabView {
ForEach (0..<100 ){ item in
CardViewNew()
}
}
.tabViewStyle(PageTabViewStyle())
.padding(.vertical, 10)
}
}
Every time when I slide to the next view of my TabView the following variable "i" should increased by 1 to show the next element of my array "shuffled_questions".
struct CardViewNew: View {
var body: some View {
Text(shuffled_questions[i])
}
}
Would be nice I've someone can help me :)

Seems like there's two ways to accomplish this. To answer your original question, you could use the selection binding of TabView to get a variable to change when the TabView moves:
#State private var tabSelection = 0
var body: some View {
TabView(selection: $tabSelection) {
ForEach (0..<100 ){ item in
Text("hi")
}
}
.tabViewStyle(PageTabViewStyle())
.padding(.vertical, 10)
Text("\(tabSelection)")
}
However, it seems like in your case it seems like you may just want to pass the index from your ForEach as a parameter to your CardViewNew:
struct ContentView : View {
var body: some View {
TabView {
ForEach (0..<100 ){ item in
CardViewNew(index: item)
}
}
.tabViewStyle(PageTabViewStyle())
.padding(.vertical, 10)
}
}
struct CardViewNew: View {
var index: Int
var body: some View {
Text(shuffled_questions[index])
}
}

Related

Problems with draggable and dropDestination using DataRepresentation in Transferable

I can't get my drag and drop with DataRepresentation to work with Transferable. I'm trying to drag and drop instances of DataSettings which is an NSManagedObject that conforms to NSSecureCoding.
Here's my UTType:
extension UTType {
static var encoderSettings = UTType(exportedAs: "com.simulator.EncoderSettings")
}
Here's my conformance to Transferable:
extension DataSettings: Transferable {
var data: Data? {
try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: true)
}
public static var transferRepresentation: some TransferRepresentation {
/*DataRepresentation(contentType: .commaSeparatedText) { setting in
let data = setting.data
print("DataRepresentation: \(data)")
return data!
} importing: { data in
print("data: \(data)")
return DataSettings()
}*/
DataRepresentation(contentType: .encoderSettings) { setting in
let data = setting.data
print("DataRepresentation: \(data)")
return data!
} importing: { data in
print("data: \(data)")
return DataSettings()
}
// ProxyRepresentation(exporting: \.title)
}
}
Here's a view where I'm testing my drop destination:
struct DropTest: View {
#State var isDropTargeted = false
var body: some View {
Color.pink
.frame(width: 200, height: 200)
.dropDestination(for: EncoderSettings.self) { setting, location in
print("\(setting)")
return true
} isTargeted: {
isDropTargeted = $0
print("Got it!!!")
}
}
}
Here's my Info plist:
The ProxyRepresentation (String) works but I need the actual Data.
The dragging starts (i.e.: I can drag the view that has the .draggable with DataSettings) but I can't drop it on my DropTest view. I can drop it on a view or app that accepts the ProxyRepresentation.
What am I missing?

How to customize the SwiftUI ViewBuilder

There are some posts about SwiftUI Builder like this. So that I can embed my content like:
struct Container<Content>: View where Content: View {
var content: Content
init(#ViewBuilder content: #escaping () -> Content) {
self.content = content()
}
var body: some View {
return content
}
}
struct ContentView: View {
var body: some View {
Container() {
Text("Content 1").tag(0)
Text("Content 2").tag(1)
}
}
}
I'm wondering if I don't pass the ViewBuilder in init. Instead I'd like to do something like:
struct ContentView: View {
var body: some View {
Container().buildContent {
Text("Content 1").tag(0)
Text("Content 2").tag(1)
}
}
}
The reason why I want to do this is because I want to mimic the TabView's tabItem.
You can't have the buildContent function mutate the Container, but you can default to having a Container that just vends an EmptyView, and the use that as a springboard for creating a new Container with your desired content.
You could achieve that sort of API like this:
struct Container<Content>: View where Content: View {
var content: Content
init(#ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
return content
}
}
extension Container where Content == EmptyView {
init() {
self.content = EmptyView()
}
/// Return a new `Container` with the given `Content` builder.
func buildContent<V : View>(#ViewBuilder content: () -> V) -> Container<V> {
Container<V>(content: content)
}
}
struct ContentView: View {
var body: some View {
Container().buildContent {
Text("Content 1").tag(0)
Text("Content 2").tag(1)
}
}
}

CheckBox in ComboBox

I would like to have checkBoxes inside a comboBox, like in this simplified example :
var rawData = [];
for (var i = 0; i < 20; i++) {
rawData.push(i);;
}
var data = new qx.data.Array(rawData);
var list = new qx.ui.form.ComboBox();
list.setWidth(150);
this.getRoot().add(list);
var controller = new qx.data.controller.List(null, list);
var delegate = {
createItem : function() {
return new qx.ui.form.CheckBox();
}
};
controller.setDelegate(delegate);
controller.setModel(data);
It's working but i'm not able to "check" the checkboxes because the combobox is closed when i click on it, so i would like to open/close the combobox only with the button.
How to do it? Thanks in advance.
Some event of the ComboBox is responsible for closing the PopUp (see code on GitHub) before the click can get to an underlying checkbox. If you implement your own ComboBox and overwrite the close method it works.
qx.Class.define("foo.ComboBox", {
extend: qx.ui.form.ComboBox,
members: {
close: function() {
}
}
})
var rawData = [];
for (var i = 0; i < 20; i++) {
rawData.push(i);;
}
var data = new qx.data.Array(rawData);
var list = new foo.ComboBox();
list.setWidth(150);
var controller = new qx.data.controller.List(null, list);
var delegate = {
createItem : function() {
return new qx.ui.form.CheckBox();
}
};
controller.setDelegate(delegate);
controller.setModel(data);
this.getRoot().add(list);
However now you have to think about how you will handle multiple selection of checkboxes and when to close the popup.

Cannot read property 'superclass' of undefined / Object #<Object> has no method 'addCls'

--------------------- Solution ---------------------------
I did a workaround of having to callParent inside my code,
var expandFieldOverride = function(event)
{
//event: collapse, false / expand, true
var fieldset = this;
var arguments = [event];
if(!fieldset.readyToExpand){
Ext.each(profilesPanel.items.items, function(panel, i)
{
if (panel.isProfilePanel)
{
console.log(event);
var field = panel.down('profileform[title=Standard Configuration]').down('fieldset[name='+fieldset.name+']');
field.readyToExpand = true;
field.setExpanded(event);
}
});
}
this.callParent(arguments);
fieldset.readyToExpand = false;
}
-------------------------Initial Problem-------------------------------
I am using ExtJS 4.2.1 and I am trying to override the collapse and expand events of fieldsets. Using collapse and expand didn't work, so I had to directly override setExpanded(). I am trying to achieve the event that when one fieldset is collapsed in a profile panel, so is the other in the other profile panel, and vice versa.
Ext.define('EcoCentral.Configuration.ThermostatProfiles.ProfileOptionsFieldSet',
{
extend: 'Ext.form.FieldSet',
setExpanded: expandFieldOverride,
//expand: expandFieldOverride,
//collapse: collapseFieldOverride,
alias: 'widget.profilefieldset'
});
var expandFieldOverride = function(event)
{
//this.callParent(arguments);
//event: collapse, false / expand, true
var fieldset = this;
var arguments = [event];
Ext.each(profilesPanel.items.items, function(panel, i)
{
if (panel.isProfilePanel)
{
var field = panel.down('profileform[title=Standard Configuration]').down('fieldset[name='+fieldset.name+']');
console.log(field);
//field.callParent(arguments);
field.self.superclass.setExpanded.call(arguments);
}
//this.callParent(arguments);
});
}
If I use 'this.callParent(arguments)' inside the code, I recieve
'Uncaught TypeError: Cannot read property 'superclass' of undefined '
I did some research and tried out this line of code
'field.self.superclass.setExpanded.call(arguments);'
from which I recieve :
'Uncaught TypeError: Object # has no method 'addCls''
Which is a call inside of the setExpanded function in the source.
setExpanded: function(expanded) {
var me = this,
checkboxCmp = me.checkboxCmp,
operation = expanded ? 'expand' : 'collapse';
if (!me.rendered || me.fireEvent('before' + operation, me) !== false) {
expanded = !!expanded;
if (checkboxCmp) {
checkboxCmp.setValue(expanded);
}
if (expanded) {
me.removeCls(me.baseCls + '-collapsed');
} else {
me.addCls(me.baseCls + '-collapsed');
}
me.collapsed = !expanded;
if (expanded) {
delete me.getHierarchyState().collapsed;
} else {
me.getHierarchyState().collapsed = true;
}
if (me.rendered) {
// say explicitly we are not root because when we have a fixed/configured height
// our ownerLayout would say we are root and so would not have it's height
// updated since it's not included in the layout cycle
me.updateLayout({ isRoot: false });
me.fireEvent(operation, me);
}
}
return me;
},
My fieldset is defined by xtype:
You have to use apply. Call is the wrong function. Have a look at this:
What is the difference between call and apply?

in sencha touch in navigation view after back button shows an old value

I am creating an application in sencha touch 2.0
i m using navigation view
i m creating an arrangement of numbers in ascending order math quiz
my problem is when i run the application it works fine for first time but when i click on back button and aging enters on the same view its shows me the old number
strenge thing is that on the button text new numbers appears but when i click on the button and get the text it shows me the old number
my code
sequence_user_answer="";
sequence_answer="";
sequence_number1=this.getRandomNumber(99,10);
sequence_number2=this.getRandomNumber(99,10);
sequence_number3=this.getRandomNumber(99,10);
if(sequence_number1==sequence_number2)
{
while(sequence_number1==sequence_number2)
{
sequence_number2=this.getRandomNumber(99,10);
}
}
else if(sequence_number3==sequence_number1 || sequence_number3==sequence_number1)
{
while(sequence_number3==sequence_number2 || sequence_number3==sequence_number1)
{
sequence_number3= this.getRandomNumber(99,10);
}
}
var sequencenumber1=Ext.getCmp('NumberSequence1');
sequencenumber1.setHtml(sequence_number1);
var sequencenumber2=Ext.getCmp('NumberSequence2');
sequencenumber2.setHtml(sequence_number2);
// alert("two");
var sequencenumber3=Ext.getCmp('NumberSequence3');
sequencenumber3.setHtml(sequence_number3);
var label1=Ext.getCmp('lblsequencenumber1');
label1.setHtml("");
var label2=Ext.getCmp('lblsequencenumber2');
label2.setHtml("");
var label3=Ext.getCmp('lblsequencenumber3');
label3.setHtml("");
if(sequence_number1>sequence_number2)
{
if(sequence_number1>sequence_number3)
{
if(sequence_number2>sequence_number3)
{
sequence_answer=sequence_answer+sequence_number3;
sequence_answer=sequence_answer+sequence_number2;
}
else
{
sequence_answer=sequence_answer+sequence_number2;
sequence_answer=sequence_answer+sequence_number3;
}
sequence_answer=sequence_answer+sequence_number1;
}
else
{
sequence_answer=sequence_answer+sequence_number2;
sequence_answer=sequence_answer+sequence_number1;
sequence_answer=sequence_answer+sequence_number3;
}
}
else
{
if(sequence_number2>sequence_number3)
{
if(sequence_number1>sequence_number3)
{
sequence_answer=sequence_answer+sequence_number3;
sequence_answer=sequence_answer+sequence_number1;
}
else
{
sequence_answer=sequence_answer+sequence_number1;
sequence_answer=sequence_answer+sequence_number3;
}
sequence_answer=sequence_answer+sequence_number2;
}
else
{
sequence_answer=sequence_answer+sequence_number2;
sequence_answer=sequence_answer+sequence_number1;
sequence_answer=sequence_answer+sequence_number3;
}
}
on button tap
getSequenceAnswer:function(selected_button_id)
{
//alert(selected_button_id);
alert(selected_button_id.getHtml()); // here it shows me an old value when i go back and enter again to this view
var ans_audio=Ext.getCmp('answeraudio');
var que_audio=Ext.getCmp('questionaudio');
var result=Ext.getCmp('statuslbl');
if(sequence_count==0)
{
var sequence_label1=Ext.getCmp('lblsequencenumber1');
sequence_label1.setHtml(selected_button_id.getHtml());
sequence_count++;
sequence_user_answer=sequence_user_answer+selected_button_id.getHtml();
}
else if(sequence_count==1)
{
var sequence_label2=Ext.getCmp('lblsequencenumber2');
sequence_label2.setHtml(selected_button_id.getHtml());
sequence_count++;
sequence_user_answer=sequence_user_answer+selected_button_id.getHtml();
}
else if(sequence_count==2)
{
var sequence_label3=Ext.getCmp('lblsequencenumber3');
sequence_label3.setHtml(selected_button_id.getHtml());
sequence_count++;
sequence_user_answer=sequence_user_answer+selected_button_id.getHtml();
if(sequence_answer==sequence_user_answer)
{
que_audio.setUrl("");
ans_audio.setUrl('audio/true.mp3');
ans_audio.play();
this.getTrue(result);
var marks=Ext.getCmp('lblMarks');
sequence_marks = sequence_marks+2;
marks.setHtml(sequence_marks);
var total=Ext.getCmp('lbltotal');
sequence_total_marks= sequence_total_marks+2;
total.setHtml(sequence_total_marks);
}
else
{
que_audio.setUrl("");
ans_audio.setUrl('audio/false.mp3');
ans_audio.play();
this.getFalse(result);
var total=Ext.getCmp('lbltotal');
sequence_total_marks= sequence_total_marks+2;
total.setHtml(sequence_total_marks);
}
}
}
Most likely you can use show listener, which invokes while a container displays. Write your logic to create components dynamically here. Or, as another alternative you can reset your label or other component data inside it.
listeners: {
show: function(list, opts){
// code to reset your comp
}
}

Resources