Flex: Spark List's Indeces in View change on Orientation Change - list

I have a spark list with a variable row_height (2 custom itemRenderer: Header 30 px, Contact 60 px) that on the only first orientation change after a scroll, change the indexes in view.
I tried to set Header to be 60 px height, and i had no problems with the orientation change.
I'm not setting the verticalScrollPosition anywhere. Adding an event listener on the viewport's list and watching the verticalScrollPosition, it doesn't change on orientation change.
I really don't know how can i fix that.
EDIT:
This is the code relative to the list:
<fx:Script>
protected function creationCompleteHandler(event:FlexEvent):void
{
addressBookViewModel = ViewModelFactory.getInstance().getAddressBookViewModel();
addressBookViewModel.getUserContacts(onDataReceived);
}
protected function pagedContactsList_initializeHandler(event:FlexEvent):void
{
asyncListView.list = pagedContactsList;
}
private function onDataReceived():void
{
pagedContactsList.length = (BusinessContext.getInstance().getTotalContacts() + BusinessContext.getInstance().getTotalLastNames());
loadPagedData();
}
private function createPendingItemFunctionHandler(index:int, ipe:ItemPendingError):Object
{
if(!addressBookViewModel.pageUp)
{
addressBookViewModel.pageUp = true;
addressBookViewModel.currentPage++;
addressBookViewModel.getMoreUserContacts(onMoreDataRecieved, onMoreDataMissing);
}
return loadingDataHeader;
}
private function onMoreDataRecieved():void
{
loadPagedData();
}
private function loadPagedData():void
{
for(var i:int = 0; i < addressBookViewModel.contacts.length; i++)
{
pagedContactsList.setItemAt(addressBookViewModel.contacts.getItemAt(i), pagedContactsList.lastItemInsertedIndex);
pagedContactsList.lastItemInsertedIndex++;
}
addressBookViewModel.pageUp = false;
}
internal var headerItemRender:ClassFactory = new ClassFactory(HeaderItemRenderer);
internal var contactItemRenderer:ClassFactory = new ClassFactory(ContactItemRenderer);
private function rendererFunction(item:Object):ClassFactory
{
return item.hasOwnProperty("isHeader") ? headerItemRender : contactItemRenderer;
}
</fx:Script>
<fx:Declarations>
<custom:PagedArrayList id="pagedContactsList" initialize="pagedContactsList_initializeHandler(event)"/>
</fx:Declarations>
<s:List id="list" width="100%"
height="100%" itemRendererFunction="rendererFunction" change="list1_changeHandler(event)">
<s:AsyncListView id="asyncListView" createPendingItemFunction="createPendingItemFunctionHandler" />
</s:List>
The curious thing is that before and after the orientation change the list.scroller.viewport.verticalScrollPosition has the same value even if the list has scrolled ~ 40 rows. (40 is the page size).
I have many lists in my app, and every list that has const row_height has no issue, but the 2 with a variable row_height have this problem. Maybe it's caused by the AsyncListView.
EDIT 2:
I removed the AsyncListView, binding directly addressBookViewModel.contacts to the list.dataProvider, removing the pagination and the issue is still there.
EDIT 3:
I think that the only thing to do is to put breakpoints everywhere in the Scroller's class.
EDIT 4:
This issue happens only when scrolling to the bottom of the list.
EDIT 5:
Find the issue!
VerticalLayout.as, in updateDisplayListVirtual(row 1797) there's a call to a method (updateLLV) that set up a LinearLayoutVector using a typicalLayoutElement. This is lazily init with the first itemRenderer added to the dataGroup of the list. In my case it's the HeaderItemRenderer (30px).
After the updateLLV, the startIndex (index of the first visible item) is setted by calling the indexOf on the LinearLayoutVector and passing the verticalScrollPosition. (briefly: verticalScrollPosition / typicalLayoutElement.height)
The problem is that nowhere is taken into consideration the variableRowHeight!

Workaround found! Not so elegant, but it works.
stage.eventListener(StageOrientationEvent.ORIENTATION_CHANGING, yourReorientHandler, false, 1)
Setting the priority is really important, otherwise the updateDisplayListVirtual will be called before your handler.
private function reorientHandler(event:StageOrientationEvent):void
{
var IndecesInView:Vector.<int> = list.dataGroup.getItemIndicesInView();
var firstInView:int = IndecesInView[0];
callLater(
function():void
{
if(!list.layout.getScrollPositionDeltaToElement(firstInView+1)) return;
list.scroller.viewport.verticalScrollPosition += list.layout.getScrollPositionDeltaToElement(firstInView+1).y;
});
}

