在android中动态地将子项添加到GridLayout

时间:2017-10-06 04:23:53

标签: android android-gridlayout

我正在制作益智游戏。我正在尝试动态调整大小为4x4的GridLayout。我将LinearLayout作为孩子添加,然后通过代码在GridLayout的ImageView内添加LinearLayout。布局完美无缺。但是当我在任何网格中放置ImageView时,图像占据了GridLayout的完整高度和宽度。但它应该只取掉掉落网格的大小。

Github link of the project.

这是我的代码:

    public class PuzzleActivity extends AppCompatActivity {

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

        findViewById(R.id.a0).setOnTouchListener(new MyTouchListener());
        findViewById(R.id.b0).setOnTouchListener(new MyTouchListener());
        findViewById(R.id.c0).setOnTouchListener(new MyTouchListener());
        findViewById(R.id.d0).setOnTouchListener(new MyTouchListener());
        findViewById(R.id.e0).setOnTouchListener(new MyTouchListener());
        GridLayout layout = (GridLayout) findViewById(R.id.gridLayout);
        layout.setRowCount(4);
        layout.setColumnCount(4);
        for (int i = 0; i < 4; i++) {
            GridLayout.Spec rowSpec = GridLayout.spec(i, 1,1);
            for (int j = 0; j < 4; j++) {
                GridLayout.Spec colSpec = GridLayout.spec(j, 1,1);
                LinearLayout linearLayout = new LinearLayout(this);
                linearLayout.setLayoutParams(new ViewGroup.LayoutParams(0,0));
                linearLayout.setOrientation(LinearLayout.HORIZONTAL);
                linearLayout.setId(R.id.row + i + R.id.col + j);
                linearLayout.setGravity(Gravity.FILL_HORIZONTAL);
                linearLayout.setBackground(ContextCompat.getDrawable(this, R.drawable.layout_background));
                linearLayout.setOnDragListener(new MyDragListener());
                ImageView imageView = new ImageView(this);
                imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
                imageView.setAdjustViewBounds(true);
                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                linearLayout.addView(imageView);
                GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams();
                myGLP.rowSpec = rowSpec;
                myGLP.columnSpec = colSpec;
                layout.addView(linearLayout, myGLP);
            }
        }
    }

    private final class MyTouchListener implements View.OnTouchListener {
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                        view);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    view.startDragAndDrop(data, shadowBuilder, view, 0);
                } else {
                    view.startDrag(data, shadowBuilder, view, 0);
                }
                view.setVisibility(View.INVISIBLE);
                return true;
            } else {
                return false;
            }
        }
    }

    class MyDragListener implements View.OnDragListener {

        private View.OnClickListener myListener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e("Image name", view.getContentDescription() + "");
                ImageView newImage = (ImageView) view;
                newImage.setImageBitmap(rotateBitmap(((BitmapDrawable) newImage.getDrawable()).getBitmap(), 90));
                //view.setRotation(view.getRotation()+90);
            }
        };

        private Bitmap rotateBitmap(Bitmap bitmap, int rotationAngleDegree) {

            int w = bitmap.getWidth();
            int h = bitmap.getHeight();

            int newW = w, newH = h;
            if (rotationAngleDegree == 90 || rotationAngleDegree == 270) {
                newW = h;
                newH = w;
            }
            Bitmap rotatedBitmap = Bitmap.createBitmap(newW, newH, bitmap.getConfig());
            Canvas canvas = new Canvas(rotatedBitmap);

            Rect rect = new Rect(0, 0, newW, newH);
            Matrix matrix = new Matrix();
            float px = rect.exactCenterX();
            float py = rect.exactCenterY();
            matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getHeight() / 2);
            matrix.postRotate(rotationAngleDegree);
            matrix.postTranslate(px, py);
            canvas.drawBitmap(bitmap, matrix, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG));
            matrix.reset();

            return rotatedBitmap;
        }

        @Override
        public boolean onDrag(View v, DragEvent event) {
            int action = event.getAction();
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    // do nothing
                    break;
                case DragEvent.ACTION_DRAG_ENTERED:
                    /**
                     * Change background of the layout where item is entering
                     */
                    v.setBackgroundColor(Color.parseColor("#ECECEC"));
                    break;
                case DragEvent.ACTION_DRAG_EXITED:
                    /**
                     * Change background of the layout back to normal once item is moved out of it
                     */
                    v.setBackground(ContextCompat.getDrawable(PuzzleActivity.this, R.drawable.layout_background));
                    break;
                case DragEvent.ACTION_DROP:
                    // Dropped, reassign View to ViewGroup
                    View view = (View) event.getLocalState();
                    LinearLayout container = (LinearLayout) v;

                    // Added the following to copy the old view's bitmap to a new ImageView:
                    ImageView oldView = (ImageView) view;
                    ImageView newView = (ImageView) container.getChildAt(0);
                    newView.setId(oldView.getId());
                    newView.setContentDescription(oldView.getContentDescription());
                    newView.setOnClickListener(myListener);
                    newView.setImageBitmap(((BitmapDrawable) oldView.getDrawable()).getBitmap());

                    view.setVisibility(View.VISIBLE);
                    break;
                case DragEvent.ACTION_DRAG_ENDED:
                    View currentView = (View) event.getLocalState();
                    currentView.setVisibility(View.VISIBLE);
                    v.setBackground(ContextCompat.getDrawable(PuzzleActivity.this, R.drawable.layout_background));
                default:
                    break;
            }
            return true;
        }
    }
}

