How to Customize Cells and Custom Cell Editors in FlexGrid for Android
One of the most important features in Xuni FlexGrid is its ability to customize cell content and cell editors. In previous posts we've examined customizing FlexGrid cells in Xamarin.Forms and iOS, and in this post we'll complete the cycle by covering cell customizations in Android.
GridCellFactory
Creating custom cell content in Android is in some regards similar to the approach taken in Xamarin.Forms in its heavy use of cell factories. The GridCellFactory class is used to create all of the cells in a grid, and by creating your own class that extends GridCellFactory, you can create you own reusable implementation. Much like in Xamarin.Forms, a grid can have only one cell factory, although a single cell factory can handle any number of customized cells in different columns. I'll be referencing the ConditionalFormatting and CustomCells samples included with the FlexGrid101 (located here on GitHub), which is a helpful reference for the implementation. In this article we'll mostly focus on using the createCellContent method for custom cell content as well as the createCellEditor method for custom editors.
Using createCellContent to customize cells()
The first step is to create your own class extending GridCellFactory. By overriding the CreateCell method, you can directly manipulate the cell. The below sample does a check on the Order Count column and colors the cell green for values over 50, and red otherwise:
public class ConditionalFormattingCellFactory extends GridCellFactory
{
private Customer mCustomer;
public ConditionalFormattingCellFactory(FlexGrid flexGrid)
{
super(flexGrid);
}
@Override
public void createCellContent(GridPanel gridPanel, FlexGridCanvasRenderEngine renderEngine, GridCellRange cellRange, Rect bounds)
{
// condition to only perform custom formatting on cells under the column orderCount
if (gridPanel.getCellType() == GridCellType.CELL && gridPanel.getColumns().get(cellRange.col).getName().equals("orderCount"))
{
// getting data object
mCustomer = (Customer) gridPanel.getRows().get(cellRange.row).getDataItem();
//change text color based on the order total
if (mCustomer.getOrderCount() >= 50)
{
flexGrid.renderEngine.setFillColor(Color.GREEN);
}
else
{
flexGrid.renderEngine.setFillColor(Color.RED);
}
}
// default method
super.createCellContent(gridPanel, renderEngine, cellRange, bounds);
}
}
Now, to use this cell factory elsewhere, you'll need to instantiate the cell factory and use the setCellFactory method for your grid object:
mGrid.setCellFactory(new ConditionalFormattingCellFactory(mGrid));
The end result: You can also use createCellContent for more advanced use cases, such as embedding other controls into grid cells. The below snip demonstrates embedding a Xuni Gauge named nPerformanceGauge into each cell for a given column:
@Override
public void createCellContent(GridPanel gridPanel, FlexGridCanvasRenderEngine renderEngine, GridCellRange cellRange, Rect bounds)
{
// condition to check cells under column Performance
if (gridPanel.getCellType().equals(GridCellType.CELL) && gridPanel.getColumns().get(cellRange.col).getName().equals("Performance"))
{
// getting data object
mCellPoint = (CustomCellPoint) gridPanel.getRows().get(cellRange.row).getDataItem();
// setting the height and width for the gauge
if (bounds.width() != mCellWidth && bounds.height() != mCellHeight)
{
this.mCellWidth = bounds.width();
this.mCellHeight = bounds.height();
mPerformanceGauge.setLayoutParams(new LayoutParams(mCellWidth - (mPaddingLeft * 2), mCellHeight - (mPaddingTop * 2)));
}
mPerformanceGauge.setValue(mCellPoint.getPerformanceGauge());
// rendering the gauge on the canvas, saving its previous state
renderEngine.canvas.save();
renderEngine.canvas.translate(bounds.left + renderEngine.panX + mPaddingLeft, bounds.top + renderEngine.panY + mPaddingTop);
mPerformanceGauge.draw(renderEngine.canvas);
mPerformanceGauge.plotAreaView.draw(renderEngine.canvas);
renderEngine.canvas.restore();
}
else
// default method
super.createCellContent(gridPanel, renderEngine, cellRange, bounds);
}
Here's what the end result will look like with our custom cells: This code is a small piece of the CellFactory implementation found here which is used in the CustomCells sample.
Providing custom editors with createCellEditor()
There will be times where you may want to provide an editor other than the default keyboard (such as a datepicker for a date column), and FlexGrid can easily accommodate those situations. The createCellEditor method can be used to conditionally for DataTypes or a specific column and provide an appropriate editor for that data. This allows you to easily capture a natural look and feel for editing your data contained in the grid. The below code piece demonstrates using a DatePickerDialog for the "hiredDate" column or a TimePickerDialog for the "hiredTime":
public View createCellEditor(GridPanel gridPanel, GridCellRange cellRange, Rect bounds)
{
GridColumn gridColumn = flexGrid.getColumns().get(cellRange.col);
// check for Date type columns
if (gridColumn.getDataType() == DataType.DATE)
{
cp = (ChartPoint) flexGrid.getCollectionView().getItems().get(cellRange.row);
Date date;
Calendar cal = Calendar.getInstance();
// check for Date
if (gridColumn.getName().equals("hiredDate"))
{
date = cp.getHiredDate();
cal.setTime(date);
mDatePicker = new DatePickerDialog(flexGrid.getContext(), onDateSetListener, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY\_OF\_MONTH));
mDatePicker.show();
mDatePicker.setOnDismissListener(onDismissListener);
}
// check for Time
else if (gridColumn.getName().equals("hiredTime"))
{
date = cp.getHiredTime();
cal.setTime(date);
mTimePicker = new TimePickerDialog(flexGrid.getContext(), onTimeSetListener, cal.get(Calendar.HOUR\_OF\_DAY), cal.get(Calendar.MINUTE), true);
mTimePicker.show();
mTimePicker.setOnDismissListener(onDismissListener);
}
return null;
}
// return super method for non-date columns
return super.createCellEditor(gridPanel, cellRange, bounds);
}
Now we'll have a custom date picker: and a custom time picker: Once again, this code is a small piece of the DefaultCellFactory implementation found here.
Conclusion
FlexGrid is a powerful tool with many customizations available. Xuni allows you to use these controls on Android, iOS, and Xamarin.Forms with similar functionality and great results. We’ve also recently covered cell customization in Xamarin.Forms and iOS, which are also worth checking out if you’re interested in Xamarin or iOS development. Regardless of platform, Xuni provides many options for enhancing your apps.