How to Use Joda Time in Eclipse?

Joda Time is another very useful library for your Android application development. It provides a quality library of classes to replace the Java JDK Date and Time classes.

This post is generally about how to import a library in eclipse for Android development, we just choose Joda Time library as a good example. Every time I have a post instructing to install a library, I’ll probably link into this post.

Ok, back to our main topic.

Why use Joda Time? Well, there are plenty of reasons, some include:

  • Easy to use – straightforward field accessors such as getDayOfWeek()
  • Up-to-date time zone calculations – based on public tz database
  • Maturity – active development since 2002, and
  • Open source (Apache).

It can save you a lot of time for tasks such as:

Joda Time: Step by Step

Step 1: Download the latest version of Joda Time.

How to Use Joda Time in Eclipse?

Download joda time in source forge.

Step 2: Extract the ZIP and find the JAR file.

Files included in the zip.

Files included in the zip.

Step 3,: Copy to JAR file to your project’s libs folder.

> Ctrl+C the Jar file
> find your libs folder (My libs folder is located in my c:/workspace/MyProject/libs/),
> and then Ctrl+V (paste) it there.

Refreshing (Click+F5) your project would look like this:

joda-time-jar-in-eclipse-copy

Step 4: Add the JAR file to your build path.

> Right click your project
> java build path
> libraries tab
> add jars button
> browse the joda time jar file in the libs folder
> order and export tab
> check the joda time jar file

If you want some visuals for this step 4, see this one:

Video Demo Permalink

Step 5: Test. You can have the following code on your sample project to see if it works.

We’ll have this code on our MainActivity.java

package com.example.jodatimeexample;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.Days;

import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        String textViewContents = "Joda Time Results:nn";
        
        TextView tv = (TextView) findViewById(R.id.tvDisplay);
        tv.setText(textViewContents);
        
        
        int daysBetween = getNumDaysBetween("2013-09-01", "2013-09-02");
        tv.setText("Days between 2013-09-01 and 2013-09-02: " + daysBetween);
        
    }

    public int getNumDaysBetween(String dateStart, String dateEnd){
        
        int numDays = 0;
        
        try{
            
            SimpleDateFormat formatYmd = new SimpleDateFormat("yyyy-MM-dd");
         
            Date d1 = formatYmd.parse(dateStart);
            Date d2 = formatYmd.parse(dateEnd);
    
            DateTime dt1 = new DateTime(d1);
            DateTime dt2 = new DateTime(d2);
            
            numDays = Days.daysBetween(dt1, dt2).getDays();
            
            // Days between 2013-09-01 and 2013-09-02: 1
            
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return numDays;
    }
    
}

activity_main.xml (layout file) used:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tvDisplay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Loading value..." />

</RelativeLayout>

The TextView will hold the output when you run the code above, and should look like this:

Days between 2013-09-01 and 2013-09-02: 1

Download Code

Just in case you want to download the code we used: JodaTimeExample.zip

Further Readings

As for some pros and cons of using Joda Time, see Jon’s answer here.

Since Joda Time is another API to learn, you’ll need more examples codes, here are some few hundred Joda Time code examples.

How to Create a Compass in Android Code – Tutorial and Source Code

android compass code example

Today I’m going to share a very simple compass in android code that you can use whenever you are creating an application with a compass feature.

It’s good to see the most devices nowadays has a motion sensor capability to make a compass run.

Unfortunately, there are still some android devices (like Huawei Y300 and Lenovo P700i) does not have full support of motions sensors so this code will not work for them.

We will cover the following in this post:

1.0 Android Compass Video Demo
2.0 Compass App Needed Files
3.0 Complete Compass in Android Code
3.1 MainActivity.java
3.2 activity_main.xml
3.3 Some Notes
4.0 Download Source Code
5.0 Further Readings

1.0 Compass in Android Code Video Demo

Our code for today will run just like the following video.

2.0 Compass App Needed Files

You need to create your own compass image. For this example, I’m using a stock photo. Your image must be a PNG with transparent background, do not use this jpg file I used. Please note that the “north” must be at the top part of the image.

compass in android code example

