Pagination Circles & Pager Dot Nav

Michael Mikkelsen 8 years ago updated by sstava 8 years ago 2
Has anyone made Pagination Circles or Dot Navigation in Wire? This could be used when paginate="yes" on a \pager>, \list> or \tableview> object to display which page you are currently on or even to navigate between pages.

They are great for small cell phone screens because they don't take up a lot of space and let the user quickly visualize the number of pages and which one they are on.

This has been done in the past. It is actually pretty easy to implement.

You simply create your dots as a class (with two different styles: on/off). Then present those dots where it is appropriate in your App.

In order to get them to switch when you change to another "page" you can use a concept called states.

Check out this link on a quick example of how to use states in your project:
I have included an example that I created for an app I built. It dynamically creates the pagination circles and centers them. It also allows you to delete the circles and rebuild them. This is useful when you are changing the query on your datasource (filtering data in an app) and the result count is different.

I attempted to pull this out of a larger app. Hopefully, it is trimmed down to only what you need.

There is a wire file and an XML file used as the datasource.

<datasource name="items" alias="ITEMS" source="" query="//item" providertype="xml" />

<style name="contain-style" width="100%" height="100%" align="center" valign="top" padding-top="25" padding-right="25" padding-left="25"></style>
<style name="btn-style-bottom" width="100%" height="45%" align="center" margin-top="15px" margin-bottom="5" ></style>
<style name="item-style" width="100%" height="100%" borderwidth="5" bordercolor="c0c0c0" cornerradius="8"></style>


<class name="item-selection">
<panel name="item-[param:index]" alias="ITEM-[param:index]" style="item-style" _index="[param:index]" onscrollto="set-item" onscrollaway="from-item">
<text name="item-text-[param:index]" width="100%" height="100%" color="#ff0000" font="helvetica" size="40" alignment="center" text="[param:title]"></text>

<class name="ellipse-inner">
<panel name="[param:container-name]"
height="100%" width="[param:panel-width]" align="center">

<class name="ellipse-item">
<panel name="[param:prename][param:index]"
width="5px" height="5px" valign="center" background="[param:ellipse-color]"
cornerradius="3" margin="13" />



<panel name="canvas" alias="CANVAS" background="303030" width="100%" height="100%" padding="50">

<list name="item-tableview"
alias="ITEMTABLEVIEW" rowheight="150" width="100%" height="45%"
datasource="items" orientation="horizontal" pagination="no"
align="center" valign="center" margin="10" >
<object class="item-selection"
title="[param:name]" />

<panel name="ellipse-container" alias="ELLIPSECONTAINER"
bottomof="ITEMTABLEVIEW" margin="10" align="center"
height="10%" width="100%">

<panel name="delete-ellipses" alias="DELETEELLIPSES"
bottomof="ELLIPSECONTAINER" align="center"
height="75px" width="150px"
borderwidth="2" bordercolor="808080"
<text name="btn-action" alias="BTNACTION" width="100%" height="100%" color="808080" font="helvetica" size="24" alignment="center" valign="center" align="center" text="Delete">




<action name="initialize" oninit="yes">
<assign property="datasource:items.source" value="res://items.xml" />

<action name="load-items">
<assign property="datasource:items.query" value="//item" />
<set target="DELETEELLIPSES" onclickup="delete-ellipses"/>
<assign property="object:BTNACTION.text" value="Delete" />

<action name="items-error" datasource="items" datasourceevent="datasourceerror">
<alert title="Items" message="Failed to load items" />

<action name="items-loaded" datasource="items" datasourceevent="querycomplete">
<assign property="var:curItemNum" value="1" />

<!-- set the variables for removing ellipses -->
<assign property="var:numDeleteCount" value="1" />
<assign property="var:numToDelete" value="[datasource:items.dataSourceResultCount]" />

<!-- determine width of ellipses based on # in datasource -->
<assign property="var:valEllipseWidth"
value="[eval:15*[datasource:items.dataSourceResultCount]]" />

<!-- create the panel that will be centered on the screen and hold the ellipses -->
<create class="ellipse-inner"
container-name="ellipseinner" />

<!-- these values will be used to manage the looping to build the ellipses -->
<assign property="var:numItems" value="[datasource:items.dataSourceResultCount]" />
<assign property="var:numCounter" value="1" />
call the action to build the ellipses. this action calls itself
until the counters match the number of retrieved items from the datasource
<play action="build-ellipses" />

<!-- called when you have scrolled to an item and sets the new item as the current item -->
<action name="set-item">
<assign property="var:curItemNum" value="_index" />
<set target="CHOSEN-ELLIPSE_index" tofront="yes" />

<!-- changes the old item from selected to unseleced with the pagination ellipses -->
<action name="from-item">
<set target="ELLIPSE_index" tofront="yes" />

manage the ellipses that show the number of items and
which item you have selected
<action name="build-ellipses">
this section builds two ellipses if it is the selected item. it
builds two ellipses, in the reverse z-order, if it is an unselected item. The purpose
is to allow the "selected" ellipse to be moved to the next selected
item on the scrollto event
<if lhs="[var:numItems]" operator="gte" rhs="1">
<if lhs="[var:numCounter]" operator="eq" rhs="[var:curItemNum]">
<create class="ellipse-item" target="ELLIPSEINNER" ellipse-color="808080" index="[var:numCounter]" prename="ellipse" move-right="1" />
<create class="ellipse-item" target="ELLIPSEINNER" ellipse-color="ffffff" index="[var:numCounter]" prename="chosen-ellipse" move-right="1" />
<if lhs="[var:numCounter]" operator="ne" rhs="[var:curItemNum]">
<create class="ellipse-item" target="ELLIPSEINNER" ellipse-color="ffffff" index="[var:numCounter]" prename="chosen-ellipse" move-right="1" />
<create class="ellipse-item" target="ELLIPSEINNER" ellipse-color="808080" index="[var:numCounter]" prename="ellipse" move-right="1" />
increment the loop counter by 1 and determine if ellipse building is done
or if we call the build-ellipses action again, in which case we come back
through this whole action again
<assign property="var:numCounter" value="[eval:[var:numCounter]+1]" />
<if lhs="[var:numCounter]" operator="lte" rhs="[var:numItems]">
<play action="build-ellipses" />

increment the loop counter by 1 and determine if ellipse deleting is done
or if we call the delete-ellipses action again
<action name="delete-ellipses">
<if lhs="[var:numDeleteCount]" operator="lte" rhs="[var:numToDelete]">
<delete target="ELLIPSE[var:numDeleteCount]" />
<delete target="CHOSEN-ELLIPSE[var:numDeleteCount]" />
<assign property="var:numDeleteCount" value="[eval:[var:numDeleteCount]+1]" />
<play action="delete-ellipses" />
<set target="DELETEELLIPSES" onclickup="load-items"/>
<assign property="object:BTNACTION.text" value="Rebuild" />


And this is the XML file

<?xml version="1.0" encoding="UTF-8"?>
<!-- <item>
</item> -->

You can uncommonly the other three nodes in the XML to prove that the circles are built dynamically