Android瀑布流控件——AndroidStaggeredGrid

来源:互联网 发布:数控火焰切割手工编程 编辑:程序博客网 时间:2024/06/05 04:31

AndroidStaggeredGrid是etsy实现的一个android瀑布流控件,没有继承ListView和Gridview,而是从更深层的AbsListVew着手实现,项目地址在这里https://github.com/etsy/AndroidStaggeredGrid。

特性

  • 设置列数,可以分别为横屏和竖屏指定不同的值
  • 屏幕方向改变时保持项的添加顺序不改变
  • 设置列表项之间的间隔
  • 支持添加header和footer
  • 支持OnScrollListener接口
下面是etsy开发的app的一个截图
这里我们看一下具体的使用方法
首先将AndroidStaggeredGrid项目导入eclipse,像这样
其中的StaggeredGridView就是要使用的瀑布流控件。导入后新建一个Android Project,

添加资源文件activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <com.etsy.android.grid.StaggeredGridView        xmlns:app="http://schemas.android.com/apk/res-auto"        android:id="@+id/grid_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:column_count_landscape="2"        app:column_count_portrait="3"        app:item_margin="8dp" /></RelativeLayout>
column_count指定列数,landscape、portrait分别指定横屏和竖屏,item_margin指定项之间的间隔。
之后在MainActivity中绑定资源,添加数据
private StaggeredGridView mGridView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mGridView = (StaggeredGridView) findViewById(R.id.grid_view);mGridView.setAdapter(new MyAdapter());}

private class MyAdapter extends BaseAdapter {@Overridepublic int getCount() {return DATA.length;}@Overridepublic Object getItem(int position) {return DATA[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = new TextView(MainActivity.this);}TextView view = (TextView) convertView;view.setText(DATA[position]);view.setBackgroundColor(COLOR[position % 5]);view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);view.setGravity(Gravity.BOTTOM);view.setTextColor(Color.WHITE);return view;}}private static final String[] DATA = new String[] {"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",        "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",        "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",        "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",        "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",        "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",        "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",        "Baylough", "Beaufort", "Beauvoorde"};

因为StaggeredGridView也继承自AbsListView,所以和ListView、GridView的用法完全一样。运行一下

背景色是这几个值
private static final int[] COLOR = new int[] {0xff33b5e5, 0xffaa66cc, 0xff99cc00, 0xffffbb33, 0xffff4444};

样子不太好看,美化一下,StaggeredGridView会根据列的个数计算列宽,因此我们可以指定每个项的高度,修改一下getView()方法
@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = new TextView(MainActivity.this);LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);convertView.setLayoutParams(lp);}TextView view = (TextView) convertView;view.setText(DATA[position]);view.setBackgroundColor(COLOR[position % 5]);view.setGravity(Gravity.BOTTOM);view.setTextColor(Color.WHITE);LayoutParams lp = (LayoutParams) view.getLayoutParams();lp.height = (int) (getPositionRatio(position) * 200);view.setLayoutParams(lp);return view;}

其中计算项高的方法是从staggeredGridView提供的sample中提出来的,就是根据位置得到一个随机的比例
private final Random mRandom = new Random();    private static final SparseArray<Double> sPositionHeightRatios = new SparseArray<Double>();private double getPositionRatio(final int position) {        double ratio = sPositionHeightRatios.get(position, 0.0);        if (ratio == 0) {            ratio = getRandomHeightRatio();            sPositionHeightRatios.append(position, ratio);        }        return ratio;    }    private double getRandomHeightRatio() {        return (mRandom.nextDouble() / 2.0) + 1.0; // height will be 1.0 - 1.5 the width    }

再次运行的结果

到这里AndroidStaggeredGrid的使用方法就介绍完了,为列表项添加点击事件setOnItemClickListener,在上面我们可以看到在项目文件中还提供了两个DynamicHeightImageview和DynamicHeightTextView,这两个视图就是如果指定了宽高比,会在绘制的时候保持该比例,具体操作看下面这几行
@Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if (mHeightRatio > 0.0) {            // set the image views size            int width = MeasureSpec.getSize(widthMeasureSpec);            int height = (int) (width * mHeightRatio);            setMeasuredDimension(width, height);        }        else {            super.onMeasure(widthMeasureSpec, heightMeasureSpec);        }    }

在实际应用中我们可以定义更加复杂的列表项。


3 3