这是我的layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:orientation="vertical">

    <android.support.v7.widget.GridLayout
        android:id="@+id/gridLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/kolamShapesLayout"
        android:layout_centerInParent="true"
        android:paddingBottom="70dp"
        android:paddingEnd="20dp"
        android:paddingStart="20dp"
        android:paddingTop="70dp"
        app:columnCount="3"
        app:rowCount="3">

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

    <android.support.v7.widget.GridLayout
        android:id="@+id/kolamShapesLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:columnCount="5"
        app:rowCount="1">

        <ImageView
            android:id="@+id/a0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:contentDescription="@string/a0"
            android:scaleType="fitXY"
            android:src="@drawable/a0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill_horizontal" />

        <ImageView
            android:id="@+id/c0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:contentDescription="@string/c0"
            android:scaleType="fitXY"
            android:src="@drawable/c0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill_horizontal" />

        <ImageView
            android:id="@+id/e0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:contentDescription="@string/e0"
            android:scaleType="fitXY"
            android:src="@drawable/e0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill_horizontal" />

        <ImageView
            android:id="@+id/d0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:contentDescription="@string/d0"
            android:scaleType="fitXY"
            android:src="@drawable/d0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill_horizontal" />

        <ImageView
            android:id="@+id/b0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:contentDescription="@string/b0"
            android:scaleType="fitXY"
            android:src="@drawable/b0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill_horizontal" />

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

</RelativeLayout>

这就是布局的外观:

enter image description here

但是当我在任意一个网格中放置一个图像时,它会占据GridLayout的完整高度和宽度

enter image description here

如果我在GridLayout中创建静态layout.xml,它的工作正常。当我创建动态GridLayout时出现问题。

这是我之前用来创建静态layout.xml的{​​{1}},它运行正常。但现在我正在尝试通过代码动态创建GridLayout,这会给我带来问题:

GridLayout

Github link of the project.

2 个答案:

答案 0 :(得分:4)

看一下将线性布局添加到onCreate()中的网格视图的位置。在早期,您将按​​如下方式设置布局参数:

LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setLayoutParams(new ViewGroup.LayoutParams(0, 0));

然而,稍后,您将使用不同的布局参数集添加线性布局,如下所示:

GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams();
myGLP.rowSpec = rowSpec;
myGLP.columnSpec = colSpec;
layout.addView(linearLayout, myGLP);

这将取消早期的布局参数。我建议您将代码更改为以下内容:

GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams();
myGLP.rowSpec = rowSpec;
myGLP.columnSpec = colSpec;
myGLP.width = 0;
myGLP.height = 0;
layout.addView(linearLayout, myGLP);

您可以删除之前的代码。

以下是结果视频:

enter image description here

答案 1 :(得分:0)

我建议你使用谷歌flexbox-layout代替support GridLayout。它更加灵活,稳定且易于使用。

github中查看有关它的更多信息。

<强>更新

这是静态XML布局的示例:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.flexbox.FlexboxLayout
        android:id="@+id/flexLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:paddingBottom="70dp"
        android:paddingEnd="20dp"
        android:paddingStart="20dp"
        android:paddingTop="70dp"
        app:alignContent="stretch"
        app:alignItems="stretch"
        app:flexDirection="row"
        app:flexWrap="wrap">

        <LinearLayout
            android:id="@+id/row0col0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#FF0000"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row0col1"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#FFFF00"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row0col2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#FF00FF"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row1col0"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:adjustViewBounds="true"
            android:background="#0000FF"
            android:orientation="horizontal"
            app:layout_flexGrow="1"
            app:layout_wrapBefore="true">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row1col1"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#00FFFF"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row1col2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#FF0000"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row2col0"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#FF0000"
            android:orientation="horizontal"
            app:layout_flexGrow="1"
            app:layout_wrapBefore="true">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row2col1"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#FFFF00"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/row2col2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#FF00FF"
            android:orientation="horizontal"
            app:layout_flexGrow="1">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="fitXY" />

        </LinearLayout>

    </com.google.android.flexbox.FlexboxLayout>
</RelativeLayout>

如果要动态添加子项,请参阅以下示例:

XML布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.flexbox.FlexboxLayout
        android:id="@+id/flexLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:paddingBottom="70dp"
        android:paddingEnd="20dp"
        android:paddingStart="20dp"
        android:paddingTop="70dp"
        app:alignContent="stretch"
        app:alignItems="stretch"
        app:flexDirection="row"
        app:flexWrap="wrap"/>

</RelativeLayout>

代码:

public class PuzzleActivity extends AppCompatActivity {

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

        FlexboxLayout layout = (FlexboxLayout) findViewById(R.id.flexLayout);
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                LinearLayout linearLayout = new LinearLayout(this);
                linearLayout.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
                linearLayout.setOrientation(LinearLayout.HORIZONTAL);
                //linearLayout.setId(R.id.row + i + R.id.col + j);
                linearLayout.setGravity(Gravity.FILL_HORIZONTAL);
                linearLayout.setBackground(ContextCompat.getDrawable(this, R.drawable.layout_background));
                ImageView imageView = new ImageView(this);
                imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
                imageView.setAdjustViewBounds(true);
                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                linearLayout.addView(imageView);

                FlexboxLayout.LayoutParams lp = new FlexboxLayout.LayoutParams(FlexboxLayout.LayoutParams.WRAP_CONTENT, FlexboxLayout.LayoutParams.WRAP_CONTENT);
                lp.setFlexGrow(1);

                if (j == 0)
                    lp.setWrapBefore(true);//notice to this!

                layout.addView(linearLayout, lp);
            }
        }
    }
}

要将flexbox添加到代码项目中,请将此行放在gradle依赖项中:

compile 'com.google.android:flexbox:0.3.0'