+2

Gridview tản mạn

Mở bài :

Nghe đến cụm từ này chắc hẳn lập trình viên Android nào cũng rất đỗi quen thuộc , tuy nhiên , cùng với sự phát triển của các phiên bản Android cũng như các thư viện hỗ trợ thì hiện nay mọi người thường sử dụng RecyleView để thay thế cho gridview. Tuy nhiên với bản thân mình việc sử dụng gridview như một thói quen và cũng có rất nhiều thù vị khi phải xử lí view, custom view phù hợp với yêu cầu ứng dụng. Trong bài viết này mình điểm qua một vài custom gridview mình hay dùng.

Thân bài :

Như đã chia sẻ ở mở bài ngay sau đây là 1 số gridView custom mình gửi tới các bạn

ExpandableHeightGridView

Trong 1 số ứng dụng nhất là các ứng dụng mạng xã hội hiện nay bạn rất dễ gắp phải những dạng layout trong scrollview, listview có chứa gridview. Khi đó khó khăn xảy ra khi trong view tồn tại 2 action scroll một của scrollview (hoặc listview) và một của gridview . Trong trường hợp này yêu cầu bắt buộc làm sao loại bỏ được scroll-view của gridview. Ví dụ layout sau

Giải pháp cho vấn đề trên đó là ExpandableHeightGridView. Bạn custom gridview như sau

public class ExpandableHeightGridView extends GridView
{

    boolean expanded = false;

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

    public ExpandableHeightGridView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ExpandableHeightGridView(Context context, AttributeSet attrs,
                                    int defStyle)
    {
        super(context, attrs, defStyle);
    }

    public boolean isExpanded()
    {
        return expanded;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        
        if (isExpanded())
        {
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);

            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        }
        else
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public void setExpanded(boolean expanded)
    {
        this.expanded = expanded;
    }
}

Sau đó trong layout đơn giản bạn chỉ cần :

            <packetname.ExpandableHeightGridView
                android:id="@+id/grid"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </packetname.ExpandableHeightGridView>

FitGridView

Ví dụ này mình lấy từ một lib trên github : https://github.com/ceryle/FitGridView

https://cloud.githubusercontent.com/assets/20969019/21449604/9b90ceac-c8f7-11e6-9c32-3c94b24f8e15.gif

Để sử dụng bạn extend từ gridview 1 class FitGridView

public class FitGridView extends GridView {
    public FitGridView(Context context) {
        super(context);
        init(null);
    }

    public FitGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public FitGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public FitGridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    private int column, row;

    private void init(AttributeSet attrs) {
        getAttributes(attrs);

        setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        setNumColumns(column);
    }

    private void getAttributes(AttributeSet attrs) {
        if (null == attrs)
            return;

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.FitGridView);

        column = typedArray.getInt(R.styleable.FitGridView_column, 0);
        row = typedArray.getInt(R.styleable.FitGridView_row, 0);

        typedArray.recycle();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        remeasure(w, h);
        updateAdapter();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        remeasure(width, height);

        setMeasuredDimension(width, height);
    }

    /**
     * use it to update view if you have changed width/height, grid size or adapter.
     */
    private void updateAdapter() {
        if (null == fitGridAdapter)
            return;

        fitGridAdapter.setNumRows(row);
        fitGridAdapter.setNumColumns(column);
        fitGridAdapter.setColumnHeight(itemHeight);
        fitGridAdapter.setColumnWidth(itemWidth);
        setAdapter(fitGridAdapter);
    }

    public void update() {
        remeasure(getMeasuredWidth(), getMeasuredHeight());
        updateAdapter();
    }

    /**
     * @param displayWidth  sets max available width for grid view
     * @param displayHeight sets max available height for grid view
     */
    public void setDimension(float displayWidth, float displayHeight) {
        itemWidth = (int) displayWidth / column;
        itemHeight = (int) displayHeight / row;
        updateAdapter();
    }

    private int itemWidth = 0, itemHeight = 0;

    private void remeasure(int width, int height) {
        itemWidth = width / (column == 0 ? 1 : column);
        itemHeight = height / (row == 0 ? 1 : row);
    }

    /**
     * @return Number of columns associated with the view
     */
    @Override
    public int getNumColumns() {
        return column;
    }

    /**
     * @return Number of rows associated with the view
     */
    public int getNumRows() {
        return row;
    }

    /**
     * @param column sets the desired number of columns in the grid
     */
    public void setNumColumns(int column) {
        this.column = column;
        super.setNumColumns(column);
    }

    /**
     * @param row sets the desired number of row in the grid
     */
    public void setNumRows(int row) {
        this.row = row;
    }

    private FitGridAdapter fitGridAdapter;

    /**
     * @param fitGridAdapter sets your adapter later in updateAdapter method.
     */
    public void setFitGridAdapter(FitGridAdapter fitGridAdapter) {
        this.fitGridAdapter = fitGridAdapter;
    }
}

Sau đó khi sử dụng : Trong .xml

    <package.FitGridView
     android:id="@+id/gridView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:listSelector="@android:color/transparent"
     app:column="3"
     app:row="4"/>

Trong code :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    gridView = (FitGridView) findViewById(R.id.gridView);
    gridView.setFitGridAdapter(new Adapter(this));
        
    // you can change grid view size any time. don't forget calling update method.
    changeSize(4, 4);
}
        
private void changeSize(int r, int c) {
     gridView.setRow(r);
     gridView.setColumn(c);
     gridView.update();
}

DynamicGridView

Đôi khi trong grid bạn cần thêm sửa xóa ở 1 vị trí bất kì , khi đó bạn cần grid của mình dồn hoặc giãn item hợp lí đó là lúc chúng ta sử dụng DynamicGridView. Mình sử dụng 1 thư viện trên githup : https://github.com/askerov/DynamicGrid

Vì code khá dài nên mọi người có thể tham khảo ở địa chỉ :(https://github.com/askerov/DynamicGrid/blob/master/dynamicgrid/src/org/askerov/dynamicgrid/DynamicGridView.java)

Sau đó sử dụng trong .xml

            <pkg.DynamicGridView
                android:id="@+id/grid"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:horizontalSpacing="4dp"
                android:minHeight="40dp"
                android:numColumns="3"
                android:verticalSpacing="4dp">
            </pkg.DynamicGridView>

Sau đó bạn sử dung adaper additem, remove item như gridview bình thường , DynamicGridView sẽ tự động dồn hoặc giãn item cho bạn.

Kết luận

Như trên mình đã giới thiệu với các bạn 3 cách nhỏ để thay đổi 1 gridview để phù hợp với yêu cầu bài toán, với mình recycle view thực sự rất lợi hại và tiện dụng tuy nhiên sử dụng listview, gridview và biến đổi custom chúng cũng có rất nhiều điều hay mà các bạn nên thử. Đôi khi cũ không phải hay 😃.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí