Is this really how the scrollView is supposed to work?

The reason it’s not included is a resource issue as well as a divergence issue.  When we did the tutorial for widget.newTextField() a few months ago, it was very iOS like. It would add a lot of complexity to skin it for Android as well.  We are a small company with limited engineering resources.  There is only so much bandwidth.

So we did what we thought was the next best thing, we wrote a tutorial to show you how to make your own widget.newTextField() that was almost drop-in ready code.  I have a file called widget-extras.lua that I put these in and build up my library of my own widgets add ons.

I probably should finish cleaning it up after this discovery and drop it in the community code for people to have access too.  But here is the current version:

function widget.newTextField(options)     local customOptions = options or {}     local opt = {}     opt.left = customOptions.left or 0     opt.top = customOptions.top or 0     opt.x = customOptions.x or 0     opt.y = customOptions.y or 0     opt.width = customOptions.width or (display.contentWidth \* 0.75)     opt.height = customOptions.height or 20     opt.id = customOptions.id     opt.listener = customOptions.listener or nil     opt.text = customOptions.text or ""     opt.inputType = customOptions.inputType or "default"     opt.isSecure = customOptions.isSecure or false     opt.font = customOptions.font or native.systemFont     opt.fontSize = customOptions.fontSize or opt.height \* 0.67     opt.fontColor = customOptions.fontColor or { 0.25, 0.25, 0.25 }     opt.placeholder = customOptions.placeholder or nil     opt.label = customOptions.label or ""     opt.labelWidth = customOptions.labelWidth or opt.width \* 0.10     opt.labelFont = customOptions.labelFont or native.systemFontBold     opt.labelFontSize = customOptions.labelFontSize or opt.fontSize     opt.labelFontColor = customOptions.labelFontColor or { 0, 0, 0 }     -- Vector options     opt.strokeWidth = customOptions.strokeWidth or 2     opt.cornerRadius = customOptions.cornerRadius or opt.height \* 0.33 or 10     opt.strokeColor = customOptions.strokeColor or {0, 0, 0}     opt.backgroundColor = customOptions.backgroundColor or { 1, 1, 1 }     local field = display.newGroup()     local deviceScale = (display.pixelWidth / display.contentWidth) \* 0.5          local bgWidth = opt.width     local background = display.newRoundedRect( 0, 0, bgWidth, opt.height, opt.cornerRadius )     background:setFillColor(unpack(opt.backgroundColor))     background.strokeWidth = opt.strokeWidth     background.stroke = opt.strokeColor     field:insert(background)     if opt.left then         field.x = opt.left + opt.width \* 0.5     elseif opt.left then         field.x = opt.x     end     if opt.top then         field.y = opt.top + opt.height \* 0.5     elseif opt.top then         field.y = opt.y     end     --     -- Support adding a label.     -- iOS 6 and earlier and Android draw the Label above the field.     -- iOS 7 draws it in the field.     local labelParameters = {         x = 0,         y = 0,         text = opt.label,         width = opt.labelWidth,         height = 0,         font = opt.labelFont,         fontSize = opt.labelFontSize,         align = "left"     }     local fieldLabel = display.newText(labelParameters)     fieldLabel:setFillColor(unpack(opt.labelFontColor))     fieldLabel.x = background.x - bgWidth / 2 + opt.cornerRadius + opt.labelWidth \* 0.5     fieldLabel.y = background.y     if not widget.isSeven() then         fieldLabel.y = background.y + opt.height + 5     end     field:insert(fieldLabel)     -- create the native.newTextField to handle the input     local tHeight = opt.height - opt.strokeWidth \* 2 - 4     if "Android" == system.getInfo("platformName") then         --         -- Older Android devices have extra "chrome" that needs to be compesnated for.         --         tHeight = tHeight + 10     end     local labelPadding = 0     if widget.isSeven() then         labelPadding = opt.labelWidth     end     field.textField = native.newTextField(0, 0, opt.width - opt.cornerRadius - labelPadding, tHeight )     field.textField.x = 0 + labelPadding     field.textField.y = 0 -- tHeight / 2     field.textField.anchorX = 0.5     field.textField.hasBackground = false     field.textField.inputType = opt.inputType     field.textField.text = opt.text     field.textField.isSecure = opt.isSecure     print(field.x, field.y, field.textField.x, field.textField.y)     print(opt.listener, type(opt.listener))     if opt.listener and type(opt.listener) == "function" then         field.textField.\_listener = opt.listener     end     field.textField.placeholder = opt.placeholder     field:insert(field.textField)     -- Function to listen for textbox events     function field.textField:\_inputListener( event )         local phase = event.phase                  if "began" == phase then             -- make sure we are in a display group             -- the trick is our master object is a group, so we need to make sure our             -- grandparent isn't the stage             if display.getCurrentStage() ~= self.parent.parent then                 -- make a guess at the keyboard height.                   local kbHeight = 0.5 \* display.contentHeight                 local fieldLoc = 0.25 \* display.contentHeight                 -- scroll into view                 if self.y \> kbHeight then                     self.yOrig = self.y                     transition.to(self.parent.parent, {time=500, y = fieldLoc})                 end             end         elseif "submitted" == phase or "ended" == phase then             -- Hide keyboard             if self.yOrig ~= self.y then -- we have been scrolled                 transition.to(self.parent.parent, {time=500, y = self.yOrig})             end         end                  -- If there is a listener defined, execute it         if self.\_listener then             self.\_listener( event )         end     end          field.textField.userInput = field.textField.\_inputListener     field.textField:addEventListener( "userInput" )     print(opt.font, opt.fontSize, deviceScale)     field.textField.font = native.newFont( opt.font, opt.fontSize \* deviceScale )     field.textField.size = opt.fontSize \* deviceScale     function field.finalize( event )         Runtime:removeEventListener( "enterFrame", syncFields )         field.textField:removeSelf()         field.textField = nil     end     field:addEventListener( "finalize" )     return field end  

And to invoke it:

    addressField = widget.newTextField({         width = display.contentWidth,         height = 30,         cornerRadius = 6,         strokeWidth = 0,         text = "",         fontSize = 14,         placeholder = "Address",         font = "HelveticaNeue-Light",         labelFont = "HelveticaNeue",         labelFontSize = 14,         labelWidth = 60,         listener = textFieldHandler,         label = "Address"     })     -- Hide the native part of this until we need to show it on the screen.     addressField.x = display.contentCenterX     addressField.y = navBar.height + 15     sceneGroup:insert(addressField)

I’ve been experiencing the exact same flicking behavior on my scrollviews as shown in your video, and I’ve been trying to fix it in *my* code. Now, it would seem, the problem may be in the underlying scrollview widget itself.

I’ve looked at the code for the scrollview widget on github, but it’s not something I could easily jump in and make a change to. It would require a little time to go through it and really figure it out in order to do things in the best way.

So I, too, would love to see the scrollview get some more love.

One more thing:

The scroll capabilities as they are at the moment fullfill their purpose

It’s possible that people aren’t complaining much about the scrollview flicking behavior because, like me, they assumed the scrollview was working properly, and that the poor flicking behavior was actually caused by something they were doing wrong in their own code.

Dave

Well, according to the Corona staff it already works correctly or is “fulfilling its purpose”. With that kind of attitude I wouldn’t be too optimistic regarding any fix for this.

As I wrote above. If an idiot like me can make some modifications that makes the scrolling look as it should in such a short time , it’s obviously not the means but the will that is the problem with Corona.

It’s the same thing with the textField “widget”. 

What do you mean by textField “widget”?   Are you referring to native.newTextField() or something else?

Yes, I mean native.newTextField(). The problem, of course, is that it is NOT a widget, which leads to third party solutions like widget.newEditField from Widgets Town.

Two things make newTextField() almost unusable:

  • Since it’s native it doesn’t follow the usual rules/guidelines as other screen elements making things like scenes/transitions a nightmare

  • It’s not working in the Android emulator. I’m not talking just about the fact that you cannot enter text into it, but the fact that it’s replaced by a gray rectangle that will forever be visible above all other stuff in the emulator until you reset the app.

Have you considered how many hours are spent among your customers trying to get around this limitation? 

I do not use Corona as a professional. I only (well, mostly) do it on my spare time. I make my living working for a company making Windows programs. When we consider a new feature (or bug fix) we always think:

A )  How many customer will be affected

B )  How much time will each customer save

If A x B is large enough, the feature should be considered.

I have no idea how many paying customers you have and how many of them are struggling with newTextField(), but I have a suspicion that it’s a LOT of us. 

I have 2 questions that I cannot get out of my mind:

  1. If it it’s so hard (for you) to develop a textEdit widget for paying customers, how can Widgets Town manage to make it for free?

  2. If it isn’t that hard, why haven’t you done it?

I don’t get it.