We will also need the two main code files seen in the complete code below.

3.0 Complete Android Compass Code

3.1 MainActivity.java where all the magic happens. The SensorManager was initialized in the onCreate() method and it was being moved or animated using the onSensorChanged() method.

package com.example.compassapp;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener {

    // define the display assembly compass picture
    private ImageView image;

    // record the compass picture angle turned
    private float currentDegree = 0f;

    // device sensor manager
    private SensorManager mSensorManager;

    TextView tvHeading;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // our compass image 
        image = (ImageView) findViewById(R.id.imageViewCompass);

        // TextView that will tell the user what degree is he heading
        tvHeading = (TextView) findViewById(R.id.tvHeading);

        // initialize your android device sensor capabilities
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        
        // for the system's orientation sensor registered listeners
        mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onPause() {
        super.onPause();
        
        // to stop the listener and save battery
        mSensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        // get the angle around the z-axis rotated
        float degree = Math.round(event.values[0]);

        tvHeading.setText("Heading: " + Float.toString(degree) + " degrees");

        // create a rotation animation (reverse turn degree degrees)
        RotateAnimation ra = new RotateAnimation(
                currentDegree, 
                -degree,
                Animation.RELATIVE_TO_SELF, 0.5f, 
                Animation.RELATIVE_TO_SELF,
                0.5f);

        // how long the animation will take place
        ra.setDuration(210);

        // set the animation after the end of the reservation status
        ra.setFillAfter(true);

        // Start the animation
        image.startAnimation(ra);
        currentDegree = -degree;

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // not in use
    }
}

3.2 activity_main.xml – Our layout file. Wrapped in RelativeLayout, the TextView is used to display the user’s current heading. The ImageView contains the compass image which is being animated like a compass using the code in our MainActivity.java

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff" >

    <TextView
        android:id="@+id/tvHeading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="40dp"
        android:layout_marginTop="20dp"
        android:text="Heading: 0.0" />

    <ImageView
        android:id="@+id/imageViewCompass"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvHeading"
        android:layout_centerHorizontal="true"
        android:src="@drawable/img_compass" />

</RelativeLayout>

3.3 Some notes

1. My app orientation is locked to portrait mode.
2. There are no special permissions in the Manifest file.
3. North Magnetic Pole is the point on the surface of Earth’s
Northern Hemisphere.
4. True north, or the geodetic north, is the direction along the earth’s surface towards the geographic North Pole.
5. Android SensorManager uses the magnetic North Pole.

5.0 Download Source Code

You can get the source code by following the whole, well detailed and free tutorial above. But isn’t it more convenient if you can just download the complete source code we used, and play around it?

There’s a small fee in getting the complete source code, it is small compared to the:

✔ Value or skill upgrade it can bring you, or YES
✔ Income you can get from your website project or business. YES
✔ Precious time you save. YES

Buy now

5.0 Further Readings

This can help you learn more about creating compass in android code. You can visit them and do more customizations!

1. Android SensorManager
2. Android RotateAnimation
3. Android Motion Sensors
4. Magnetic North Pole vs. Geographic North Pole

Introducing The Code Of A Ninja’s Android App (Beta)

Introducing our favorite programming blog’s android app! For the past few days, I have some spare time to code this. Now you guys can browse our blog instantly in your Android phone or tablet. To download this free app, go to your Google Play store and then search using the keywords “code blog by mike dalisay“, you can see our app on the search result.

0-codeofaninja-android-app-search

I think the first advantage of having a mobile website android app is, an app has to be installed. It means that your website or blog will have its own program and icon in the device home screen or list of apps. Users can put it anywhere they want. Our awesome readers can simply tap it to instantly visit your site and see some updates.

The app (ninja) icon is in my home screen.

The app (ninja) icon is in my home screen.

As for the features of this app, we’ll have screenshots with captions below, this can also be a user’s guide.

The Blog View or the “Read Codes” section.  Launching the app will bring you here.

The Blog View or the “Read Codes” section.
Launching the app will bring you here.

The Navigation Drawer. You can see this view if you click the  ninja icon on the upper left corner OR did a swipe from left to right.

