Monday, August 13, 2012

Howto - Creating a two dimensions scroll view

Rendering Amortization schedule in a horizontal + vertical scrolling view

An Amortization schedule consists of many rows and columns of data that we want to display it on a scrolling pane (i.e. feasible to scroll vertically and horizontally).



The Android sample has good example on vertical scrolling but don't have the combined scrolling in two dimensions. After Google around and couple of trials and errors, I came to this solution...

Scrolling view classes
Android has two classes for scrolling, one for horizontal and one for vertical. They all subclass from FrameLayout and they can have one child containing all data to scroll.
  1. ScrollView - Vertically scrolling only
  2. HorizontalScrollView - Horizontal scrolling only
Layout the scrolling pane in the XML
In the layout XML, the HorizontalScrollView is placed inside the ScrollView. It also has a header row to show the name of each column.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>

<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="fill_parent">

<TableLayout
android:id="@+id/amortization"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>

<TableRow
android:background="#ffff00">
<TextView
android:text="@string/amortization_1"
android:padding="3dip"
/>
<TextView
android:text="@string/amortization_2"
android:padding="3dip"
/>
<TextView
android:text="@string/amortization_3"
android:padding="3dip"
/>
<TextView
android:text="@string/amortization_4"
android:padding="3dip"
/>
<TextView
android:text="@string/amortization_5"
android:padding="3dip"
/>
<TextView
android:text="@string/amortization_6"
android:padding="3dip"
/>
<TextView
android:text="@string/amortization_7"
android:padding="3dip"
/>
</TableRow>

</TableLayout>
</HorizontalScrollView>
</ScrollView>


Programmatic adding rows into the amortization schedule table
In the AmortizationActivity's onCreate(...) method, it finds the TableLayout object by id=R.id.amortization and calls the appendRows(...) to programmatically adding TableRow object into the TableLayout.



protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.amortization);
TableLayout aTable=(TableLayout)findViewById(R.id.amortization);
Bundle aBundle=getIntent().getExtras();
if(aBundle!=null){
LoanCalculator amortization=(LoanCalculator)
aBundle.getSerializable("amortization");
String[][] amortValues=amortization.computeAmortization();
appendRows(aTable,amortValues);
}
}

...
private void appendRows(TableLayout table, String[][] amortization) {
int rowSize=amortization.length;
int colSize=(amortization.length>0)?amortization[0].length:0;
for(int i=0; i<rowSize; i++){
TableRow row = new TableRow(this);

for(int j=0; j<colSize; j++){
TextView c = new TextView(this);
c.setText(amortization[i][j]);
c.setPadding(3, 3, 3, 3);
row.addView(c);
}

table.addView(row, new TableLayout.LayoutParams());
}
}