Difference between revisions of "Android Interface/Native Android GUI"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(15 intermediate revisions by 7 users not shown)
Line 1: Line 1:
 +
{{Platform only|Android|Android|Android}}
 
Go back to [[Android Interface]]
 
Go back to [[Android Interface]]
  
 
__TOC__
 
__TOC__
==Android API Hello World in Pascal==
+
==Android4Pascal==
  
Here is an example Pascal application written for Android. It shows how to create controls, receive callback events and how to use the timer.
+
See the page about [[Android4Pascal]], which is the bindings between Pascal programs and the Android Java APIs.
  
The full directory structure can be download with this svn command:
 
  
  svn co https://p-tools.svn.sourceforge.net/svnroot/p-tools/turbochessclock4android turbochessclock4android
 
  
Here is the Pascal code from this example:
+
==Manifest configuration==
  
<delphi>
+
===Control the program restart===
{
 
  A simple Chess Clock application
 
  
   Author: Felipe Monteiro de Carvalho - 2011
+
By default the program will restart on orientation change, on keyboard change, and in a lot of other cases. This is usually unwanted. To disable program restart on keyboard showing and orientation changed add this to the manifest file:
  License: Public Domain
+
 
}
+
<syntaxhighlight lang=pascal>
 +
   <activity
 +
    ...
 +
    android:configChanges="orientation|keyboardHidden"
 +
</syntaxhighlight>
 +
 
 +
See also:
 +
 
 +
* http://developer.android.com/guide/topics/manifest/activity-element.html#config
 +
 
 +
==Resource files==
 +
 
 +
===Guidelines for the Icons===
 +
 
 +
Read here: http://developer.android.com/guide/practices/ui_guidelines/icon_design.html
 +
 
 +
==Using other APIs==
 +
 
 +
===Using the Timer===
 +
 
 +
The Android API bindings include a handy timer control called TAndroidTimer. It works just like a Runnable, and inside it a Handler class is utilized to run the Runnable in the main GUI thread so that event executed in this timer can call Android APIs.
 +
 
 +
====Timer example====
 +
 
 +
<syntaxhighlight lang=pascal>
 
program turbochessclock4android;
 
program turbochessclock4android;
  
Line 25: Line 46:
 
uses
 
uses
 
   Classes, SysUtils, androidpipescomm, androidview, javalang,
 
   Classes, SysUtils, androidpipescomm, androidview, javalang,
   androidapp, androidtimer, androidutil;
+
   androidapp, androidtimer;//, gles11;
  
 
type
 
type
Line 31: Line 52:
 
   public
 
   public
 
     procedure HandleOnTimer(ASender: TObject);
 
     procedure HandleOnTimer(ASender: TObject);
     procedure buttonStartClickCallback(v: TView);
+
     procedure buttonClickCallback(v: TView);
    procedure buttonMoveClickCallback(v: TView);
 
 
   end;
 
   end;
  
 
var
 
var
   layout: TLinearLayout;
+
   //...
   params: TLayoutParams;
+
   TimerCount: Integer = 0;
  tv, black_label, white_label: TTextView;
 
  scroller: TScrollView;
 
  btn_move, btn_start: TButton;
 
  tp: TTimePicker;
 
  WhiteTimeCount: Integer = 0;
 
  BlackTimeCount: Integer = 0;
 
 
   MyTimer: TAndroidTimer;
 
   MyTimer: TAndroidTimer;
 
   MyEventHandler: TEventHandler;
 
   MyEventHandler: TEventHandler;
  IsWhitePlayerMove: Boolean = True;
 
  
procedure TEventHandler.buttonStartClickCallback(v: TView);
+
procedure TEventHandler.buttonClickCallback(v: TView);
 
begin
 
begin
  black_label.setVisibility(VISIBLE);
 
  white_label.setVisibility(VISIBLE);
 
  btn_move.setVisibility(VISIBLE);
 
  //
 
  WhiteTimeCount := tp.getCurrentHour() * 60 * 60 + tp.getCurrentMinute() * 60;
 
  BlackTimeCount := WhiteTimeCount;
 
  //
 
  MyTimer.removeCallbacks();
 
 
   MyTimer.postDelayed(100);
 
   MyTimer.postDelayed(100);
end;
 
 
procedure TEventHandler.buttonMoveClickCallback(v: TView);
 
begin
 
  IsWhitePlayerMove := not IsWhitePlayerMove;
 
 
end;
 
end;
  
 
procedure TEventHandler.HandleOnTimer(ASender: TObject);
 
procedure TEventHandler.HandleOnTimer(ASender: TObject);
var
 
  lSeconds, lMinutes, lHours: Integer;
 
 
begin
 
begin
//  Inc(TimerCount);
+
  Inc(TimerCount);
   if IsWhitePlayerMove then
+
   tv.setText(Format('Timer event #%d', [TimerCount]));
  begin
 
    lSeconds := WhiteTimeCount mod 60;
 
    lMinutes := (WhiteTimeCount mod (60 * 60)) div 60;
 
    lHours := WhiteTimeCount div (60 * 60);
 
    white_label.setText(Format('White %d:%d:%d', [lHours, lMinutes, lSeconds]));
 
    Dec(WhiteTimeCount);
 
  end
 
  else
 
  begin
 
    lSeconds := BlackTimeCount mod 60;
 
    lMinutes := (BlackTimeCount mod (60 * 60)) div 60;
 
    lHours := BlackTimeCount div (60 * 60);
 
    black_label.setText(Format('White %d:%d:%d', [lHours, lMinutes, lSeconds]));
 
    Dec(BlackTimeCount);
 
  end;
 
  //
 
  MyTimer.removeCallbacks();
 
 
   MyTimer.postDelayed(1000);
 
   MyTimer.postDelayed(1000);
 