Related

How to fill state/region/subregion selections when page is opened in edit mode?

In Laravel 8/livewire 2/aplinejs I need to fill state/region/subregion, which are tables in db
and I select subregion from priorly selected regions and select regions from priorly selected, like
public function updatedSelectedState($state_id)
{
$this->regionsSelectionArray = Region::getRegionsSelectionArray($state_id, 'A');
$this->detailsForm['state_id'] = $state_id;
}
public function updatedSelectedRegion($region_id)
{
$this->subregionsSelectionArray = Subregion::getSubregionsSelectionByRegionIdArray($region_id);
$this->selectedSubregion = null;
}
it works ok for data inserting , but when I open editor in “edit” mode and I neeed to fill initvalue I
failed how do it. I remember when I made similar tasks with jquery I have common bool var which I set to true
when jquery was inited. And in onChange event I checked this var .
But how can I do it in livewire ?
Thanks in advance!
Call the below functions in your edit method
Example:
public function updatedSelectedState($state_id)
{
$this->changeSelectedState($state_id);
}
public function updatedSelectedRegion($region_id)
{
$this->changeSelectedRegion($region_id);
}
public function changeSelectedState($state_id){
$this->regionsSelectionArray = Region::getRegionsSelectionArray($state_id, 'A');
$this->detailsForm['state_id'] = $state_id;
}
public function changeSelectedRegion($region_id)
{
$this->subregionsSelectionArray = Subregion::getSubregionsSelectionByRegionIdArray($region_id);
$this->selectedSubregion = null;
}
public function edit(){
// $state_id = provide your state id here
// $region_id = provide your region id here
$this->changeSelectedState($state_id);
$this->changeSelectedRegion($region_id);
}

AUDIOKIT - Why is the AKOscillatorBank RELASE, DECAY, SUSTAIN, and ATTACK being updated long after I change their values?

I have a simple AudioKit app in the works.
I initialize an AKOsicillatorBANK at runtime and allow you to press a button to access a new viewCONTROLLER which has SLIDERS that when changed change the values of the oscillatorBANK properties [releaseDURATION, attackDURATION, decayDURATION, sustainLEVEL].
At the end of the slider's PANGESTURE [state == ended], I call a function that sets the oscillatorBANKS properties to their new values, which are stored in class variables.
I do not know why, but the changes only take effect some time (a few minutes) after the function is called. Does anyone know why this is?
ALSO PLEASE DO NOT COMMENT ON MY CAPITALIZATION STYLE. I PREFER THIS AS IT ALLOWS ME TO EMPHASIZE WHAT I BELIEVE TO BE IS IMPORTANT, WHICH CAN THEN HELP YOU SEE MY TRAIN OF THOUGHTS BETTER.
HERE IS THE CODE. Please note that I ONLY included the code for DECAY within the panGESTURE, because attack, release, and sustain code is all the same design:
// MAIN VIEW CONTROLLER CLASS, GLOBAL SCOPE, INITIALIZED WITH VIEW DID LOAD //
let bank = AKOscillatorBank()
var bankATTACK: Double = 0
var bankDECAY: Double = 0
var bankSUSTAIN: Double = 1
var bankRELEASE: Double = 0
func updateBANKWAVE() {
self.bank.rampDuration = 1
self.bank.attackDuration = self.bankATTACK
self.bank.decayDuration = self.bankDECAY
self.bank.sustainLevel = self.bankSUSTAIN
self.bank.releaseDuration = self.bankRELEASE
print("NEW BANK RAMP [\(self.bank.rampDuration)]")
print("NEW BANK ATTACK [\(self.bank.attackDuration)]")
print("NEW BANK DEC [\(self.bank.decayDuration)]")
print("NEW BANK SUS [\(self.bank.sustainLevel)]")
print("NEW BANK REL [\(self.bank.releaseDuration)]")
}
func prepareforSEGUE() {
if let sliderCONTROLLER = segue.destination as? SLIDERVIEWCONTROLLER {
sliderCONTROLLER.mainCONTROLLER = self
}
}
// SLIDER VIEW CONTROLLER CLASS //
if panGESTURE.state == changed {
// ... update a UILabel to reflect the value to be set ...
decayTEXT = String(format: "%.3f", (self.decayTRANSLATION.truncatingRemainder(dividingBy: 100.0)))
// ... update the MAIN controller variables ...
self.mainCONTROLLER.bankDECAY = Double(self.decayTRANSLATION.truncatingRemainder(dividingBy: 100.0))
// ... protect against values above 10 or below 0 ...
if decayTRANSLATION > 10 { decayVALUE.text = "10.000" ; decayTRANSLATION = 10.01 ; self.mainCONTROLLER.bankDECAY = 10 }
if decayTRANSLATION < 0 { decayVALUE.text = "0.000" ; decayTRANSLATION = -0.01 ; self.mainCONTROLLER.bankDECAY = 0 }
}
if panGESTURE.state == ended {
self.mainCONTROLLER.updateBANKWAVE()
}
By changing the oscillatorBANK.rampDURATION property to 0 instead of 1, I get instantaneous results. However, even though the release is being set to 1, the note can still be heard after 4 or 5 seconds... so...

