Help using Stacks to create this basic example

Hi

I’m struggling to get to grips with stacks. I’ve been trying to style a simple widget all day and I am at the point where I need to ask as I’m getting no further.

Please see attached image. I want to have 3 separate columns, a line break in between each and 2 or 3 rows which are all aligned.

Can anyone help post a basic example like the attached screenshot.

Try this.
Please forgive the brevity of the variable naming. I was typing on mobile.

The idea is to have a main horizontal stack to contain the columns. Inside each column, there is a horizontal stack to fill in the horizontal space. Doing that in all columns will make each the same width.

After that, just fill in the content you need.

Edit: This is how it looks like

const w = new ListWidget()

// main stack
const m = w.addStack()
m.layoutHorizontally()

// function to add column
const addCol = s => {
  // add to parent stack
  const c = s.addStack()
  c.layoutVertically()
  
  // spacer to fill in the width
  const sp = c.addStack()
  sp.layoutHorizontally()
  sp.addSpacer()
  return c
  
}

// add a centered text inside a stack
const ctext = (s, text) => {
  const b = s.addStack()
  b.layoutHorizontally()
  b.addSpacer()
  const t = b.addText(text)
  b.addSpacer()
  return t
}

// add a divider 
// 1px width stack with bgcolor
const div = s => {
  const d = s.addStack()
  d.size = new Size(1, 100)
  d.backgroundColor = Color.lightGray()
}

// layout: left, middle, right
const lf = addCol(m)
div(m)
const md = addCol(m)
div(m)
const rg = addCol(m)

// text titles
ctext(lf,"Current").font = Font.title1()
ctext(lf,"Visitors").font = Font.title1()
ctext(md,"Total").font = Font.title1()
ctext(md,"Visitors").font = Font.title1()
ctext(rg,"Bounce").font = Font.title1()
ctext(rg,"Rate").font = Font.title1()

// space after titles
lf.addSpacer(5)
md.addSpacer(5)
rg.addSpacer(5)

// values
ctext(lf,"4").font = Font.title1()
ctext(md,"8914").font = Font.title1()
ctext(rg,"14%").font = Font.title1()

await w.presentMedium()
Script.setWidget(w)
1 Like

You did that on a mobile, impressive!

Thank you, I understood what I needed to do but couldn’t work out how. You example is perfect, thank you.

1 Like

@supermamon I’ve spent a couple of days breaking down your code and adjusting it so I can learn to create others but I’ve hit an issue I’m hoping you can help with.

First off, Is it possible to create a title area with a background colour as per the image?
image

Secondly, I’ve been trying to add another row of details with another line break. I’m getting there but I can’t quite make it work. Can you take a look at my code help me with the layout. The image attached is a rough idea of what I am trying to do.

@supermamon I forgot to post the code.


const widget = new ListWidget()

// *********************** Stacks ************************ // 

// main stack
const m = widget.addStack()
m.layoutHorizontally()

// function to add column
const addCol = s => {
  // add to parent stack
  const c = s.addStack()
  c.layoutVertically()
  
  // spacer to fill in the width
  const sp = c.addStack()
  sp.layoutHorizontally()
  sp.addSpacer()
  return c
  
}

// function to add column
const addRow = hs => {
  // add to parent stack
  const hss = hs.addStack()
  hss.layoutHorizontally()

  return hss
  
}

// ********************** Styling ********************** // 

// Color
const backgroundColor = new Color('#F3g6B3', 1);

// Align Text in the Center
const centerAlignedText = (s, text) => {
  const b = s.addStack()
  b.layoutHorizontally()
  b.addSpacer()
  const t = b.addText(text)
  b.addSpacer()
  return t
}
// Align Text to the Left
const leftAlignedText = (s, text) => {
  const b = s.addStack()
  b.layoutHorizontally()
  const t = b.addText(text)
  return t
}
// Align Text to the Right
const rightAlignedText = (s, text) => {
  const b = s.addStack()
  b.layoutHorizontally()
  b.addSpacer()
  const t = b.addText(text)
  return t
}

// add a Divider to split the Columns - 1px width stack with bgcolor
const columnDivider = s => {
  const d = s.addStack()
  d.size = new Size(1, 40)
  d.backgroundColor = backgroundColor
}

// Align Text to the Left
const rowDivider = (hs) => {
  const d = hs.addStack()
  d.layoutHorizontally()
  d.addSpacer()
  d.size = new Size(40, 1)
  d.backgroundColor = backgroundColor
  return d
}

// Add Columns
const column1 = addCol(m)
columnDivider(m)
const column2 = addCol(m)
columnDivider(m)
const column3 = addCol(m)

// Add Rows
const row1 = addRow(m)
rowDivider(m)
const row2 = addRow(m)
rowDivider(m)
const row3 = addRow(m)
rowDivider(m)

// Space after titles
column1.addSpacer(15)
column2.addSpacer(15)
column3.addSpacer(15)


// *********************** Text ************************ // 

// Titles
centerAlignedText(column1,"Current Visitors").font = Font.systemFont(10);
centerAlignedText(column2,"Total Visitors").font = Font.systemFont(10);
centerAlignedText(column3,"Bounce Rate").font = Font.systemFont(10);

// Values
centerAlignedText(column1,"4").font = Font.systemFont(24);
centerAlignedText(column2,"8914").font = Font.systemFont(24);
centerAlignedText(column3,"14%").font = Font.systemFont(24);

centerAlignedText(column1,"Current Visitors").font = Font.systemFont(10);
centerAlignedText(column2,"Total Visitors").font = Font.systemFont(10);
centerAlignedText(column3,"Bounce Rate").font = Font.systemFont(10);

// Values
centerAlignedText(column1,"4").font = Font.systemFont(24);
centerAlignedText(column2,"8914").font = Font.systemFont(24);
centerAlignedText(column3,"14%").font = Font.systemFont(24);

// ********************* Complete ********************** // 

// Create widget and complete script
Script.setWidget(widget);
Script.complete();

// Present Widget
await widget.presentMedium()

I’ve spent days on this and I have come to the conclusion it’s not possible at this time.

Hello,

You have to build more row and column levels:
r1 —> Title
r2 —> container
r2c1 —> current visitors and value + separator + other title and value
r2c2 —> separator
r2c3 …

1 Like