Android自绘GridView控件

Android为我们提供了一个很好用的网格控件GridView,它的另外一种实现Google在提供PSDK时包含了一个简单的例子,大家一起来看看吧: 对于还不熟悉Android平台控件子类化的网友可以看看其具体实现的方法,主要是构造时提供了初始化资源、计算控件的尺寸和位置measure相关的处理,大家本次需要注意的是这个固定的Gird是从ViewGroup派生,没有实现onDraw,注意下面的onLayout方法,完整代码如下

public class FixedGridLayout extends ViewGroup {
int mCellWidth;
int mCellHeight;

public FixedGridLayout(Context context) {
    super(context);
}

public FixedGridLayout(Context context, AttributeSet attrs) {
    super(context, attrs);


    TypedArray a = context.obtainStyledAttributes(
            attrs, R.styleable.FixedGridLayout);
    mCellWidth = a.getDimensionPixelSize(
            R.styleable.FixedGridLayout_cellWidth, -1);
    mCellHeight = a.getDimensionPixelSize(
            R.styleable.FixedGridLayout_cellHeight, -1);
    a.recycle();
}

public void setCellWidth(int px) {
    mCellWidth = px;
    requestLayout();
}

public void setCellHeight(int px) {
    mCellHeight = px;
    requestLayout();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int cellWidthSpec = MeasureSpec.makeMeasureSpec(mCellWidth,
            MeasureSpec.AT_MOST);
    int cellHeightSpec = MeasureSpec.makeMeasureSpec(mCellHeight,
            MeasureSpec.AT_MOST);

    int count = getChildCount();
    for (int index=0; index<count; index++) {
        final View child = getChildAt(index);
        child.measure(cellWidthSpec, cellHeightSpec);
    }
    // Use the size our parents gave us
    setMeasuredDimension(resolveSize(mCellWidth*count, widthMeasureSpec),
            resolveSize(mCellHeight*count, heightMeasureSpec));
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int cellWidth = mCellWidth;
    int cellHeight = mCellHeight;
    int columns = (r - l) / cellWidth;
    if (columns < 0) {
        columns = 1;
    }
    int x = 0;
    int y = 0;
    int i = 0;
    int count = getChildCount();
    for (int index=0; index<count; index++) {
        final View child = getChildAt(index);

        int w = child.getMeasuredWidth();
        int h = child.getMeasuredHeight();

        int left = x + ((cellWidth-w)/2);
        int top = y + ((cellHeight-h)/2);

        child.layout(left, top, left+w, top+h);
        if (i >= (columns-1)) {
            // advance to next row
            i = 0;
            x = 0;
            y += cellHeight;
        } else {
            i++;
            x += cellWidth;
        }
    }
}

}

调用的方法也很简单,我们在Activity的onCreate中这样写即可。

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

    FixedGridLayout grid = (FixedGridLayout)findViewById(R.id.grid);
    grid.setCellWidth(80);
    grid.setCellHeight(80);
}

涉及到的资源如下: \res\values\attrs.xml 文件内容为

而main.xml的内容为

<?xml version="1.0" encoding="utf-8"?>

<com.android123.myGridView.FixedGridLayout
xmlns:android=“http://schemas.android.com/apk/res/android
xmlns:app=“com.android123.myGridView”
android:id=“@+id/grid”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:cellWidth=“80dp”
app:cellHeight=“100dp”
>






</com.android123.myGridView.FixedGridLayout>

那么很多网友要问了,这个GridView的内部元素在那里,这里例子懒省事直接在main.xml中往ViewGroup手动加入ImageView实现n宫格的方法,Android123需要提醒网友的是,默认情况下Android的GridView要比这个复杂得多,因为还需要绑定Adapter以及处理很多细节,是从AbsListView派生的,而非本例的ViewGroup,这里仅给大家另外一种思路去实现想要的功能。