Xamarin Forms - Get the size of an AbsoluteLayout

I cannot find the way to get the Width and the Height of a Xamarin.Forms.View.
I have this object:
public class SquareLayout : View
{
public static readonly BindableProperty ScalingBaseProperty =
BindableProperty.Create(nameof(ScalingBase), typeof(ScalingBaseType), typeof(SquareLayout), ScalingBaseType.Average,
propertyChanged: OnScalingBasePropertyChanged);
public ScalingBaseType ScalingBase
{
get { return (ScalingBaseType)GetValue(ScalingBaseProperty); }
set { SetValue(ScalingBaseProperty, value); }
}
public enum ScalingBaseType
{
Average,
Height,
Width
}
public static void OnScalingBasePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
SquareLayout sq = ((SquareLayout)bindable);
Debug.WriteLine("|Width = {0}|Height = {1}|", sq.Bounds.Width, sq.Bounds.Height);
switch (sq.ScalingBase)
{
case ScalingBaseType.Average:
double size = (sq.Bounds.Width + sq.Bounds.Height) / 2;
sq.WidthRequest = size;
sq.HeightRequest = size;
break;
case ScalingBaseType.Height:
sq.WidthRequest = sq.Bounds.Height;
break;
case ScalingBaseType.Width:
sq.HeightRequest = sq.Bounds.Width;
break;
}
Debug.WriteLine("|Width = {0}|Height = {1}|", sq.Bounds.Width, sq.Bounds.Height);
}
}
Basically, you declare somewhere this SquareLayout and then, based on an Enum, the layout is resized as a Square.
So, I then have this XAML part
<ContentPage.Content>
<AbsoluteLayout BackgroundColor="White">
...
<AbsoluteLayout x:Name="ToolsLayout" BackgroundColor="Red"
AbsoluteLayout.LayoutBounds="0.5, 0.05, 0.9, 0.075"
AbsoluteLayout.LayoutFlags="All">
<control:SquareLayout BackgroundColor="White" ScalingBase="Height"
AbsoluteLayout.LayoutBounds="0, 0.5, 0.1, 1"
AbsoluteLayout.LayoutFlags="All">
</control:SquareLayout>
<control:SquareLayout BackgroundColor="White" ScalingBase="Height"
AbsoluteLayout.LayoutBounds="1, 0.5, 0.1, 1"
AbsoluteLayout.LayoutFlags="All">
</control:SquareLayout>
</AbsoluteLayout>
...
</AbsoluteLayout>
</ContentPage.Content>
Which would give me a Rectangle with two Square around.. But nothing !
I tried to display the Width and the Height but nothing.. I tried the Bounds as well as you can see in the example, but nothing one more time..
The only values I get are -1
Does someone can help me? Thank in advance !
Xamarin has very less documentation for newbies , took some time to figure this out , basically during design time the the width and height property have a default value of -1 , which indicates auto , there is no way of knowing during design time what the values will be , hence you need to use 'events' to get the width and height property in this case you will use SizeChanged event , when the layout bounds are set during runtime this event will trigger.
In your xaml codebehind use this event to get your widh and height of yourlayout , i have used a lambda function , this can be implemented in many ways i just find this method easy.
yourlayout.SizeChanged+=(sender,e)=>
{
//Add your child objects here and set its values using yourlayout.Height etc
};
Instead of adding your children within this function you can use it to return a value and use that instead.
NOTE:I am not sure if this is the best practice for MVVM or otherwise

Tag-it shows no delete-symbol

I don't know why I don't get the "X" symbol ...
It should be like this:
How can I find the problem? Maybe an CSS-file is blocking an other CSS-file?
JavaScript-Code
$(function() {
var sampleTags = ['Klavier', 'Blockflöte', 'Schlagzeug', 'Gesang', 'Saxophon', 'Klarinette', 'Keyboard', 'Panflöte', 'Mundharmonika', 'Beatboxing', 'Akkordeon', 'Cello', 'Bratsche', 'Tuba', 'Kontrabass', 'E-Gitarre', 'E-Bass', 'Akustikgitarre'];
$('#singleFieldTags').tagit({
availableTags: sampleTags,
singleField: true,
singleFieldNode: $('#mySingleField'),
beforeTagAdded: function(evt, ui) {
var counter = jQuery.inArray(ui.tagLabel, sampleTags);
if(counter != -1) {
return true;
} else {
$('.tagit-new input').val('');
return false;
}
},
});
});
Susanne, encountered the same issue. After a significant amount of time wasted, I determined that the 'x' icon is present, it's just not rendering on the browser level.
var removeTag = $('<a><span class="text-icon">\xd7</span></a>') // \xd7 is an X
This is line 485 of tag-it.js; when you check the rendering of your page, you'll see this is actually present. I changed it to the following in order to confirm that it was present and just needed to be rendered differently.
var removeTag = $('<a><span>x</span></a>') // \xd7 is an X
It can be styled however, from this point. Hope this helps anyone encountering this issue.

Hide UltragridRow that has no visible child rows after applying RowFilter

So, I am setting the DataSource of my BindingSource to the DefaultViewManager of a DataSet that has a DataRelation. I then set my BindingSource as the UltraGrid's DataSource before applying a RowFilter to the the "SalesOrderSublines" DataView.
public void RefreshData()
{
var dataset = DataService.GetMillWorkOrders()
bindingSource1.DataSource = dataset.DefaultViewManager;
ultraGridSequences.SetDataBinding(bindingSource1, "", true, true);
var dvm = bindingSource1.DataSource as DataViewManager;
dvm.DataViewSettings["SalesOrderSublines"].RowFilter = "LINE_NO = 2;
}
public static DataSet GetMillWorkOrders()
{
DataSet ds = OracleHelper.ExecuteDataset(_connectionString, CommandType.StoredProcedure, SQL.GET_WORK_ORDERS);
ds.Tables[0].TableName = "WorkOrders";
ds.Tables[1].TableName = "SalesOrderSublines";
var dr = new DataRelation("WorkOrderSublines", ds.Tables["WorkOrders"].Columns["WORK_ORDER"], ds.Tables["SalesOrderSublines"].Columns["WORK_ORDER"]);
ds.Relations.Add(dr);
return ds;
}
Then, as the UltraGridRows are initializing I want to hide any parent row ("WorkOrders") that has no visible child rows ("WorkOrderSublines") because of my RowFilter.
private void ultraGridSequences_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e)
{
if (e.Row.Band.Key != "WorkOrders") return;
e.Row.Hidden = e.Row.ChildBands["WorkOrderSublines"].Rows.VisibleRowCount == 0;
}
Although the RowFilter does work properly on the rows in the "WorkOrderSublines" band the VisibleRowCount of the band is still greater than zero and so the parent row is never hidden. My guess is that I want to look for something other than the VisibleRowCount of the ChildBand to determine if the top-level row should be hidden, but I'm stuck. Any help would be greatly appreciated. Thanks ahead of time.
Instead of relying on VisibleRowCount you could simply compare the count of child row filtered vs total count.
void ultraGridSequences_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e)
{
if (e.Row.Band.Key != "WorkOrders") return;
var sublinesBand = e.Row.ChildBands["WorkOrderSublines"]
e.Row.Hidden = sublinesBand.Rows.Count(row => row.IsFilteredOut) ==
sublinesBand.Rows.Count();
}
Should be fine performance-wise so long as we're not talking huge amounts of records?
Using the Filtering within the Grid may be an option rather than using the filtering in the DataSource. The following resources have more details on implementing this:
http://forums.infragistics.com/forums/t/51892.aspx
http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.aspx?ArticleID=7703