The Navigation Drawer. You can see this view if you click the
ninja icon on the upper left corner OR did a swipe from left to right.

Tapping the “About Blog” option will  show you some info about the blog.

Tapping the “About Blog” option will
show you some info about the blog.

“The Ninjas” section contains some information  about the people behind our blog.

“The Ninjas” section contains some information
about the people behind our blog.

Clicking the “share” icon on the upper right corner  of the app will enable you to share the URL of  what you are currently reading in the app.

Clicking the “share” icon on the upper right corner
of the app will enable you to share the URL of
what you are currently reading in the app.

Also, the action overflow will enable you to “refresh” or “copy” the URL of what you are currently reading.

Also, the action overflow will enable you to “refresh” or “copy”
the URL of what you are currently reading.

Now you might ask, what are the functions of those other icons in the navigation drawer?

  1. Like on Facebook – will open the Facebook app with our Facebook page loaded.
  2. Follow on Google+ – will open the Google+ app with our Google+ page.
  3. Follow on Twitter – opens the Twitter app with my twitter account.
  4. Subscribe via email – opens a browser with a feedburner form for email subscription.
  5. Send Feedback – will open the Gmail app pre-loaded with my email, subject and content.

Our app will automatically detect if one of those apps were not installed. It will tell the user “[app_name] does not exist!”

In the future, I want this app to have an offline feature, like the app is able to download useful tutorials or posts on the device so it can be viewed without internet connection.

As of the moment, I only tested this app on my phone and 10.1 tablet (both Jelly Bean). I looks good and works fine for me. You might encounter performance issues, bugs or crashes, the usual things for a beta release. Please don’t hesitate to report them to me, the same if you have any comments or suggestion for our app’s improvement. Thanks!

Thanks for reading this Introducing The Code Of A Ninja’s Android App (Beta)!

Android Notification with Sound and Icon Tutorial

My app needed a simple Android notification with sound and icon. So here’s the code I used to make that happen. I know that there are many other types of notification in Android, but this time, I just want to show you a very simple code that can be a solution to your problem too!

I will probably create a series of blog posts regarding Android notifications, and make it like a cheat sheet for all of us. Anyway, here are some screenshots of today’s code output:

When you run this code

When you run this code

When you click the button “Show Notification”, the notification bar will have the ninja icon and you will hear a sound (make sure you’re not in silent mode).

When you click the button “Show Notification”,
the notification bar will have the ninja icon
and you will hear a sound
(make sure you’re not in silent mode).

When you slide down the notification bar.

When you slide down the notification bar.

Download Code

AndroidNotificationBar.zip

Hide Notification

How to hide the notification? There are two ways:

1. First, you can click the “Cancel Notification” button.
2. Or, second, swipe the notification to left or right (swipe the notification in the third image).

These ways were set programatically, so read the code (with comments) below.

Let’s Code!

Here’s are our awesome code: MainActivity.java

package com.example.androidnotificationbar;

import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // listener handler
        View.OnClickListener handler = new View.OnClickListener(){
            public void onClick(View v) {
                
                switch (v.getId()) {

                    case R.id.btnShowNotification:
                        showNotification();
                        break;
                    
                    case R.id.btnCancelNotification:
                        cancelNotification(0);
                        break;
                }
            }
        };
            
        // we will set the listeners
        findViewById(R.id.btnShowNotification).setOnClickListener(handler);
        findViewById(R.id.btnCancelNotification).setOnClickListener(handler);
        
    }
    
    public void showNotification(){

        // define sound URI, the sound to be played when there's a notification
        Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        
        // intent triggered, you can add other intent for other actions
        Intent intent = new Intent(MainActivity.this, NotificationReceiver.class);
        PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
        
        // this is it, we'll build the notification!
        // in the addAction method, if you don't want any icon, just set the first param to 0
        Notification mNotification = new Notification.Builder(this)
            
            .setContentTitle("New Post!")
            .setContentText("Here's an awesome update for you!")
            .setSmallIcon(R.drawable.ninja)
            .setContentIntent(pIntent)
            .setSound(soundUri)
            
            .addAction(R.drawable.ninja, "View", pIntent)
            .addAction(0, "Remind", pIntent)
            
            .build();
        
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        // If you want to hide the notification after it was selected, do the code below
        // myNotification.flags |= Notification.FLAG_AUTO_CANCEL;
        
        notificationManager.notify(0, mNotification);
    }
    
    public void cancelNotification(int notificationId){
        
        if (Context.NOTIFICATION_SERVICE!=null) {
            String ns = Context.NOTIFICATION_SERVICE;
            NotificationManager nMgr = (NotificationManager) getApplicationContext().getSystemService(ns);
            nMgr.cancel(notificationId);
        }
    }
    
}