end;
 
end;
  
 
begin
 
begin
  // Here add any initialization.
 
  // Any initialization code will be run inside Activity.onCreate,
 
  // so keep it as short as possible!
 
  // It should mostly contain GUI initialization
 
  // User interface
 
 
   MyEventHandler := TEventHandler.Create;
 
   MyEventHandler := TEventHandler.Create;
 +
  // ...
 +
end.
 +
</syntaxhighlight>
  
  // Prepares the UI of the program
+
[[Category:Android]]
  layout := TLinearLayout.Create;
 
  params := TLayoutParams.Create(androidview.FILL_PARENT, androidview.FILL_PARENT);
 
  layout.setLayoutParams(params);
 
  params.Free;
 
  layout.setOrientation(androidview.VERTICAL);
 
 
 
  // Game UI
 
 
 
  black_label := TTextView.Create;
 
  black_label.setText('Black time:');
 
  black_label.setVisibility(GONE);
 
  black_label.setTextSize(COMPLEX_UNIT_PX, 40);
 
  layout.addView(black_label);
 
 
 
  white_label := TTextView.Create;
 
  white_label.setText('White time:');
 
  white_label.setVisibility(GONE);
 
  white_label.setTextSize(COMPLEX_UNIT_PX, 40);
 
  layout.addView(white_label);
 
 
 
  btn_move := TButton.Create;
 
  btn_move.setText('Move finished!');
 
  btn_move.setOnClickListener(@MyEventHandler.buttonMoveClickCallback);
 
  btn_move.setVisibility(GONE);
 
  layout.addView(btn_move);
 
 
 
  // Config UI
 
 
 
  tv := TTextView.Create;
 
  tv.setText('Please select how much to give to the players and press "Start Game":');
 
  layout.addView(tv);
 
 
 
  tp := TTimePicker.Create;
 
  tp.setIs24HourView(True);
 
  tp.setCurrentHour(0);
 
  tp.setCurrentMinute(30);
 
  layout.addView(tp);
 
 
 
  btn_start := TButton.Create;
 
  btn_start.setText('Start game!');
 
  btn_start.setOnClickListener(@MyEventHandler.buttonStartClickCallback);
 
  layout.addView(btn_start);
 
 
 
  // And also allow the user to scroll the UI if it is larger then the screen width
 
  // Scrolling takes place only horizontally
 
 
 
  scroller := TScrollView.Create;
 
  scroller.addView(layout);
 
 
 
  Activity.setContentView(scroller);
 
 
 
  MyTimer := TAndroidTimer.Create;
 
  MyTimer.OnTimer := @MyEventHandler.HandleOnTimer;
 
 
 
  // Now tell Java that the initialization has finished
 
  vAndroidPipesComm.onCreateFinished();
 
  // Here you can add any other initialization,
 
  // specially non-GUI code
 
 
 
  // Now we block our execution waiting for callbacks from Java
 
  vAndroidPipesComm.MessageLoop();
 
end.
 
</delphi>
 

Latest revision as of 08:17, 9 February 2020

Android robot.svg

This article applies to Android only.

See also: Multiplatform Programming Guide

Go back to Android Interface

Android4Pascal

See the page about Android4Pascal, which is the bindings between Pascal programs and the Android Java APIs.


Manifest configuration

Control the program restart

By default the program will restart on orientation change, on keyboard change, and in a lot of other cases. This is usually unwanted. To disable program restart on keyboard showing and orientation changed add this to the manifest file:

  <activity
     ...
     android:configChanges="orientation|keyboardHidden"

See also:

Resource files

Guidelines for the Icons

Read here: http://developer.android.com/guide/practices/ui_guidelines/icon_design.html

Using other APIs

Using the Timer

The Android API bindings include a handy timer control called TAndroidTimer. It works just like a Runnable, and inside it a Handler class is utilized to run the Runnable in the main GUI thread so that event executed in this timer can call Android APIs.

Timer example

program turbochessclock4android;

{$mode objfpc}{$H+}

uses
  Classes, SysUtils, androidpipescomm, androidview, javalang,
  androidapp, androidtimer;//, gles11;

type
  TEventHandler = class
  public
    procedure HandleOnTimer(ASender: TObject);
    procedure buttonClickCallback(v: TView);
  end;

var
  //...
  TimerCount: Integer = 0;
  MyTimer: TAndroidTimer;
  MyEventHandler: TEventHandler;

procedure TEventHandler.buttonClickCallback(v: TView);
begin
  MyTimer.postDelayed(100);
end;

procedure TEventHandler.HandleOnTimer(ASender: TObject);
begin
  Inc(TimerCount);
  tv.setText(Format('Timer event #%d', [TimerCount]));
  MyTimer.postDelayed(1000);
end;

begin
  MyEventHandler := TEventHandler.Create;
  // ...
end.