In the spirit of sharing and firing off yet another “Let’s work together to build a [fill in the blank]” quest, here’s a simple SplitView implementation using a tableView on the left and a scrollView on the right.
You can have a number of splitView variations obviously but I thought lets start with a simple one. This one assumes you are on an iPad and in landscape orientation so please set your simulator to run in that configuration. In real life a SplitView would need to accommodate the orientation change as well. See attached image for what this is supposed to look like when you run the code.
I also used this demo as an opportunity to put all widgets from tab4 in CL’s WidgetDemo sample code into action. Each time you select a Player on the list the settings values are updated on the right. This is a good way to see how widgets can be updated from values in a file or db etc. Saving back of changed states is not implemented for the purposes of this demo.
I am hoping this can act as a starting point in a new cooperative effort to build a piece of code we can re-use/re-cycle as needed while building our business apps. Thanks for your time in looking at it and improving it. Please post back if you have updates.
Remarks : In the course of building this demo I came across the following bugs / shortcomings. Filing these as separate bug reports with CL and hope these can be addressed in the near future.
- All widgets behave well when inserted into a scrollView except newSegmentedControl. This widget never gets the click/tap event and update its visuals when inside a scrollView. You will see this one when you try to click the newSegmentedControl on the right. Case # 29097 previously reported by Joe528
- obj:setValue() method is not yet implemented for newSegmentedControl() Case # 29143
- Grouped Radio Buttons in a display group should update all buttons when setValue is used on one Case # 29138
- newStepper:setValue does not update newStepper.value Case # 29142
- newSwitch in style = “onOff” has a major bug where the whole switch moved on x-axis left & right when you programmatically change its state using object:setState(). You will see this one when you run the code and select a player on the left. Case # 29144
Happy holidays to all CL Staff and CL Developer friends. Keep well.
local widget = require "widget" -- Set a default theme / Uncomment one of the following to see how this demo -- looks like and works on each theme widget.setTheme( "widget\_theme\_ios7" ) --widget.setTheme( "widget\_theme\_ios" ) --widget.setTheme( "widget\_theme\_android" ) -- Some sample data to populate the tableView on the left - No save to file etc -- implemented for the purpose of this demo local settings = { {caption = "Settings 1", isCategory=true}, {caption = "Player 1", isCategory=false, segmentedValue=2, hSliderVal=30, vSliderVal=10, newStepperVal= 4, newProgressViewVal = .5, checkboxButtonVal = {isOn=false}, onOffSwitchVal = {isOn=true}, radioButton1Val = {isOn=false}}, {caption = "Player 2", isCategory=false, segmentedValue=4, hSliderVal=60, vSliderVal=30, newStepperVal= 40, newProgressViewVal = .1, checkboxButtonVal = {isOn=true}, onOffSwitchVal = {isOn=false}, radioButton1Val = {isOn=true}}, {caption = "Settings 2", isCategory=true}, {caption = "Player 1", isCategory=false, segmentedValue=1, hSliderVal=50, vSliderVal=100, newStepperVal= 34, newProgressViewVal = .2, checkboxButtonVal = {isOn=true}, onOffSwitchVal = {isOn=true}, radioButton1Val = {isOn=true}}, {caption = "Player 2", isCategory=false, segmentedValue=5, hSliderVal=90, vSliderVal=10, newStepperVal= 45, newProgressViewVal = .6, checkboxButtonVal = {isOn=false}, onOffSwitchVal = {isOn=false}, radioButton1Val = {isOn=false}}, {caption = "Settings 3", isCategory=true}, {caption = "Player 1", isCategory=false, segmentedValue=1, hSliderVal=70, vSliderVal=40, newStepperVal= 2, newProgressViewVal = .8, checkboxButtonVal = {isOn=true}, onOffSwitchVal = {isOn=false}, radioButton1Val = {isOn=false}}, {caption = "Player 2", isCategory=false, segmentedValue=3, hSliderVal=20, vSliderVal=70, newStepperVal= 0, newProgressViewVal = .9, checkboxButtonVal = {isOn=false}, onOffSwitchVal = {isOn=true}, radioButton1Val = {isOn=true}} } local statusBarVisible = true -- change this to false if you wish statusBar to be hidden. local statusBarHeight = display.topStatusBarContentHeight if not statusBarVisible then statusBarHeight = 0 display.setStatusBar( display.HiddenStatusBar ) end local titleBarHeight = 44 -- Feel free to change this value to change your TitleBar Height local tabBarHeight = 50 -- Feel free to change this value to change your TabBar Height local splitViewHeight = display.contentHeight - titleBarHeight - tabBarHeight - statusBarHeight local splitLeftWidth = display.contentWidth / 4 -- or you could use a value such as 200 here local titleBarStrokeWidth = 2 local splitRightWidth = display.contentWidth - splitLeftWidth - (titleBarStrokeWidth / 2) local titleBarFillColor = {247/255, 247/255, 247/255} local titleBarStrokeColor = {192/255, 192/255, 196/255} local titleBarLeftLabel = "Players" local titleBarRightLabel = "Settings - Details" local titleBarTextFont = native.systemFont local titleBarTextFontSize = 16 local titleBarLeft = display.newRect(0, statusBarHeight, splitLeftWidth, titleBarHeight) titleBarLeft.anchorX, titleBarLeft.anchorY = 0, 0 titleBarLeft.strokeWidth = titleBarStrokeWidth titleBarLeft:setFillColor(unpack(titleBarFillColor)) titleBarLeft:setStrokeColor(unpack(titleBarStrokeColor)) local titleBarLeftText = display.newText( titleBarLeftLabel, 0, statusBarHeight, titleBarTextFont, titleBarTextFontSize ) titleBarLeftText:setFillColor( 0, 0, 0 ) titleBarLeftText.anchorX = 0.5 titleBarLeftText.anchorY = 0.5 titleBarLeftText.x = splitLeftWidth / 2 titleBarLeftText.y = statusBarHeight + (titleBarHeight / 2) local titleBarRight = display.newRect(splitLeftWidth + (titleBarStrokeWidth/2), statusBarHeight, splitRightWidth, titleBarHeight) titleBarRight.anchorX, titleBarRight.anchorY = 0, 0 titleBarRight.strokeWidth = titleBarStrokeWidth titleBarRight:setFillColor(unpack(titleBarFillColor)) titleBarRight:setStrokeColor(unpack(titleBarStrokeColor)) local titleBarRightText = display.newText( titleBarRightLabel, 0, statusBarHeight, titleBarTextFont, titleBarTextFontSize) titleBarRightText:setFillColor( 0, 0, 0 ) titleBarRightText.anchorX = 0.5 titleBarRightText.anchorY = 0.5 titleBarRightText.x = splitLeftWidth + (splitRightWidth / 2) titleBarRightText.y = statusBarHeight + (titleBarHeight / 2) local splitSeparatorLine = display.newLine( splitLeftWidth, 0, splitLeftWidth, display.contentHeight - tabBarHeight ) --splitSeparatorLine:setFillColor( 0, 0, 0 ) splitSeparatorLine:setStrokeColor(unpack(titleBarStrokeColor)) splitSeparatorLine.strokeWidth = titleBarStrokeWidth local scrollView = widget.newScrollView { left = splitLeftWidth + 1, top = titleBarHeight + statusBarHeight, width = splitRightWidth, height = splitViewHeight, } scrollView.anchorX = 0 scrollView.anchorY = 0 scrollView.x = splitLeftWidth + 1 scrollView.y = titleBarHeight + statusBarHeight + 1 -- Status text box local statusBox = display.newRect( 70, 290, 210, 120 ) statusBox.anchorX = 0 statusBox.anchorY = 0 statusBox:setFillColor( 0, 0, 0 ) statusBox.alpha = 0.4 scrollView:insert( statusBox ) -- Status text local statusText = display.newText( "Interact with a widget to begin!", 80, 300, 200, 0, native.systemFont, 20 ) statusText.anchorX = 0 statusText.anchorY = 0 statusText.x = statusBox.x + 5 statusText.y = statusBox.y + 5 scrollView:insert( statusText ) --------------------------------------------------------------------------------------------- -- widget.newSegmentedControl() --------------------------------------------------------------------------------------------- -- The listener for our segmented control local function segmentedControlListener( event ) local target = event.target print("here") -- Update the status box text statusText.text = "Segmented Control\nSegment Pressed: " .. target.segmentLabel end local segments = { "The", "Corona", "SDK", "Widget", "Demo!" } -- Create a default segmented control (using widget.setTheme) local segmentedControl = widget.newSegmentedControl { left = 10, top = 60, segments = segments, defaultSegment = 3, onPress = segmentedControlListener, } scrollView:insert( segmentedControl ) --------------------------------------------------------------------------------------------- -- widget.newSlider() --------------------------------------------------------------------------------------------- -- The listener for our slider's local function sliderListener( event ) -- Update the status box text statusText.text = event.target.id .. "\nCurrent Percent:\n" .. event.value .. "%" end -- Create a horizontal slider local horizontalSlider = widget.newSlider { left = 150, top = 232, width = 150, id = "Horizontal Slider", listener = sliderListener, } scrollView:insert( horizontalSlider ) -- Create a vertical slider local verticalSlider = widget.newSlider { left = 10, top = 270, height = 150, id = "Vertical Slider", orientation = "vertical", listener = sliderListener, } scrollView:insert( verticalSlider ) --------------------------------------------------------------------------------------------- -- widget.newSpinner() --------------------------------------------------------------------------------------------- -- Create a spinner widget local spinner = widget.newSpinner { left = 274, top = 55, } scrollView:insert( spinner ) -- Start the spinner animating spinner:start() --------------------------------------------------------------------------------------------- -- widget.newStepper() --------------------------------------------------------------------------------------------- -- Create some text for the stepper local currentValue = display.newText( "Value: 00", 165, 105, native.systemFont, 20 ) currentValue.anchorX = 0 currentValue.anchorY = 0 currentValue:setFillColor( 0 ) scrollView:insert( currentValue ) -- The listener for our stepper local function stepperListener( event ) local phase = event.phase -- Update the text to reflect the stepper's current value currentValue.text = "Value: " .. string.format( "%02d", event.value ) end -- Create a stepper local newStepper = widget.newStepper { left = 50, top = 105, initialValue = 0, minimumValue = 0, maximumValue = 50, onPress = stepperListener, } scrollView:insert( newStepper ) print (newStepper.value) --------------------------------------------------------------------------------------------- -- widget.newProgressView() --------------------------------------------------------------------------------------------- local newProgressView = widget.newProgressView { left = 20, top = 240, width = 100, isAnimated = true, } scrollView:insert( newProgressView ) -- Set the progress to 100% newProgressView:setProgress( 1.0 ) --------------------------------------------------------------------------------------------- -- widget.newSwitch() --------------------------------------------------------------------------------------------- -- Create a group for the radio button set local radioGroup = display.newGroup() -- The listener for our radio switch local function radioSwitchListener( event ) local switch = event.target --print( "Switch with ID '"..switch.id.."' is on: "..tostring(switch.isOn) ) -- Update the status box text statusText.text = "Switch with ID '" ..switch.id.. "' \nis on: " end -- Create some text to label the radio button with local radioButtonText = display.newText( "Use?", 40, 150, native.systemFont, 16 ) radioButtonText.anchorX = 0 radioButtonText.anchorY = 0 radioButtonText:setFillColor( 0 ) scrollView:insert( radioButtonText ) -- Create a default radio button (using widget.setTheme) local radioButton1 = widget.newSwitch { left = 25, top = 180, style = "radio", id = "Radio Button 1", initialSwitchState = true, onPress = radioSwitchListener, } radioGroup:insert( radioButton1 ) local radioButton2 = widget.newSwitch { left = 55, top = 180, style = "radio", id = "Radio Button 2", initialSwitchState = false, onPress = radioSwitchListener, } radioGroup:insert( radioButton2 ) scrollView:insert( radioGroup ) -- Create some text to label the checkbox with local checkboxText = display.newText( "Sound?", 110, 150, native.systemFont, 16 ) checkboxText.anchorX = 0 checkboxText.anchorY = 0 checkboxText:setFillColor( 0 ) scrollView:insert( checkboxText ) -- The listener for our checkbox switch local function checkboxSwitchListener( event ) -- Update the status box text statusText.text = "Checkbox Switch\nIs on?: " .. tostring( event.target.isOn ) end -- Create a default checkbox button (using widget.setTheme) local checkboxButton = widget.newSwitch { left = 120, top = 180, style = "checkbox", id = "Checkbox button", onPress = checkboxSwitchListener, } scrollView:insert( checkboxButton ) -- Create some text to label the on/off switch with local switchText = display.newText( "Music?", 200, 150, native.systemFont, 16 ) switchText.anchorX = 0 switchText.anchorY = 0 switchText:setFillColor( 0 ) scrollView:insert( switchText ) -- The listener for our on/off switch local function onOffSwitchListener( event ) -- Update the status box text statusText.text = "On/Off Switch\nIs on?: " .. tostring( event.target.isOn ) end -- Create a default on/off switch (using widget.setTheme) local onOffSwitch = widget.newSwitch { left = 190, top = 180, initialSwitchState = true, onPress = onOffSwitchListener, onRelease = onOffSwitchListener, } scrollView:insert( onOffSwitch ) --[[]]-- local function onRowRender(event) local row = event.row local txt = display.newText(row,settings[row.index].caption, row.contentWidth / 2,row.contentHeight / 2,"HelveticaNeue-Light", 16); txt:setFillColor(0,0,0,1) return true end local function onRowTouch(event) local phase = event.phase local row = event.target if "press" == phase then print( "Pressed row: " .. row.index ) elseif "release" == phase then print( "Tapped and/or Released row: " .. row.index ) -- Update the status box text statusText.text = settings[row.index].caption .. " selected" local segmentNum = settings[row.index].segmentedValue --obj:setValue() method is not yet implemented for segmentedControl so we have to use a workaround --I will leave the next line as commented out code until obj:setValue() method is available for segmentedControl --segmentedControl:setValue(settings[row.index].segmentedValue) if 1 == segmentNum then segmentedControl:setLeftSegmentActive() elseif #segments == segmentNum then segmentedControl:setRightSegmentActive() else segmentedControl:setMiddleSegmentActive( segmentNum ) end segmentedControl.\_segmentNumber = segmentNum; horizontalSlider:setValue(settings[row.index].hSliderVal) verticalSlider:setValue(settings[row.index].vSliderVal) newStepper:setValue(settings[row.index].newStepperVal) currentValue.text = "Value: " .. string.format( "%02d", newStepper.\_view.\_currentValue ) newProgressView:setProgress(settings[row.index].newProgressViewVal ) checkboxButton:setState( settings[row.index].checkboxButtonVal ) onOffSwitch:setState( settings[row.index].onOffSwitchVal ) radioButton1:setState( settings[row.index].radioButton1Val ) radioButton2:setState( {isOn = not radioButton1.isOn} ) end end local tableView = widget.newTableView({ left = 0, top = titleBarHeight + statusBarHeight, width = splitLeftWidth - 1, height = splitViewHeight, shouldHideBackground = true, onRowTouch = onRowTouch, onRowRender = onRowRender, }) for i = 1, #settings do local data = settings[i] tableView:insertRow{ rowHeight = data.isCategory and 40 or 30, isCategory = data.isCategory, rowColor = data.isCategory and { default={ 0.8, 0.8, 0.8, 0.8 } } or { default={ 1, 1, 1 }, over={ 1, 0.5, 0, 0.2 } }, } end