Home > OP4JS > Smart Mobile Studio, creating a toggle switch

Smart Mobile Studio, creating a toggle switch

February 19, 2013 Leave a comment Go to comments

As work continues from the release candidate to the final release – we are busy polishing the product, adding missing bits and pieces, tweaking the css and making things better.

One of the latest controls to be added is the classical iPhone toggle-box (on-off switch) that has been lacking from Smart Mobile Studio. So it’s about time we got it in there 🙂

Creating controls

Smart Mobile Studio component writing is actually very simple. It’s much easier than under Delphi – but it involves one aspect that to some Spartans can feel.. well, a bit odd. Namely the fact that you have to take CSS into account. In this short article i’ll post the code for the TW3ToggleSwitch control (which will be in the next hotfix or update before we officially hit the 1.1 mark).

The standard controls so far

The standard controls so far

The CSS code for TW3Switchbox is fairly straight-forward:


/* ##########################################################################
   # TW3ToggleSwitch
   ########################################################################## */

.TW3ToggleSwitch {
  background-color: #FFFFFF;
	border:1px solid #AAA;
	border-radius:6px;
	color:#FFF;
	font-weight:700;
	overflow:hidden;
	box-shadow:0 1px 0 #FFF;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
 }

.TW3ToggleOnLabel {
  border-radius: 6px;
  text-align:center;
	background:#007FEA;
	text-shadow:0 -1px 0 #093B5C;
	box-shadow:0 4px 5px -2px rgba(0,0,0,0.3) inset;
}

.TW3ToggleOffLabel {
  border-radius: 6px;
  text-align:center;
	box-shadow:0 4px 5px -2px rgba(0,0,0,0.3) inset;
}

.TW3ToggleKnob {
  cursor: pointer;
  background-color: #FFFFFF;
	border:1px solid #AAA;
	border-radius:4px;
	color:#FFF;
	font-weight:700;
	overflow:hidden;
	box-shadow:0 4px 0 -2px #F1F1F1 inset, 0 2em 2em -2em #AAA inset, 0 0 2px rgba(0,0,0,.5);
}

.TW3ToggleKnob:hover {
	background:#E5E5E5;
}

If you are wondering why i have divided the toggle-box into 4 parts (the box, the knob, the on/off labels) there is a good reason for this. It means that you can alter the look of the control without us getting involved. If you dont like the way the control looks – then you are free to alter the CSS and make your own style. Freedom baby 😉

And then there is the pascal classes:

  TW3ToggleKnob = Class(TW3CustomControl)
  protected
    procedure InitializeObject; override;
  End;

  TW3ToggleOnLabel = Class(TW3Label)
  public
    class function supportAdjustment:Boolean;override;
  end;

  TW3ToggleOffLabel = Class(TW3Label)
  public
    class function supportAdjustment:Boolean;override;
  end;

  TW3ToggleSwitch = Class(TW3CustomControl)
  private
    FKnob:    TW3ToggleKnob;
    FOnText:  TW3ToggleOnLabel;
    FOffText: TW3ToggleOffLabel;
    Procedure HandleTouch(Sender: TObject; Info: TW3TouchData);
    procedure HandleMouseDown(sender:Tobject;button:TMouseButton;
              shiftState:TShiftState;x,y:Integer);
    function  getChecked:Boolean;
    procedure setChecked(Const aValue:Boolean);
  protected
    procedure InitializeObject; override;
    Procedure FinalizeObject;Override;
    procedure Resize; override;
  public
    Property  Checked:Boolean read getChecked write setChecked;
    Procedure Toggle;
  End;

