2048游戏animation的LayoutManager?

为了训练目的,我目前正在复制2048年的游戏。 我已经完成了逻辑和交互,但是在单个TextView打印(并且简单地刷新)它当然是荒谬的。

在考虑如何为游戏构buildUI时,我不确定要select哪个LayoutManager 。 在游戏的4×4网格中我需要做的是在行和列中用animation合并和添加单元格 。 在我看来,这:

我错过了简单的解决scheme吗? 如果不是,我的数据结构(它目前是一个16个整数的数组,但可以很容易地改变成一个4×4的整数数组)的最“自然”的LayoutManager是什么。

Solutions Collecting From Web of "2048游戏animation的LayoutManager?"

更新:包括出现的瓷砖演示和两个瓷砖组合。

我build议你去ConstraintLayout 。 它可以让你有效地定位你的观点,并可以为你提供一些简单的animation。 我嘲笑了下面的一个快速示例来演示这种方法。

以下是结果的video:

在这里输入图像说明

XML布局使用ConstraintLayout作为视图组。 这两个框只是文本视图,但可以很容易地成为图像视图或其他types的视图。

这两个盒子简单地在水平原则之间垂直移动, 520dp gdln100148dpgdln25 )和520dpgdln100 ),对于gdln100520dpgdln100 )。 这些移动animation使用ConstraintSetTransitionManager通过附加到“animate”button的点击处理程序。 XML代码如下:

activity_main.xml中

 <android.support.constraint.ConstraintLayout 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:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <android.support.constraint.Guideline android:id="@+id/gdln0" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="24dp" /> <android.support.constraint.Guideline android:id="@+id/gdln25" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="148dp" /> <android.support.constraint.Guideline android:id="@+id/gdln50" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="272dp" /> <android.support.constraint.Guideline android:id="@+id/gdln75" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="396dp" /> <android.support.constraint.Guideline android:id="@+id/gdln100" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="520dp" /> <TextView android:id="@+id/textView1" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginStart="24dp" android:background="@android:color/darker_gray" android:gravity="center" android:text="2" android:textColor="@android:color/white" android:textSize="72sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/gdln0" /> <TextView android:id="@+id/textView2" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginStart="24dp" android:background="@android:color/darker_gray" android:gravity="center" android:text="4" android:textColor="@android:color/white" android:textSize="72sp" app:layout_constraintStart_toEndOf="@+id/textView1" app:layout_constraintTop_toBottomOf="@id/gdln25" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:layout_marginRight="16dp" android:text="Animate" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout> 

MainActivity.java

 public class MainActivity extends AppCompatActivity { private int mSquareSide; private int mMargin; private int mBoardState = 0; private TextView mNewView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Resources r = getResources(); mSquareSide = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, r.getDisplayMetrics()); mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, r.getDisplayMetrics()); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.layout); ConstraintSet newSet = new ConstraintSet(); mBoardState = (mBoardState + 1) % 3; switch (mBoardState) { case 0: // Just reset the board to its starting condition. setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(this); break; case 1: // Move tiles down and insert new tile. mNewView = new TextView(layout.getContext()); mNewView.setId(View.generateViewId()); mNewView.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); mNewView.setTextSize(72); mNewView.setTextColor(getResources().getColor(android.R.color.white)); mNewView.setText("2"); mNewView.setVisibility(View.INVISIBLE); mNewView.setGravity(Gravity.CENTER); ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(mSquareSide, mSquareSide); mNewView.setLayoutParams(lp); layout.addView(mNewView); newSet.clone(layout); newSet.connect(mNewView.getId(), ConstraintSet.TOP, R.id.gdln0, ConstraintSet.BOTTOM); newSet.connect(mNewView.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, mMargin); newSet.clear(R.id.textView1, ConstraintSet.TOP); newSet.clear(R.id.textView2, ConstraintSet.TOP); newSet.connect(R.id.textView1, ConstraintSet.BOTTOM, R.id.gdln100, ConstraintSet.BOTTOM); newSet.connect(R.id.textView2, ConstraintSet.BOTTOM, R.id.gdln100, ConstraintSet.BOTTOM); TransitionManager.beginDelayedTransition(layout); newSet.applyTo(layout); mNewView.setVisibility(View.VISIBLE); break; case 2: // Move tiles up and combine two tiles. newSet.clone(layout); newSet.clear(R.id.textView1, ConstraintSet.BOTTOM); newSet.clear(R.id.textView2, ConstraintSet.BOTTOM); newSet.connect(R.id.textView1, ConstraintSet.TOP, R.id.gdln0, ConstraintSet.BOTTOM); newSet.connect(R.id.textView2, ConstraintSet.TOP, R.id.gdln0, ConstraintSet.BOTTOM); Transition transition = new AutoTransition(); transition.addListener(new Transition.TransitionListener() { @Override public void onTransitionStart(Transition transition) { } @Override public void onTransitionEnd(Transition transition) { mNewView.setText("4"); // Here you would remove the overlapped view // with layout.removeView(View); } @Override public void onTransitionCancel(Transition transition) { } @Override public void onTransitionPause(Transition transition) { } @Override public void onTransitionResume(Transition transition) { } }); TransitionManager.beginDelayedTransition(layout, transition); newSet.applyTo(layout); break; } } }); } } 

我认为我会用简单的方式绘制整个东西,而不使用任何TextView或类似的东西。

让我解释一下为什么。

假设你有一组16个TextView ,这是你在网格中可以使用的最大值,你应该pipe理哪一个是可见的,哪一个是不可见的,隐藏与否,在布局中移动它。 这会占用很多资源,如果你使用的是你所描述的布局,那么“自由”的转换也是不可能的。

假设你有两个瓷砖,你想在另一个上滑动并合并它们。 我能想到的唯一可用布局是RelativeLayout因为它是最容易操作的约束条件之一。

你将不得不处理每一个TextView而是要pipe理渐变和重叠,同时让Android考虑所有TextView可以做的事情。

现在,你必须做所有的动作/重叠的东西,所以你为什么不通过绘制每个瓷砖呢? 你将不得不再写一些代码来画一个假设的Tile类到一个canvas中 (注意你可能会改变你的数据结构)。

当你有你的绘图机制后,你将不得不使用TextView来做同样的事情 ,而是以一种不同的,更自由的思维方式,减less约束和使用更less的Android资源。

我知道你是在问一些关于Layoutbuild议,我build议你自己画一些瓷砖,这可能不是你需要的,如果我用这么长时间的话来打扰你,我很抱歉,但是如果你在一个“更广泛”的方式,我认为这是一个好主意,要记住。
这也是学习关于An​​droid 2D绘图的好机会!

快乐的编码!