问题
I am making a puzzle game. I am trying to make a GridLayout
dynamically of size 4x4. I am adding LinearLayout
as the child and then an ImageView
inside the LinearLayout
of the GridLayout through code. Layout is coming perfectly fine. But when I drop an ImageView in any of the grid the image is taking complete height and width of the GridLayout. But it should only take the size of the grid in which it is dropped.
Github link of the project.
Here is my code:
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;
}
}
}
Here is my 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>
This is how the Layout is looking:
But when I drop an Image in the any of the grid its taking complete height and width of the GridLayout
:
If I am doing creating a static GridLayout
in layout.xml
its working fine. Problem comes when I am creating dynamic GridLayout
.
Here is my layout.xml
which i used previously to create static GridLayout
and it worked fine. But now I am trying dynamic creation of GridLayout through code which is giving me issues:
<?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">
<LinearLayout
android:id="@+id/row0col0"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="1">
<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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="1">
<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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="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="@drawable/layout_background"
android:orientation="horizontal"
app:layout_columnWeight="1"
app:layout_gravity="fill_horizontal"
app:layout_rowWeight="1">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitXY" />
</LinearLayout>
</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>
Github link of the project.
回答1:
Take a look at where you are adding the linear layout to the grid view in onCreate()
. Early on you are setting the layout params as follows:
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
Yet, later on, you are adding the linear layouts with a different set of layout params as follows:
GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams();
myGLP.rowSpec = rowSpec;
myGLP.columnSpec = colSpec;
layout.addView(linearLayout, myGLP);
This will negate the earlier layout parameters. I suggest you change the code to the following:
GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams();
myGLP.rowSpec = rowSpec;
myGLP.columnSpec = colSpec;
myGLP.width = 0;
myGLP.height = 0;
layout.addView(linearLayout, myGLP);
You can delete the earlier code.
Here is a video of the result:
回答2:
I recommend you, use google flexbox-layout
instead of support GridLayout
. its much more flexible and also stable and easy to use.
See more about it in github.
UPDATE:
This is sample for static XML layout:
<?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>
If you want dynamically add children, see this sample:
XML layout:
<?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>
Code:
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);
}
}
}
}
For add flexbox
to code project, put this line in your gradle dependency:
compile 'com.google.android:flexbox:0.3.0'
来源:https://stackoverflow.com/questions/46598252/issues-adding-child-to-gridlayout-dynamically-in-android