And ofcourse, the implementation. Note: the methods “supportAdjustment” is not in the current RTL. All in all it controls the way the method AdjustToParentBox affects it’s sub controls. You dont really have to care about that at this point, it’s taken care of.


  //###########################################################################
  // TW3ToggleOnLabel
  //###########################################################################

  class function TW3ToggleOnLabel.supportAdjustment:Boolean;
  Begin
    result:=False;
  end;

  //###########################################################################
  // TW3ToggleOffLabel
  //###########################################################################

  class function TW3ToggleOffLabel.supportAdjustment:Boolean;
  Begin
    result:=False;
  end;

  //###########################################################################
  // TW3ToggleKnob
  //###########################################################################

  procedure TW3ToggleKnob.InitializeObject;
  begin
    inherited;
    w3_setStyle(Handle,w3_CSSPrefix('Transition'),'left .12s');
  end;

  //###########################################################################
  // TW3ToggleSwitch
  //###########################################################################

  procedure TW3ToggleSwitch.InitializeObject;
  begin
    inherited;
    (* Create the "ON" label *)
    FOnText:=TW3ToggleOnLabel.Create(self);
    FOnText.Caption:='ON';
    FOnText.AlignText:=taCenter;
    FOnText.Font.Color:=clWhite;

    (* Create the "OFF" label *)
    FOffText:=TW3ToggleOffLabel.Create(self);
    FOffText.Caption:='OFF';
    FOffText.Font.Color:=clBlack;
    FOffText.AlignText:=taCenter;

    (* Create our leaver knob *)
    FKnob:=TW3ToggleKnob.create(self);

    (* setup internal handlers *)
    self.OnMouseDown:=HandleMouseDown;

    self.OnTouchBegin:=HandleTouch;
  end;

  Procedure TW3ToggleSwitch.FinalizeObject;
  Begin
    FKnob.free;
    FOffText.free;
    FOnText.free;
    inherited;
  end;

  function  TW3ToggleSwitch.getChecked:Boolean;
  Begin
    result:=FKnob.left>0;
  end;

  procedure TW3ToggleSwitch.setChecked(Const aValue:Boolean);
  Begin
    if aValue<>getChecked then
    Toggle;
  end;

  Procedure TW3ToggleSwitch.Toggle;
  Begin
    case getChecked of
    True:   FKnob.Left:=0;
    False:  FKnob.Left:=(width div 2)-8;
    end;
    w3_callback(
      procedure ()
      begin
        if assigned(OnChanged) then
        onChanged(self);
      end,
      300);
  end;

  Procedure TW3ToggleSwitch.HandleTouch(Sender: TObject; Info: TW3TouchData);
  Begin
    Toggle;
  end;

  procedure TW3ToggleSwitch.HandleMouseDown(sender:TObject;
            button:TMouseButton;
            shiftState:TShiftState;
            x, y : Integer);
  Begin
    if button=mbLeft then
    Toggle;
  end;

  procedure TW3ToggleSwitch.Resize;
  var
    mTemp:  Integer;
    wd: Integer;
    hd: Integer;
  Begin
    wd:=width;
    hd:=height;

    if (wd>0) and (hd>0) then
    begin
      mTemp:=(wd div 2);
      if (FKnob.width<>mTemp)
      or (FKnob.height<>hd) then
      FKnob.SetSize(mTemp + 8,hd);

      FOnText.SetBounds(0,0,mTemp,hd);
      FOffText.SetBounds(mTemp,0,mTemp,hd);
    end;
  end;

The magic movement

How exactly did we animate the button? It slides fluently from left to right (and visa versa)? The magic is in this simple line:

w3_setStyle(Handle,w3_CSSPrefix('Transition'),'left .12s');

In this line we tell the browser that it should apply a transition on a css value, in this case the “left” property of the knob control. So whenever you alter the left position of that control, it will apply a 0.12s delay in the movement. Voila — that’s how you create a very simple and smooth scrolling effect (doesn’t get much simpler than that).

You could also apply it to any other css value, like width/height or background color. It’s really simple to create hardware accelerated effects with very little effort under Smart Mobile Studio. Once you have some CSS under your belt – it’s a piece of cake.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: