SortableTableView文档翻译:一个可排序的表格控件
一个可排序的表格(TableView)控件,包括了一个简单的TableView 以及更高级的SortableTableView
项目:http://www.jcodecraeer.com/a/opensource/2015/0729/3237.html
动态图:
设置
build.gradle中添加依赖
dependencies {
...
compile 'de.codecrafters.tableview:tableview:0.9.3'
...
}
特性
Layouting
列数
所提供的TableView非常容易满足你的要求,只需在xml布局中设置属性就能设置列数。
<de.codecrafters.tableview.TableView
android:id="@+id/tableView"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:columnCount="4" />
第二种办法是直接在代码中设置TableView的列数。
TableView tableView = (TableView) findViewById(R.id.tableView);
tableView.setColumnCount(4);
列宽
要设置列的相对宽度你可以为每列定义一个特定的权重值(weight)。默认每列的权重值是1,所以每列的宽度是一致的。要让第一列(第一列的index是0)的宽度是其余列的两倍,只需做如下调用。
tableView.setColumnWeight(0, 2);
因为列的宽度不是绝对值而是相对值,因此TableView会适应屏幕的宽度。
显示数据
简单数据
对于显示简单的数据比如二维数组,你可以使用SimpleTableDataAdapter。SimpleTableDataAdapter将把给定的String转换成TextView,并显示在TableView里面的和二维数组相对应的位置。
public class MainActivity extends AppCompatActivity {
private static final String\[\]\[\] DATA_TO_SHOW = { { "This", "is", "a", "test" },
{ "and", "a", "second", "test" } };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TableView<String\[\]> tableView = (TableView<String\[\]>) findViewById(R.id.tableView);
tableView.setDataAdapter(new SimpleTableDataAdapter(this, dataToShow));
}
}
自定义数据
对应显示复杂的自定义数据,你需要实现自己的TableDataAdapter。因此你需要实现getCellView(int rowIndex, int columnIndex, ViewGroup parentView) 方法。每一个table cell都会调用这个方法,它需要返回显示在指定了行号和列号的cell里面的view。这里是一个为Car对象准备的TableDataAdapter的例子。
public class CarTableDataAdapter extends TableDataAdapter<Car> {
public CarTableDataAdapter(Context context, List<Car> data) {
super(context, data);
}
@Override
public View getCellView(int rowIndex, int columnIndex, ViewGroup parentView) {
Car car = getRowData(rowIndex);
View renderedView = null;
switch (columnIndex) {
case 0:
renderedView = renderProducerLogo(car);
break;
case 1:
renderedView = renderCatName(car);
break;
case 2:
renderedView = renderPower(car);
break;
case 3:
renderedView = renderPrice(car);
break;
}
return renderedView;
}
...
}
TableDataAdapter提供了几个用来渲染cell view的方法,比如:
-
getRowData()
-
getContext()
-
getLayoutInflater()
-
getResources()
可排序的数据
如果你需要让数据可排序,你应该使用SortableTableView而不是常规的TableView。为了让一个table能按某列排序,你只需实现一个Comparator,然后设置到指定的列。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
sortableTableView.setColumnComparator(0, new CarProducerComparator());
}
private static class CarProducerComparator implements Comparator<Car> {
@Override
public int compare(Car car1, Car car2) {
return car1.getProducer().getName().compareTo(car2.getProducer().getName());
}
}
这样做之后,SortableTableView将自动在列的header旁边显示一个可以排序的指示图标。点击这个header,table将按照给定的Comparator升序排列,如果header再次被点击将按照降序排列。
Header 数据
设置header视图的数据跟设置table cell的数据是一样的。你要做的就是继承TableHeaderAdapter,它同样提供了TableDataAdapter中描述的那些方法。
如果你要在header中显示的仅仅是列的标题(多数情况下都是如此)theSimpleTableHeaderAdapter完全满足你的需求。
Interaction Listening
点击数据的监听
监听item的点击可以注册一个TableDataClickListener,TableView提供了一个addDataClickListener()方法来做这件事情。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
tableView.addDataClickListener(new CarClickListener());
}
private class CarClickListener implements TableDataClickListener<Car> {
@Override
public void onDataClicked(int rowIndex, Car clickedCar) {
String clickedCarString = clickedCar.getProducer().getName() + " " + clickedCar.getName();
Toast.makeText(getContext(), clickedCarString, Toast.LENGTH_SHORT).show();
}
}
Header点击的监听
监听header的点击可以注册一个TableHeaderClickListner。TableView提供了一个addHeaderClickListener()方法来做这件事情。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
tableView.addHeaderClickListener(new MyHeaderClickListener());
}
private class MyHeaderClickListener implements TableHeaderClickListener {
@Override
public void onHeaderClicked(int columnIndex) {
String notifyText = "clicked column " + (columnIndex+1);
Toast.makeText(getContext(), notifyText, Toast.LENGTH_SHORT).show();
}
}
样式
头部样式
table view提供了几种可以定义header的样式。其中一种就是为设置header一个colour。你可以在xml中采用或者在代码中采用。
<de.codecrafters.tableview.TableView
android:id="@+id/tableView"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:headerColor="@color/primary" />
tableView.setHeaderBackgroundColor(getResources().getColor(R.color.primary));
对应更复杂的header样式,你也可以把一个drawable设置成header的背景,方法如下:
tableView.setHeaderBackground(R.drawable.linear_gradient);
此外,你还可以为table header设置一个elevation。你可以在xml或者代码中设置elevation。
<de.codecrafters.tableview.TableView
android:id="@+id/tableView"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:headerElevation="10" />
tableView.setHeaderElevation(10);
注意:这个_elevationd的实现事用_app-compat的_elevation实现的,因此它可以兼容_lollipop之前的设备____
对于SortableTableViews,我们也可以使用自定义的图标去替换默认的sortable indicator icon(可排序指示图标)。为此你需要实现SortStateViewProvider,然后设置到SortableTableView。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
sortbaleTableView.setHeaderSortStateViewProvider(new MySortStateViewProvider());
}
private static class MySortStateViewProvider implements SortStateViewProvider {
private static final int NO_IMAGE_RES = -1;
@Override
public int getSortStateViewResource(SortState state) {
switch (state) {
case SORTABLE:
return R.mipmap.ic_sortable;
case SORTED_ASC:
return R.mipmap.ic_sorted_asc;
case SORTED_DESC:
return R.mipmap.ic_sorted_desc;
default:
return NO_IMAGE_RES;
}
}
}
还存在一个名叫SortStateViewProviders的工厂类,可以从它那里获得一些SortStateViewProvider的预定义。
Data Row Styling
总的来说,你可以在自定义的TableDataAdapter中完成数据内容样式的所有工作。但是如果你想为一整行添加颜色,可以使用TableDataRowColoriser。在库中已经有一些现成的TableDataRowColoriser实现。可以通过工厂类TableDataRowColorisers获得。
这个工厂包括了比如一个间隔行的coloriser,这个coloriser会让奇数行和偶数行呈现不同的颜色。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
int colorEvenRows = getResources().getColor(R.color.white);
int colorOddRows = getResources().getColor(R.color.gray);
tableView.setDataRowColoriser(TableDataRowColorisers.alternatingRows(colorEvenRows, colorOddRows));
}
如果TableDataRowColorisers工厂中的TableDataRowColoriser不能满足你的需求,你可以创建自己的TableDataRowColoriser实现。下面是一个小例子。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
tableView.setDataRowColoriser(new CarPriceRowColoriser());
}
private static class CarPriceRowColoriser implements TableDataRowColoriser<Car> {
@Override
public int getRowColor(int rowIndex, Car car) {
int rowColor = getResources(R.color.white);
if(car.getPrice() < 50000) {
rowColor = getResources(R.color.light_green);
} else if(car.getPrice() > 100000) {
rowColor = getResources(R.color.light_red);
}
return rowColor;
}
}
这个coloriser将根据显示在此行的汽车的价格设置每行的颜色。便宜的汽车(低于50,000)是绿色背景,昂贵的汽车(高于100,000)是红色背景,其余是白色背景。