自适应网格布局DashboardLayout改写
2014-07-04 16:03
369 查看
原来的DashboardLayout.java的下载地址
它是一个自适应的网格布局,所谓的自适应是指当它的布局会根据子view的数量进行调整,具体效果把上述代码下载下来运行就知道了。当它的子view数量是奇数时,它的布局是1*N,垂直排列,居中显示.如果是偶数,它的布局就是n*M,居中显示。
针对子View的数量是偶数的情况,它是通过遍历的形式(初始化列数为1),判断每个子View之间的水平方向上和垂直方向上的间隔之差达到最小值来决定最终的布局(即应该用几行和几列)
以下是我改写的DashboardLayout,添加了动态addChildView和removeChildView的方法,还有当子view的数量是奇数时,也按照子View数量为偶数的情况去处理。
上两张效果图;
它是一个自适应的网格布局,所谓的自适应是指当它的布局会根据子view的数量进行调整,具体效果把上述代码下载下来运行就知道了。当它的子view数量是奇数时,它的布局是1*N,垂直排列,居中显示.如果是偶数,它的布局就是n*M,居中显示。
针对子View的数量是偶数的情况,它是通过遍历的形式(初始化列数为1),判断每个子View之间的水平方向上和垂直方向上的间隔之差达到最小值来决定最终的布局(即应该用几行和几列)
int spaceDifference; // Horizontal and vertical space between items int hSpace = 0; int vSpace = 0; int cols = 1; int rows; while (true) { rows = (visibleCount - 1) / cols + 1; hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); spaceDifference = Math.abs(vSpace - hSpace); if (spaceDifference < bestSpaceDifference) { // Found a better whitespace squareness/ratio bestSpaceDifference = spaceDifference; // If we found a better whitespace squareness and there's only 1 // row, this is // the best we can do. if (rows == 1) { break; } } else { // This is a worse whitespace ratio, use the previous value of // cols and exit. --cols; rows = (visibleCount - 1) / cols + 1; hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); break; } ++cols; }
以下是我改写的DashboardLayout,添加了动态addChildView和removeChildView的方法,还有当子view的数量是奇数时,也按照子View数量为偶数的情况去处理。
package com.example.gridviewtest; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.Toast; import android.widget.ImageView.ScaleType; /** * Custom layout that arranges children in a grid-like manner, optimizing for * even horizontal and vertical whitespace. */ public class DashboardLayout extends ViewGroup { private int mMaxChildWidth = 0; private int mMaxChildHeight = 0; private Object mSyncLock = new Object(); private OnClickListener mOnClickListener; public DashboardLayout(Context context) { super(context, null); init(); } public DashboardLayout(Context context, AttributeSet attrs) { super(context, attrs, 0); init(); } public DashboardLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init(){ setClickable(true); mOnClickListener = new OnClickListener() { @Override public void onClick(View v) { synchronized (mSyncLock) { int childCount = getChildCount(); for(int i = 0;i < childCount;i++){ if(v == getChildAt(i)){ Toast.makeText(getContext(), ""+i, Toast.LENGTH_SHORT).show(); } } } } }; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mMaxChildWidth = 0; mMaxChildHeight = 0; final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } // get the size of child view child.measure(childWidthMeasureSpec, childHeightMeasureSpec); mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth()); mMaxChildHeight = Math.max(mMaxChildHeight, child.getMeasuredHeight()); } setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec), resolveSize(mMaxChildHeight, heightMeasureSpec)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int width = r - l; int height = b - t; t = 0; final int count = getChildCount(); // Calculate the number of visible children. int visibleCount = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } ++visibleCount; } if (visibleCount == 0) { return; } // Calculate what number of rows and columns will optimize for even // horizontal and // vertical whitespace between items. Start with a 1 x N grid, then try // 2 x N, and so on. int bestSpaceDifference = Integer.MAX_VALUE; int spaceDifference; // Horizontal and vertical space between items int hSpace = 0; int vSpace = 0; int cols = 1; int rows; while (true) { rows = (visibleCount - 1) / cols + 1; hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); spaceDifference = Math.abs(vSpace - hSpace); if (spaceDifference < bestSpaceDifference) { // Found a better whitespace squareness/ratio bestSpaceDifference = spaceDifference; // If we found a better whitespace squareness and there's only 1 // row, this is // the best we can do. if (rows == 1) { break; } } else { // This is a worse whitespace ratio, use the previous value of // cols and exit. --cols; rows = (visibleCount - 1) / cols + 1; hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); break; } ++cols; } // Lay out children based on calculated best-fit number of rows and // cols. // If we chose a layout that has negative horizontal or vertical space, // force it to zero. // ebirdfighter think it may be cause some serious problem hSpace = Math.max(0, hSpace); vSpace = Math.max(0, vSpace); // Re-use width/height variables to be child width/height. width = (width - hSpace * (cols + 1)) / cols; height = (height - vSpace * (rows + 1)) / rows; int left, top; int col, row; int visibleIndex = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } row = visibleIndex / cols; col = visibleIndex % cols; left = l + hSpace * (col + 1) + width * col; top = t + vSpace * (row + 1) + height * row; child.layout(left, top,(left + width), (top + height)); ++visibleIndex; } } /** * add an ImageView dynamicly */ public void addChild() { synchronized (mSyncLock) { ImageView imageView = new ImageView(getContext()); imageView.setImageResource(R.drawable.ic_launcher); imageView.setScaleType(ScaleType.CENTER_INSIDE); imageView.setOnClickListener(mOnClickListener); addView(imageView, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } } /** * remove an ImageView dynamicly */ public void removeChild() { synchronized (mSyncLock) { if(getChildCount() > 0){ removeViewAt(getChildCount() - 1); } } } }
上两张效果图;
相关文章推荐
- SWT GridLayout 网格布局
- iOS AutoLayout自动布局中级开发教程(4)-label文字自动适应大小,宽度(新)
- iOS AutoLayout自动布局中级开发教程(4)-label等文字自动适应大小,宽度
- iOS AutoLayout自动布局中级开发教程label等文字自动适应大小,宽度
- android布局------GirdLayout(网格布局)详解
- Java基础之创建窗口——使用网格布局管理器(TryGridLayout)
- SWT GridLayout 网格布局
- esayyui的layout嵌套布局可以解决fit自适应的位置偏移问题
- Layout布局之网格布局
- Android开发总结笔记 GirdLayout(网格布局) 1-1-5
- 自定义布局RelativeLayout 画网格线
- Java布局管理器(三)之GridLayout(网格布局管理)和CardLayout( 卡片布局管理)
- SWT GridLayout网格布局
- Android LinearLayout layout_weight适应屏幕布局
- 自适应的网格布局-砌墙效果
- Android学习 9-> 表格布局TableLayout和网格布局GridLayout
- Android布局layout如何适应不同的分辨率和不同大小的屏幕
- android屏幕自适应不同分辨率或不同屏幕大小的layout布局
- jQuery Easy UI (适应屏幕分辨率大小)布局(Layout)