Проблемы с динамическим добавлением дочернего элемента в GridLayout в android
Я делаю игру-головоломку. Я пытаюсь сделать GridLayout
динамически размером 4x4. Я добавляю LinearLayout
как ребенок, а затем ImageView
внутри LinearLayout
сетки через код. Планировка идет отлично. Но когда я помещаю ImageView в любую сетку, изображение принимает полную высоту и ширину сетки. Но он должен принимать только размер сетки, в которую он упал.
Здесь это мой код:
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>
Вот как выглядит макет:
Но когда я опускаю изображение в любой из сетки его принимая полную высоту и ширину GridLayout
:
Если я делаю создание статического GridLayout
в layout.xml
его работа отлично. Проблема возникает, когда я создаю динамический GridLayout
.
Вот мой layout.xml
, который я использовал раньше для создания статики GridLayout
и это работало нормально. Но теперь я пытаюсь динамическое создание GridLayout через код, который дает мне проблемы:
<?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>
2 ответа:
Посмотрите, где вы добавляете линейный макет к сетчатому виду в
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);
Вы можете удалить предыдущий код.
Вот видео из результат:
Я рекомендую вам использовать google
Подробнее об этом читайте в github.flexbox-layout
вместоsupport GridLayout
. его гораздо более гибкий, а также стабильный и простой в использовании.Обновление:
Это пример для статического 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'