Not able to add child layout correctly in Custom View

Surya945 :

I am trying to create a custom view which is basically a grid. No of rows and no of columns is variable. And the grid item is also supplied. Then in the custom view according to rows and columns, grid item is inflated. And onLayout the positioning of child layouts happens.
I am facing a problem in doing so. Child layout is not being correctly displayed. When I am setting the margin and padding in child layout ( include_item.xlm ), margin and padding are not being applied.


screenshot (not allowed to attach picture by stackoverflow) https://drive.google.com/file/d/1XFWs7o0aGxTFHzy4JVT3B7F6OlT5Q0W4/view?usp=sharing


GridLayoutMyAuto.java

1) no of row
2) no of column
3) reference of child layout
4) width_acc_height // width will be equal to height
5) height_acc_width // height will be equal to width

import android.content.Context;
import android.content.res.TypedArray;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.View;



public class GridLayoutMyAuto extends CoordinatorLayout {


    private int row = 4;
    private int column = 4;
    private double childWidth;
    private double childHeight;
    private int child_layout;
    private boolean width_acc_height = false, height_acc_width = false;
    private View[][] grid;

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

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

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


    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context
                .obtainStyledAttributes(attrs, R.styleable.GridLayoutMyAuto);

        row = typedArray.getInteger(R.styleable.GridLayoutMyAuto_row, 5);
        column = typedArray.getInteger(R.styleable.GridLayoutMyAuto_column, 5);
        child_layout = typedArray.getResourceId(R.styleable.GridLayoutMyAuto_child_layout,/*R.child_layout.include_item_2048*/-1);
        width_acc_height = typedArray.getBoolean(R.styleable.GridLayoutMyAuto_width_acc_height, false);
        height_acc_width = typedArray.getBoolean(R.styleable.GridLayoutMyAuto_height_acc_width, false);

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < column; j++) {
                inflate(context, child_layout, this);
            }
        }
        typedArray.recycle();

    }

    public void resetLayout() {
        requestLayout();
    }

    public int getRow() {
        return row;
    }

    public int getColumn() {
        return column;
    }

    public View[][] getGrid() {
        return grid;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childCount = getChildCount();
        int newHeight = row * (widthMeasureSpec / column);

        if (width_acc_height == true) {
            widthMeasureSpec = heightMeasureSpec;
        } else if (height_acc_width == true) {
            heightMeasureSpec = widthMeasureSpec;
        }

        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() != View.GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }

        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean b, int left, int top, int right, int bottom) {

        grid = new View[row][column];

        childWidth = (right - left) / (column * 1.0);
        childHeight = (bottom - top) / (row * 1.0);

        int x;
        int y = top;
        int count = 0;
        for (int i = 0; i < row; i++) {
            x = left;
            for (int j = 0; j < column; j++) {
                View child = getChildAt(count++);
                child.layout(x, y, (int) (x + childWidth), (int) (y + childHeight));
                grid[i][j] = child;
                x += childWidth;
            }
            y += childHeight;

        }
    }


}

values.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="GridLayoutMyAuto">
        <attr name="row" format="integer" />
        <attr name="column" format="integer" />
        <attr name="child_layout" format="reference" />
        <attr name="width_acc_height" format="boolean" />
        <attr name="height_acc_width" format="boolean" />
    </declare-styleable>
</resources>

used in content.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".Classic2048Activity"
    tools:showIn="@layout/activity">

    <suryapps.in.grid_layout_auto.GridLayoutMyAuto
        android:id="@+id/gridLayoutAuto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:child_layout="@layout/include_item"
        app:column="4"
        app:height_acc_width="true"
        app:row="4" />

</LinearLayout>

child layout include_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="8dp">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="2"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="30sp" />

</android.support.v7.widget.CardView>

Surya945 :

Finally, I got the solution. I had to make two changes first in onMesure and sencond in onlayout.

Modified GridLayoutAutoMy.class

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;

import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
 * Modified by Surya Jeet Singh
 */

public class GridLayoutMyAuto extends CoordinatorLayout {


    private int row = 4;
    private int column = 4;
    private double childWidth;
    private double childHeight;
    private int child_layout;
    private boolean width_acc_height = false, height_acc_width = false;
    private View[][] grid;

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

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

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


    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context
                .obtainStyledAttributes(attrs, R.styleable.GridLayoutMyAuto);

        row = typedArray.getInteger(R.styleable.GridLayoutMyAuto_row, 5);
        column = typedArray.getInteger(R.styleable.GridLayoutMyAuto_column, 5);
        child_layout = typedArray.getResourceId(R.styleable.GridLayoutMyAuto_child_layout,/*R.child_layout.include_item_2048*/-1);
        width_acc_height = typedArray.getBoolean(R.styleable.GridLayoutMyAuto_width_acc_height, false);
        height_acc_width = typedArray.getBoolean(R.styleable.GridLayoutMyAuto_height_acc_width, false);

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < column; j++) {
                inflate(context, child_layout, this);
            }
        }
        typedArray.recycle();

    }

    public void resetLayout() {
        requestLayout();
    }


    public int getRow() {
        return row;
    }

    public int getColumn() {
        return column;
    }

    public View[][] getGrid() {
        return grid;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childCount = getChildCount();
        int newHeight = row * (widthMeasureSpec / column);

        if (width_acc_height == true) {
            widthMeasureSpec = heightMeasureSpec;
        } else if (height_acc_width == true) {
            heightMeasureSpec = widthMeasureSpec;
        }
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            int padding = child.getPaddingLeft();
            if (child.getVisibility() != View.GONE) {
                measureChild(child, widthMeasureSpec / column - 2 * padding, heightMeasureSpec / row - 2 * padding);
            }
        }

        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean b, int left, int top, int right, int bottom) {

        grid = new View[row][column];

        childWidth = (right - left) / (column * 1.0);
        childHeight = (bottom - top) / (row * 1.0);

        int x;
        int y = top;
        int count = 0;
        for (int i = 0; i < row; i++) {
            x = left;
            for (int j = 0; j < column; j++) {
                View child = getChildAt(count++);
                int padding = child.getPaddingLeft();
//                padding=18;
                child.layout(x + padding, y + padding, (int) (x + childWidth) - padding, (int) (y + childHeight) - padding);
                grid[i][j] = child;
                x += childWidth;
            }
            y += childHeight;

        }
    }


}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=135799&siteId=1