AndroidStaggeredGrid是etsy实现的一个android瀑布流控件,没有继承ListView和Gridview,而是从更深层的AbsListVew着手实现,项目地址在这里https://github.com/etsy/AndroidStaggeredGrid。
特性
<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指定项之间的间隔。
private StaggeredGridView mGridView; @Override protected 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 { @Override public int getCount() { return DATA.length; } @Override public Object getItem(int position) { return DATA[position]; } @Override public long getItemId(int position) { return position; } @Override public 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" };
private static final int[] COLOR = new int[] { 0xff33b5e5, 0xffaa66cc, 0xff99cc00, 0xffffbb33, 0xffff4444 };
@Override public 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; }
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 }
@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); } }