I also put the ninja icon in our drawable folder, that’s the source of our icon.

Please share what Android notification example you want next!

Thanks for reading this Android Notification with Sound and Icon Tutorial!

Android Date Picker Example App

I have a friend who often asks: “What day of the week is [insert date here]?” So I decided to create a simple app for him to easily know what day of the week is a certain date. After I made this simple app, I also find it fun to use, haha! Now I know what day of the week I was born, it was Monday (July 30, 1990)!

Video Demo

Here’s the final output of our code for today.

Video Demo Permalink

Live Demo

In case you want to try it yourself, I uploaded this simple app in my play store account. Download it here: Day Of Week Ninja, or you can just search for “day of week ninja” in your android device.

Let’s Code

MainActivity.java – code to run this android date picker example are just in this one file.

package com.example.datepickerlistener;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.os.Bundle;
import android.app.Activity;
import android.view.Gravity;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

    DatePicker datePickerBirthday;
    TextView textViewUserDate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // create the date picker
        datePickerBirthday = new DatePicker(this);
        
        // hide the whole calendar view (works in api 11 or greater)
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (currentapiVersion >= 11) {
            datePickerBirthday.setCalendarViewShown(false);
        }

        // create the TextView
        textViewUserDate = new TextView(this);
        textViewUserDate.setGravity(Gravity.CENTER);
        
        // initialize the date to current date
        SimpleDateFormat sdfDateTime = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        String dateStr = sdfDateTime.format(new Date(System.currentTimeMillis()));
        
        String[] dateSplit = dateStr.split("-");
        int currentYear = Integer.parseInt(dateSplit[0]);
        int currentMonth = Integer.parseInt(dateSplit[1]);
        int currentDay = Integer.parseInt(dateSplit[2]);
        
        // to show date and day of week in the TextView
        setHumanReadableDate(currentYear, currentMonth, currentDay);

        // initialize date picker listener
        // currentMonth - 1, because on the picker, 0 is January
        datePickerBirthday.init(currentYear, currentMonth - 1, currentDay, birthdayListener);

        // add to the container
        LinearLayout linearLayoutCalTvContainer = new LinearLayout(this);
        linearLayoutCalTvContainer.setOrientation(LinearLayout.VERTICAL);
        linearLayoutCalTvContainer.addView(datePickerBirthday);
        linearLayoutCalTvContainer.addView(textViewUserDate);

        // set the views for the activity
        setContentView(linearLayoutCalTvContainer);

    }

    // the date picker listener
    OnDateChangedListener birthdayListener = new OnDateChangedListener() {
        
        @Override
        public void onDateChanged(DatePicker birthDayDatePicker,
                int newYear, int newMonth, int newDay) {

            try{
                
                // currentMonth + 1, to retrieve proper month
                setHumanReadableDate(newYear, newMonth + 1, newDay);
                
            } catch (NullPointerException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    
    // show the user a better date format
    public void setHumanReadableDate(int newYear, int newMonth, int newDay){
        try {
            
            String clickedDate = newYear + "-" + newMonth + "-" + newDay;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date d = sdf.parse(clickedDate);

            SimpleDateFormat sdfDateTime = new SimpleDateFormat("MMMM dd, yyyy 'is' EEEE", Locale.US);
            String dateStr = sdfDateTime.format(d);
            
            textViewUserDate.setText(dateStr);
            
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

}

You can share your thoughts on this Android date picker example code!

Android Table Scroll with Fixed Header and Column

Here’s a sample code I used when I was tasked to make an Android scroll-able table with static header and column. Please note that this code is not yet fully optimized but it can help you have an idea on how this functionality was coded.

Video Demo

The final output of our code for today!

Code Basis

In order to be successful at something, you have to first visualize it. So here’s a simple visualization of what views will be included in our code.

android-fixed-header-and-column

Code

MainActivity.java – executes the table layout

package com.example.tablefreezepane;

import com.Table.TableMainLayout;

import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TableMainLayout(this));
    }
}

SampleObject.java – used for populating some table data, like the rows and table headers.

package com.Table;

public class SampleObject {
    
    String header1;
    String header2;
    String header3;
    String header4;
    String header5;
    String header6;
    String header7;
    String header8;
    String header9;
    
    public SampleObject(String header1, String header2, String header3,
            String header4, String header5, String header6,
            String header7, String header8, String header9){
        
        this.header1 = header1;
        this.header2 = header2;
        this.header3 = header3;
        this.header4 = header4;
        this.header5 = header5;
        this.header6 = header6;
        this.header7 = header7;
        this.header8 = header8;
        this.header9 = header9;
        
    }
}

TableMainLayout.java – where everything were constructed.

*Custom horizontal and vertical scroll views were used to sync the movement of table scrolling effect.

package com.Table;


import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class TableMainLayout extends RelativeLayout {

    public final String TAG = "TableMainLayout.java";
    
    // set the header titles
    String headers[] = {
        "Header 1 n multi-lines",
        "Header 2",
        "Header 3",
        "Header 4",
        "Header 5",
        "Header 6",
        "Header 7",
        "Header 8",
        "Header 9"
    };
    
    TableLayout tableA;
    TableLayout tableB;
    TableLayout tableC;
    TableLayout tableD;
    
    HorizontalScrollView horizontalScrollViewB;
    HorizontalScrollView horizontalScrollViewD;

    ScrollView scrollViewC;
    ScrollView scrollViewD;
    
    Context context;
    
    List<SampleObject> sampleObjects = this.sampleObjects();
    
    int headerCellsWidth[] = new int[headers.length];
    
    public TableMainLayout(Context context) {
        
        super(context);
        
        this.context = context;
        
        // initialize the main components (TableLayouts, HorizontalScrollView, ScrollView)
        this.initComponents();
        this.setComponentsId();
        this.setScrollViewAndHorizontalScrollViewTag();
        
        
        // no need to assemble component A, since it is just a table
        this.horizontalScrollViewB.addView(this.tableB);
        
        this.scrollViewC.addView(this.tableC);
        
        this.scrollViewD.addView(this.horizontalScrollViewD);
        this.horizontalScrollViewD.addView(this.tableD);
        
        // add the components to be part of the main layout
        this.addComponentToMainLayout();
        this.setBackgroundColor(Color.RED);
        
        
        // add some table rows
        this.addTableRowToTableA();
        this. addTableRowToTableB();
        
        this.resizeHeaderHeight();
        
        this.getTableRowHeaderCellWidth();
        
        this.generateTableC_AndTable_B();
        
        this.resizeBodyTableRowHeight();
    }

    // this is just the sample data
    List<SampleObject> sampleObjects(){
        
        List<SampleObject> sampleObjects = new ArrayList<SampleObject>();
        
        for(int x=1; x<=20; x++){
            
            SampleObject sampleObject = new SampleObject(
                "Col 1, Row " + x, 
                "Col 2, Row " + x + " - multi-lines",
                "Col 3, Row " + x,
                "Col 4, Row " + x,
                "Col 5, Row " + x,
                "Col 6, Row " + x,
                "Col 7, Row " + x,
                "Col 8, Row " + x,
                "Col 9, Row " + x
            );
            
            sampleObjects.add(sampleObject);
        }
        
        return sampleObjects;
    
    }
    
    // initalized components 
    private void initComponents(){
        
        this.tableA = new TableLayout(this.context); 
        this.tableB = new TableLayout(this.context); 
        this.tableC = new TableLayout(this.context); 
        this.tableD = new TableLayout(this.context);
        
        this.horizontalScrollViewB = new MyHorizontalScrollView(this.context);
        this.horizontalScrollViewD = new MyHorizontalScrollView(this.context);
        
        this.scrollViewC = new MyScrollView(this.context);
        this.scrollViewD = new MyScrollView(this.context);
        
        this.tableA.setBackgroundColor(Color.GREEN);
        this.horizontalScrollViewB.setBackgroundColor(Color.LTGRAY);
        
    }
    
    // set essential component IDs
    private void setComponentsId(){
        this.tableA.setId(1);
        this.horizontalScrollViewB.setId(2);
        this.scrollViewC.setId(3);
        this.scrollViewD.setId(4);
    }
    
    // set tags for some horizontal and vertical scroll view
    private void setScrollViewAndHorizontalScrollViewTag(){
        
        this.horizontalScrollViewB.setTag("horizontal scroll view b");
        this.horizontalScrollViewD.setTag("horizontal scroll view d");
        
        this.scrollViewC.setTag("scroll view c");
        this.scrollViewD.setTag("scroll view d");
    }
    
    // we add the components here in our TableMainLayout
    private void addComponentToMainLayout(){
        
        // RelativeLayout params were very useful here
        // the addRule method is the key to arrange the components properly
        RelativeLayout.LayoutParams componentB_Params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
        componentB_Params.addRule(RelativeLayout.RIGHT_OF, this.tableA.getId());
        
        RelativeLayout.LayoutParams componentC_Params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
        componentC_Params.addRule(RelativeLayout.BELOW, this.tableA.getId());
        
        RelativeLayout.LayoutParams componentD_Params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
        componentD_Params.addRule(RelativeLayout.RIGHT_OF, this.scrollViewC.getId());
        componentD_Params.addRule(RelativeLayout.BELOW, this.horizontalScrollViewB.getId());
        
        // 'this' is a relative layout, 
        // we extend this table layout as relative layout as seen during the creation of this class
        this.addView(this.tableA);
        this.addView(this.horizontalScrollViewB, componentB_Params);
        this.addView(this.scrollViewC, componentC_Params);
        this.addView(this.scrollViewD, componentD_Params);
            
    }
    

    
    private void addTableRowToTableA(){
        this.tableA.addView(this.componentATableRow());
    }
    
    private void addTableRowToTableB(){
        this.tableB.addView(this.componentBTableRow());
    }
    
    // generate table row of table A
    TableRow componentATableRow(){
        
        TableRow componentATableRow = new TableRow(this.context);
        TextView textView = this.headerTextView(this.headers[0]);
        componentATableRow.addView(textView);
        
        return componentATableRow;
    }
    
    // generate table row of table B
    TableRow componentBTableRow(){
        
        TableRow componentBTableRow = new TableRow(this.context);
        int headerFieldCount = this.headers.length;
        
        TableRow.LayoutParams params = new TableRow.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
        params.setMargins(2, 0, 0, 0);
        
        for(int x=0; x<(headerFieldCount-1); x++){
            TextView textView = this.headerTextView(this.headers[x+1]);
            textView.setLayoutParams(params);
            componentBTableRow.addView(textView);
        }
        
        return componentBTableRow;
    }
    
    // generate table row of table C and table D
    private void generateTableC_AndTable_B(){
        
        // just seeing some header cell width
        for(int x=0; x<this.headerCellsWidth.length; x++){
            Log.v("TableMainLayout.java", this.headerCellsWidth[x]+"");
        }
        
        for(SampleObject sampleObject : this.sampleObjects){
            
            TableRow tableRowForTableC = this.tableRowForTableC(sampleObject);
            TableRow taleRowForTableD = this.taleRowForTableD(sampleObject);
            
            tableRowForTableC.setBackgroundColor(Color.LTGRAY);
            taleRowForTableD.setBackgroundColor(Color.LTGRAY);
            
            this.tableC.addView(tableRowForTableC);
            this.tableD.addView(taleRowForTableD);
            
        }
    }
    
    // a TableRow for table C
    TableRow tableRowForTableC(SampleObject sampleObject){
        
        TableRow.LayoutParams params = new TableRow.LayoutParams( this.headerCellsWidth[0],LayoutParams.MATCH_PARENT);
        params.setMargins(0, 2, 0, 0);
        
        TableRow tableRowForTableC = new TableRow(this.context);
        TextView textView = this.bodyTextView(sampleObject.header1);
        tableRowForTableC.addView(textView,params);
        
        return tableRowForTableC;
    }
    
    TableRow taleRowForTableD(SampleObject sampleObject){

        TableRow taleRowForTableD = new TableRow(this.context);
        
        int loopCount = ((TableRow)this.tableB.getChildAt(0)).getChildCount();
        String info[] = {
            sampleObject.header2,
            sampleObject.header3,
            sampleObject.header4,
            sampleObject.header5,
            sampleObject.header6,
            sampleObject.header7,
            sampleObject.header8,
            sampleObject.header9
        };
        
        for(int x=0 ; x<loopCount; x++){
            TableRow.LayoutParams params = new TableRow.LayoutParams( headerCellsWidth[x+1],LayoutParams.MATCH_PARENT);
            params.setMargins(2, 2, 0, 0);
            
            TextView textViewB = this.bodyTextView(info[x]);
            taleRowForTableD.addView(textViewB,params);
        }
        
        return taleRowForTableD;
        
    }
    
    // table cell standard TextView
    TextView bodyTextView(String label){
        
        TextView bodyTextView = new TextView(this.context);
        bodyTextView.setBackgroundColor(Color.WHITE);
        bodyTextView.setText(label);
        bodyTextView.setGravity(Gravity.CENTER);
        bodyTextView.setPadding(5, 5, 5, 5);
        
        return bodyTextView;
    }
    
    // header standard TextView
    TextView headerTextView(String label){
        
        TextView headerTextView = new TextView(this.context);
        headerTextView.setBackgroundColor(Color.WHITE);
        headerTextView.setText(label);
        headerTextView.setGravity(Gravity.CENTER);
        headerTextView.setPadding(5, 5, 5, 5);
        
        return headerTextView;
    }
    
    // resizing TableRow height starts here
    void resizeHeaderHeight() {
        
        TableRow productNameHeaderTableRow = (TableRow) this.tableA.getChildAt(0);
        TableRow productInfoTableRow = (TableRow)  this.tableB.getChildAt(0);

        int rowAHeight = this.viewHeight(productNameHeaderTableRow);
        int rowBHeight = this.viewHeight(productInfoTableRow);

        TableRow tableRow = rowAHeight < rowBHeight ? productNameHeaderTableRow : productInfoTableRow;
        int finalHeight = rowAHeight > rowBHeight ? rowAHeight : rowBHeight;

        this.matchLayoutHeight(tableRow, finalHeight);
    }
    
    void getTableRowHeaderCellWidth(){
        
        int tableAChildCount = ((TableRow)this.tableA.getChildAt(0)).getChildCount();
        int tableBChildCount = ((TableRow)this.tableB.getChildAt(0)).getChildCount();;
        
        for(int x=0; x<(tableAChildCount+tableBChildCount); x++){
            
            if(x==0){
                this.headerCellsWidth[x] = this.viewWidth(((TableRow)this.tableA.getChildAt(0)).getChildAt(x));
            }else{
                this.headerCellsWidth[x] = this.viewWidth(((TableRow)this.tableB.getChildAt(0)).getChildAt(x-1));
            }
            
        }
    }
    
    // resize body table row height
    void resizeBodyTableRowHeight(){
        
        int tableC_ChildCount = this.tableC.getChildCount();
        
        for(int x=0; x<tableC_ChildCount; x++){
        
            TableRow productNameHeaderTableRow = (TableRow) this.tableC.getChildAt(x);
            TableRow productInfoTableRow = (TableRow)  this.tableD.getChildAt(x);
    
            int rowAHeight = this.viewHeight(productNameHeaderTableRow);
            int rowBHeight = this.viewHeight(productInfoTableRow);
    
            TableRow tableRow = rowAHeight < rowBHeight ? productNameHeaderTableRow : productInfoTableRow;
            int finalHeight = rowAHeight > rowBHeight ? rowAHeight : rowBHeight;

            this.matchLayoutHeight(tableRow, finalHeight);      
        }
        
    }
    
    // match all height in a table row
    // to make a standard TableRow height
    private void matchLayoutHeight(TableRow tableRow, int height) {
        
        int tableRowChildCount = tableRow.getChildCount();
        
        // if a TableRow has only 1 child
        if(tableRow.getChildCount()==1){
            
            View view = tableRow.getChildAt(0);
            TableRow.LayoutParams params = (TableRow.LayoutParams) view.getLayoutParams();
            params.height = height - (params.bottomMargin + params.topMargin);
            
            return ;
        }
        
        // if a TableRow has more than 1 child
        for (int x = 0; x < tableRowChildCount; x++) {
            
            View view = tableRow.getChildAt(x);
            
            TableRow.LayoutParams params = (TableRow.LayoutParams) view.getLayoutParams();

            if (!isTheHeighestLayout(tableRow, x)) {
                params.height = height - (params.bottomMargin + params.topMargin);
                return;
            }
        }

    }

    // check if the view has the highest height in a TableRow
    private boolean isTheHeighestLayout(TableRow tableRow, int layoutPosition) {
        
        int tableRowChildCount = tableRow.getChildCount();
        int heighestViewPosition = -1;
        int viewHeight = 0;

        for (int x = 0; x < tableRowChildCount; x++) {
            View view = tableRow.getChildAt(x);
            int height = this.viewHeight(view);

            if (viewHeight < height) {
                heighestViewPosition = x;
                viewHeight = height;
            }
        }

        return heighestViewPosition == layoutPosition;
    }

    // read a view's height
    private int viewHeight(View view) {
        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        return view.getMeasuredHeight();
    }

    // read a view's width
    private int viewWidth(View view) {
        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        return view.getMeasuredWidth();
    }

    // horizontal scroll view custom class
    class MyHorizontalScrollView extends HorizontalScrollView{

        public MyHorizontalScrollView(Context context) {
            super(context);
        }
        
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            String tag = (String) this.getTag();
            
            if(tag.equalsIgnoreCase("horizontal scroll view b")){
                horizontalScrollViewD.scrollTo(l, 0);
            }else{
                horizontalScrollViewB.scrollTo(l, 0);
            }
        }
        
    }

    // scroll view custom class
    class MyScrollView extends ScrollView{

        public MyScrollView(Context context) {
            super(context);
        }
        
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            
            String tag = (String) this.getTag();
            
            if(tag.equalsIgnoreCase("scroll view c")){
                scrollViewD.scrollTo(0, t);
            }else{
                scrollViewC.scrollTo(0,t);
            }
        }
    }

    
}

