我正在制作益智游戏。我正在尝试动态调整大小为4x4的GridLayout
。我将LinearLayout
作为孩子添加,然后通过代码在GridLayout的ImageView
内添加LinearLayout
。布局完美无缺。但是当我在任何网格中放置ImageView时,图像占据了GridLayout的完整高度和宽度。但它应该只取掉掉落网格的大小。
这是我的代码:
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
的{{1}},它运行正常。但现在我正在尝试通过代码动态创建GridLayout,这会给我带来问题:
GridLayout
答案 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);
您可以删除之前的代码。
以下是结果视频:
答案 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'