There! Now I’ve gotten it out of my system! Thanks!

If anything, you can expect less going forward. Walter, in another thread openly indicated that the widget library is not something that will be supported and improved forever… 

Hey @runewinse.  As I develop each day more business apps, I can understand your deception and I would like to say that you are not alone seeing these bugs.

@ksan even did a good job by proactively creating a spreadsheet to concentrate all widget problems (since Corona doesn’t have a open bug tracker as other SDK have).

I just think that more experienced Corona devs are getting tired of complaining, so you as a new developer may think that the others are fine with what we have today.

The bottom line is: Corona is a great tool but as every tool it also has its flaws. Unfortunately business apps are not a priority and so we see a lot of these issues that we wouldn’t expect see due to their nature (some very basic and, as you said, not difficult to solve). Since Corona has a small team and have their own priorities, I wouldn’t wait for them to solve anything that is not related to the core.

What we, as developers, could do is to get together and solve the problem ourselves. I am open to discuss that possibility (I can create a specific topic about that). Let me your thoughts.

Disappointing, but not surprising… This trend has been going on for a while.

I don’t think I’m prepared to use much more money on Corona at this stage. 

Yep, more than once I have suggested that they remove the bragging about Corona being a tool for creating business apps as it’s obviously not. For simple 2D games it’s a great tool.

My view is that this is Coronas responsibility.

This is like buying a new car without the door handle on the drivers side. Yes, it’s possible to get around the problem by entering through the passenger side door. Or somehow create a makeshift door handle yourself. But would you accept such a thing?

Good analogy but IMHO the situation is actually worse. its like buying a car with ‘pretend’ door handles that only work sometimes and not in the way you would expect door handles to work. To add to the insult, the manufacturer says “here… take the maintenance manual and tools needed, go fix your door handles yourself”… 

I fully agree with you. I PAID for a product that was advertised as suitable for developing business apps at X10 faster rate as compared to native development. I paid for those darn door handles. 

The problem is not just about widgets and text entry etc either. Look at the shortcomings of mapViews and webViews for instance. You can’t even embed a button into your mapView bubbles. 

Finally, for me, perhaps the biggest issue is the lack of consistency of API between IOS & Android. If the promise of “Write once, deploy everywhere” is not going to prove to be the case then what is the point of using a cross platform SDK such as Corona? 

Unfortunately, for me, the experience has been far from “write once, deploy everywhere”… I summarize my Corona SDK experience as “write once, debug everywhere”… I may still use it for the occasional game idea but I have made the decision not to use Corona SDK for anything beyond that. 

Re: native.newTextField().   Corona’s graphics engine is in OpenGL.  That lives in a canvas behind any native.* object.  Corona SDK is built around OpenGL and that will likely not change in the future.  You will not be able to put Corona display objects on top of native.* objects. 

But there is good news.  You can insert native.* objects into display groups and any moving around of the display group, changing the group’s alpha property should now work.  I’ve been monkeying around with the Business App Sample and I’ve taken the widget.newTextField() code that we put into a tutorial, removed all the syncing code and inserted the native.newTextField into the display group for the widget.newTextField().  I moved both it and the mapView into the scene:create() function to allow Composer to transition them on and off screen and manage them accordingly.  This all seems to work nicely.  I had both crossFade and slideLeft transitions working on the scene.

Yes, we all know that by now, but the problem isn’t that the native.newTextField() is working the way it is. The problem is that there isn’t a (built-in) widget.* version of it.

I’m not 100% sure what you have done here, but I’m very happy that something is being done  :slight_smile:

For us complete morons it’s not easy to understand why something like widget.newTextField() isn’t included in the widget library in the first place. Hopefully you’ll soon add it so that the life of your customers gets e bit easier! Thanks in advance!

The reason it’s not included is a resource issue as well as a divergence issue.  When we did the tutorial for widget.newTextField() a few months ago, it was very iOS like. It would add a lot of complexity to skin it for Android as well.  We are a small company with limited engineering resources.  There is only so much bandwidth.

So we did what we thought was the next best thing, we wrote a tutorial to show you how to make your own widget.newTextField() that was almost drop-in ready code.  I have a file called widget-extras.lua that I put these in and build up my library of my own widgets add ons.

I probably should finish cleaning it up after this discovery and drop it in the community code for people to have access too.  But here is the current version:

function widget.newTextField(options)     local customOptions = options or {}     local opt = {}     opt.left = customOptions.left or 0     opt.top = customOptions.top or 0     opt.x = customOptions.x or 0     opt.y = customOptions.y or 0     opt.width = customOptions.width or (display.contentWidth \* 0.75)     opt.height = customOptions.height or 20     opt.id = customOptions.id     opt.listener = customOptions.listener or nil     opt.text = customOptions.text or ""     opt.inputType = customOptions.inputType or "default"     opt.isSecure = customOptions.isSecure or false     opt.font = customOptions.font or native.systemFont     opt.fontSize = customOptions.fontSize or opt.height \* 0.67     opt.fontColor = customOptions.fontColor or { 0.25, 0.25, 0.25 }     opt.placeholder = customOptions.placeholder or nil     opt.label = customOptions.label or ""     opt.labelWidth = customOptions.labelWidth or opt.width \* 0.10     opt.labelFont = customOptions.labelFont or native.systemFontBold     opt.labelFontSize = customOptions.labelFontSize or opt.fontSize     opt.labelFontColor = customOptions.labelFontColor or { 0, 0, 0 }     -- Vector options     opt.strokeWidth = customOptions.strokeWidth or 2     opt.cornerRadius = customOptions.cornerRadius or opt.height \* 0.33 or 10     opt.strokeColor = customOptions.strokeColor or {0, 0, 0}     opt.backgroundColor = customOptions.backgroundColor or { 1, 1, 1 }     local field = display.newGroup()     local deviceScale = (display.pixelWidth / display.contentWidth) \* 0.5          local bgWidth = opt.width     local background = display.newRoundedRect( 0, 0, bgWidth, opt.height, opt.cornerRadius )     background:setFillColor(unpack(opt.backgroundColor))     background.strokeWidth = opt.strokeWidth     background.stroke = opt.strokeColor     field:insert(background)     if opt.left then         field.x = opt.left + opt.width \* 0.5     elseif opt.left then         field.x = opt.x     end     if opt.top then         field.y = opt.top + opt.height \* 0.5     elseif opt.top then         field.y = opt.y     end     --     -- Support adding a label.     -- iOS 6 and earlier and Android draw the Label above the field.     -- iOS 7 draws it in the field.     local labelParameters = {         x = 0,         y = 0,         text = opt.label,         width = opt.labelWidth,         height = 0,         font = opt.labelFont,         fontSize = opt.labelFontSize,         align = "left"     }     local fieldLabel = display.newText(labelParameters)     fieldLabel:setFillColor(unpack(opt.labelFontColor))     fieldLabel.x = background.x - bgWidth / 2 + opt.cornerRadius + opt.labelWidth \* 0.5     fieldLabel.y = background.y     if not widget.isSeven() then         fieldLabel.y = background.y + opt.height + 5     end     field:insert(fieldLabel)     -- create the native.newTextField to handle the input     local tHeight = opt.height - opt.strokeWidth \* 2 - 4     if "Android" == system.getInfo("platformName") then         --         -- Older Android devices have extra "chrome" that needs to be compesnated for.         --         tHeight = tHeight + 10     end     local labelPadding = 0     if widget.isSeven() then         labelPadding = opt.labelWidth     end     field.textField = native.newTextField(0, 0, opt.width - opt.cornerRadius - labelPadding, tHeight )     field.textField.x = 0 + labelPadding     field.textField.y = 0 -- tHeight / 2     field.textField.anchorX = 0.5     field.textField.hasBackground = false     field.textField.inputType = opt.inputType     field.textField.text = opt.text     field.textField.isSecure = opt.isSecure     print(field.x, field.y, field.textField.x, field.textField.y)     print(opt.listener, type(opt.listener))     if opt.listener and type(opt.listener) == "function" then         field.textField.\_listener = opt.listener     end     field.textField.placeholder = opt.placeholder     field:insert(field.textField)     -- Function to listen for textbox events     function field.textField:\_inputListener( event )         local phase = event.phase                  if "began" == phase then             -- make sure we are in a display group             -- the trick is our master object is a group, so we need to make sure our             -- grandparent isn't the stage             if display.getCurrentStage() ~= self.parent.parent then                 -- make a guess at the keyboard height.                   local kbHeight = 0.5 \* display.contentHeight                 local fieldLoc = 0.25 \* display.contentHeight                 -- scroll into view                 if self.y \> kbHeight then                     self.yOrig = self.y                     transition.to(self.parent.parent, {time=500, y = fieldLoc})                 end             end         elseif "submitted" == phase or "ended" == phase then             -- Hide keyboard             if self.yOrig ~= self.y then -- we have been scrolled                 transition.to(self.parent.parent, {time=500, y = self.yOrig})             end         end                  -- If there is a listener defined, execute it         if self.\_listener then             self.\_listener( event )         end     end          field.textField.userInput = field.textField.\_inputListener     field.textField:addEventListener( "userInput" )     print(opt.font, opt.fontSize, deviceScale)     field.textField.font = native.newFont( opt.font, opt.fontSize \* deviceScale )     field.textField.size = opt.fontSize \* deviceScale     function field.finalize( event )         Runtime:removeEventListener( "enterFrame", syncFields )         field.textField:removeSelf()         field.textField = nil     end     field:addEventListener( "finalize" )     return field end  

And to invoke it:

    addressField = widget.newTextField({         width = display.contentWidth,         height = 30,         cornerRadius = 6,         strokeWidth = 0,         text = "",         fontSize = 14,         placeholder = "Address",         font = "HelveticaNeue-Light",         labelFont = "HelveticaNeue",         labelFontSize = 14,         labelWidth = 60,         listener = textFieldHandler,         label = "Address"     })     -- Hide the native part of this until we need to show it on the screen.     addressField.x = display.contentCenterX     addressField.y = navBar.height + 15     sceneGroup:insert(addressField)

I’ve just read through this thread started over a year ago because I’m finding the behaviour of the scrollview widget very disappointing. It’s so sluggish and choppy on flicks that subtle touch gestures that I thought for ages it was a memory issue on my devices, but it can’t be that.
I would like to know if there have been any developments over the past year since this thread was started that have made the scrollview gestures better, or whether I should abandon corona’s widgets to just use bespoke code such as runewinse’s solution?

First off, I’m a big fan of Corona SDK. I think they’ve made a lot of things easy for us, and I have a couple of apps that I don’t think I could have completed in a reasonable amount of time without it.

However, the widgets have always left a bit to be desired. I think we’ve stopped using all Corona widgets except for a heavily modified version of the scrollview.

We got tired of having new widget-related bugs every time we would get a new daily build, so we finally downloaded the widgets from github and use our local version.  This has worked better for us because we don’t pick up any mysterious new bugs caused by widget bug fixes. This also allows us to modify the widgets to meet our specific needs better.

And yes, our scrollview still jerks a bit when scrolling. We haven’t been able to fix that either.

Dave

dave.haynes, I also don’t use the widget library for any of the UI in my apps with the exception of the scrollview for the same reasons. If your local version of scrollview is in any way even a bit better than the corona widget library version, would you be up for sharing it? I’d greatly appreciate it.

julius, it’s now become very specific to how we’re using it and not really designed to be as portable/reusable as it should be. Part of it was just trying to fix things early on in the app’s development when we were still just “adding on” to the existing scrollview. Another part of it was that we were doing that when we didn’t really know what the heck we were doing in Lua. :slight_smile:  If we could start over, knowing what we know now, it would be much different.

Dave

The scrollView has a bunch of moving parts. Some people want scroll bars, some don’t. Some want it to scroll fast at times and slow at others. But at the end of the day, it’s a group with a touch handler on it. If you don’t need all the bells and whistles you can make you’re own.  If you want to improve it, download the source from http://github.com/coronalabs and take a crack at it. It’s pure Lua.

Rob

I’ve just read through this thread started over a year ago because I’m finding the behaviour of the scrollview widget very disappointing. It’s so sluggish and choppy on flicks that subtle touch gestures that I thought for ages it was a memory issue on my devices, but it can’t be that.
I would like to know if there have been any developments over the past year since this thread was started that have made the scrollview gestures better, or whether I should abandon corona’s widgets to just use bespoke code such as runewinse’s solution?

First off, I’m a big fan of Corona SDK. I think they’ve made a lot of things easy for us, and I have a couple of apps that I don’t think I could have completed in a reasonable amount of time without it.

However, the widgets have always left a bit to be desired. I think we’ve stopped using all Corona widgets except for a heavily modified version of the scrollview.

We got tired of having new widget-related bugs every time we would get a new daily build, so we finally downloaded the widgets from github and use our local version.  This has worked better for us because we don’t pick up any mysterious new bugs caused by widget bug fixes. This also allows us to modify the widgets to meet our specific needs better.

And yes, our scrollview still jerks a bit when scrolling. We haven’t been able to fix that either.

Dave