You can share your thoughts (in the comments section below) about this scroll-able android TableLayout with fixed header and column code!
Thanks for reading this Android Table Scroll with Fixed Header and Column!

12+ Android Programming Tutorial Blogs and Resources

Here are some of the Android programming tutorial blogs or android code resources that you may also find very useful when starting your Android programming journey. Posts in these blogs ranges from basic to advanced programming, some includes tips and tricks with eclipse or android game programming, so just pick what suits you.

The blogs below does not include the top code resources like StackOverflow and official guides from Google such as the Android Training, Android Design and Android Developer.‘s blog

1. Vogella

12+ Android Programming Tutorial Blogs and Resources

2. Android Helper

android-helper

3. Android-er

android-er

4. Android Aspect

android-aspect

5. Android Hive

android-hive

6. Android for Beginners

android-for-beginners

7. Sai Geetha’s Android Blog

sai-geethas-blog

8. Mkyong Android Tutorial

android-programming-tutorial-2

9. Tech Blog On – Android

tech-blogon

10. Java Code Geeks – Android

java-code-geeks

11. The Code of a Ninja Android Blogs

code-of-a-ninja-android-blogs

12. Tutorials Point – Android

android-programming-tutorial

I also want to grow this list, if you know other useful Android code blogs or resources please drop it in the comments section below, I’m more that willing to update this post!

Please share if you think this list is a useful collection of android programming tutorials!