If you are here, we will assume:
- You are an iOS Developer
- You like CocoaTouch
- You need to code Android but you don't want to learn it
- You want to replicate your iOS code to Android
- You prefer Kotlin over Java
In Android, Activity is equivalent to UIViewController and it normally looks like:
public class MainActivity extends AppCompatActivity
{
Button button; // Equivalent to iOS UIButton
ListView tableview; //Equivalent to iOS UITableView
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Link XML to variables
this.button = this.findViewById(R.id.button);
this.listView = this.findViewById(R.id.tableview);
//Set action to button
this.button.setOnClickListener(new View.OnclickListener()
{
@Override
public void onClick(View view)
{
...
}
}
}
}
Not bad. But using this library, it becomes:
open class MainActivity: UIViewController() {
@IBOutlet(R.id.button) lateinit var button: UIButton
@IBOutlet(R.id.tableview) lateinit var tableview: UITableView
@IBAction(R.id.button) fun click(sender: UIButton) {
...
}
}
Nice right? But it becomes better. The thing we most hate on Android SDK, it's how you can't alloc the activity to be presented and just pass objects. You need to transfer data via bundle and the SDK will create an activity for you. This starts to be annoying when you need to pass a custom object and you have to implement Parcelable or Serializable. This adds lots of lines of code, because Android copy objects between activities. This is an example of how to transfer a custom objects from one Activity to another in Android:
CustomObject.java
public class CustomObject extends Object implements Parcelable
{
...
public String name;
public CustomObject()
{
name = "";
}
//
// Parcelable Trash code
//
public CustomObject(Parcel in)
{
name = in.readString();
}
@Override public int describeContents()
{
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags)
{
...
dest.writeString(name);
}
public static final Parcelable.Creator<CustomObject> CREATOR = new Parcelable.Creator<CustomObject>()
{
public CustomObject createFromParcel(Parcel in)
{
return new CustomObject(in);
}
public CustomObject[] newArray(int size)
{
return new CustomObject[size];
}
}
}
SenderActivity.java
public void presentReceiverController()
{
CustomObject customObject = new CustomObject(...);
Intent intent = new Intent(this, ReceiverActivity.class);
intent.putParcelableExtra("key_customObject", customObject);
this.startActivity(intent);
}
ReceiverActivity.java
public class ReceiverActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_receiver);
//Get custom Object
Bundle bundle = getIntent().getExtras();
CustomObject customObject = bundle.getParcelable("key_customObject");
}
}
Boring, right? Now, forget about Pacelable, Serializable, Bundle and Intent. Just alloc and pass data:
CustomObject.kt
open class CustomObject: NSObject() {
...
lateinit var name: String
}
SenderController.kt
fun presentReceiverController() {
var customObject = CustomObject(...)
customObject.name = "My name"
var controller = this.storyboard.instantiateViewControllerWithIdentifier(R.layout.receiver) as ReceiverController
controller.customObject = customObject
this.navigationController.pushViewController(controller, true)
}
ReceiverController.kt
open class ReceiverController: UIViewController() {
lateinit var customObject: CustomObject
override fun viewDidLoad() {
super.viewDidLoad()
// Just access object normally
println(this.customObject.name)
}
Sweet, right? Simple as you do in iOS.
This framework is based on a Single Activity Application and each ViewController is represented by fragments using composition.
If you add the method bellow to your controller, you will receive on back notifications. It's the same of receive a button pressed action.
@IBAction(DefaultActions.onBackPressed) fun back(sender: UIButton) {
//TODO
}
If you don't add it, the back button will close you app.
var activity: Activity = UIApplication.sharedApplication().activity()
var context: Context = UIApplication.sharedApplication().context()
We created some structures such as UIViewContorller, UIButton, UITableView, UILabel... that we needed to create the Stark Bank app. But there are a lot of to do yet. iOS have a bunch of other elements that needs to be coded. Maybe We are here looking for contributors, just maybe.
We added an example app that use some structures, you should try it.
6.1 Add to Gradle the last version:
compile 'com.starkbank:cocoatouch:0.0.1'
6.2 - Create file: MainStoryboard.kt
class MainStoryboard: UIStoryboard() {
}
6.3 - Go to AndroidManifest and make it the fist launch Activity
<activity android:name=".MainStoryboard">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
6.4 - Create a XML in res/layout named mainstoryboard.xml. (Copy and paste this code)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container">
</FrameLayout>
6.5 - Create file: AppDelegate.kt
class AppDelegate: UIResponder(), UIApplicationDelegate {
override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<String, String>?): Boolean {
return true
}
override fun applicationWillResignActive(application: UIApplication) {
}
override fun applicationDidEnterBackground(application: UIApplication) {
}
override fun applicationWillEnterForeground(application: UIApplication) {
}
override fun applicationDidBecomeActive(application: UIApplication) {
}
override fun applicationWillTerminate(application: UIApplication) {
}
}
6.6 - Override methods in MainStoryboard, declaring the initial UIViewController id and mapping layout ids with classes
class MainStoryboard: UIStoryboard() {
override fun applicationDelegate(): UIApplicationDelegate {
return AppDelegate()
}
override fun initialViewControllerId(): Int {
return R.layout.mainviewcontroller
}
override fun storyboardId(): Int {
return R.layout.mainstoryboard
}
override fun containerId(): Int {
return R.id.container
}
override fun viewControllerForIdentifier(identifier: Int): UIViewController {
return when (identifier) {
R.layout.mainviewcontroller -> MainViewController()
else -> throw Resources.NotFoundException()
}
}
override fun viewCellForIdentifier(identifier: Int): UITableViewCell {
return when (identifier) {
R.layout.maintableviewcell -> MainTableViewCell()
else -> throw Resources.NotFoundException()
}
}
}
The initialViewControllerId is the id of the first ViewController. Your app will start there. You can set any ViewController you want.
7.1 - New UIViewController
- Create a new kotlin file and make your class inherit UIViewController
- Create a XML file in res/layout
- Go to MainStoryboard
- Find the method viewControllerForIdentifier
- Add the case R.laytout.YOUR_LAYOUT_NAME: return new YOUR_CLASS_NAME()
Example:
File: TutorialViewController.kt
open class TutorialViewController: UIViewController() {
}
File: tutorialviewcontroller.xml
Create it in the folder res->layout. You can edit your canvas and work with pure XML. Yeah you will need to learn how to handle pure XML for Android. (We miss you XCODE interfacebuilder...).
File: MainStoryboard.kt
class MainStoryboard: UIStoryboard() {
...
override fun viewControllerForIdentifier(identifier: Int): UIViewController {
return when (identifier) {
...
R.layout.tutorialviewcontroller -> TutorialViewController()
else -> throw Resources.NotFoundException()
}
}
}
You have your new UIViewController set =)
7.2 - New UITableViewCell
- Create a new kotlin file and make your class inherit UITableViewCell
- Create a XML file in res/layout
- Go to MainStoryboard
- Find the method viewCellForIdentifier
- Add the case R.laytout.YOUR_LAYOUT_NAME: return new YOUR_CLASS_NAME()
Example:
File: TutorialTableViewCell.kt
open class TutorialTableViewCell: UITableViewCell() {
}
File: tutorialtableviewcell.xml
Create it in the folder res->layout. You can edit your canvas and work with pure XML. Yeah you will need to learn how to handle pure XML for Android. (We miss you XCODE interfacebuilder...).
File: MainStoryboard.kt
class MainStoryboard: UIStoryboard() {
...
override fun viewCellForIdentifier(identifier: Int): UITableViewCell {
return when (identifier) {
...
R.layout.tutorialtableviewcell -> TutorialTableViewCell()
else -> throw Resources.NotFoundException()
}
}
}
You have your new TutorialTableViewCell set =)
- Think in one example or structure in iOS you would like to create
- Code the example in iOS
- Stackoverflow how to do the same/similar in Android
- Code it in Android and make it works
- Create classes to simulate iOS but do the Android code under the table
You can contact us here or just send an email to: [email protected]
MIT