SortableTableView文档翻译:一个可排序的表格控件

一个可排序的表格(TableView)控件,包括了一个简单的TableView 以及更高级的SortableTableView 

项目:http://www.jcodecraeer.com/a/opensource/2015/0729/3237.html 

动态图:

1438166623131556.gif

设置

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)是红色背景,其余是白色背景。