The Quickest way to render a Table from a CSV file in Android

Vivek Vashistha
4 min readJan 4, 2023

In the last article, I showed How to read CSV files and perform Sort and Filter operations on them. In this article, I’ll show how we can render CSV files directly on Android UI. Tables in Android are generally rendered using TableLayout, which is sometimes inconvenient and requires some patience to see even the first output until some significant code is written.

Here comes TableUIBuilder which takes a CSV file as input and renders it on screen with just one line of code.

Suppose we’ve to build TableLayout for the following CSV file content:-

Student Name, Course, Score
Raghvan, Ancient Mythology, 100
Krishna, Politics, 98
Chanakya, Economics, 98

To render this data, write the following one-line code in your Activity/Fragment:-

((ViewGroup) findViewById(R.id.tableContainer)).addView(new TableUIBuilder(this, "student_records.csv").build());

Output:-

The output of students_records.csv

Formatting Table

Now you might want to change the background color of Heading Row, making the text bolder and changing the text color to different color. This can be done as follows:-

((ViewGroup) findViewById(R.id.tableContainer)).addView(
new TableUIBuilder(this, "students_records.csv")
.setDefaultCellBackgroundColor(Color.WHITE)
.setRowBackgroundColor(Color.GRAY,0) // setting background color of 0th row
.setRowTextStyle(Typeface.BOLD,0) // setting text style of 0th row
.setRowTextColor(Color.DKGRAY, 0) // setting text color of 0th Row
.build());
Output after setting additional Properties in TableUIBuilder

But what about Dynamic Data in CSV?

TableUIBuilder also supports dynamic data binding. Let’s say, we’ve to fetch Student records from some other data source, but we want to load UI from the template saved in CSV as follows:-

Student Name, Course, Score
{student_name}, {course}, {score}

Here student_name, course, and score enclosed in curly braces represent variable names that can be bound with data source as follows:

((ViewGroup) findViewById(R.id.tableContainer)).addView(
new TableUIBuilder(this, "students_records_dynamic.csv")
.setDefaultCellBackgroundColor(Color.WHITE)
.setRowBackgroundColor(Color.GRAY,0)
.setRowTextStyle(Typeface.BOLD,0)
.setRowTextColor(Color.DKGRAY, 0)
.bind(getStudentsDataAdapter(getStudentData())) // data binding
.build());
private TableUIBuilder.TableDataAdapter getStudentsDataAdapter(List<Student> students) {
return new TableUIBuilder.TableDataAdapter() {
@Override
public int getRowCount(int templateRowIndex) {
if(templateRowIndex == 1) {
// templateRowIndex = 1 represents second row in CSV file
// for which we return total number of times we want to repeat this row
return students.size();
}
return super.getRowCount(templateRowIndex);
}

@Override
public String getValue(String columnName, int templateRowIndex, int index) {
if(templateRowIndex == 1) {
// templateRowIndex = 1 represents second row in CSV file
// for which we return value for given binding variable : columnName
// for given index
switch (columnName) {
case "student_name": return students.get(index).name;
case "course": return students.get(index).course;
case "score": return students.get(index).score;
}
}
return super.getValue(columnName, templateRowIndex, index);
}
};
}

// Sample Data Source
private List<Student> getStudentData() {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("Raghvan", "Ancient Mythology", "100"));
students.add(new Student("Krishna", "Politics", "98"));
students.add(new Student("Chanakya", "Economics", "98"));
return students;
}

We get the same output as the previous one, but the data source is different:

Dynamic Data need not be a pure vertical list. It can be layout in any way as follows:

School Name# {student_name}, City:{city}, School Rank #{school_rank}
Student Name, Course, Score
{student_name}, {course}, {score}

Here repetition count for the first row (templateRowIndex = 0) will be 1 and for the third row (templateRowIndex=2) will be the total student records. Hence binding adapter can be written as follows:

private TableUIBuilder.TableDataAdapter getStudentsDataAdapter(List<Student> students) {
return new TableUIBuilder.TableDataAdapter() {
@Override
public int getRowCount(int templateRowIndex) {
if(templateRowIndex == 2) {
return students.size();
}
return super.getRowCount(templateRowIndex);
}
@Override
public String getValue(String columnName, int templateRowIndex, int index) {
if(templateRowIndex == 0) {
switch (columnName) {
case "school_name":return "Stanford University";
case "city":return "Stanford";
case "school_rank": return "1";
}
} else if(templateRowIndex == 2) {
switch (columnName) {
case "student_name": return students.get(index).name;
case "course": return students.get(index).course;
case "score": return students.get(index).score;
}
}
return super.getValue(columnName, templateRowIndex, index);
}
};
}

Other Customisation Support

There are a few more customizations supported:-

  1. You can use ColSpan to merge two or more horizontal cells.
  2. You can set text alignment, text style, and text color for individual cells, rows, or the entire table.
  3. You can set the background color of a cell, row, and/or entire table.

Conclusion

TableUIBuilder provides the quickest and easiest way to load CSV data into Android’s TableLayout. There are a lot of enhancements that can be done to support various use cases. Feel free to check out the source code from here.

--

--