我正在创建一个游戏,其中会有大量可点击的ImageView和一个无法点击的imageView,当点击可点击的ImageView时,它应该将其位置与不可点击的ImageView交换(在此示例中,它被调用imageView2)。
当我使用px单元作为我的imageView(s)时,一切正常。但是,如您所知,使用px单元会导致不同设备上的显示不同。但是,当我使用dp单位时,属性动画不起作用。我如何使用dp单位?
MainActivity.java
public class MainActivity extends Activity implements View.OnClickListener {
ImageView imageView1, imageView2;
float x, x_9, y, y_9;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView2 = (ImageView) findViewById(R.id.imageView2);
imageView1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// Get x position of clicked imageView
x = v.getX();
// Get x position of imageView2
x_9 = imageView2.getX();
// Get y position of clicked imageView
y = v.getY();
// Get y position of imageView2
y_9 = imageView2.getY();
// Check if imageViews are align with each other either horizontally or vertically
if((x == x_9 && y + 100 == y_9) || (x == x_9 && y - 100 == y_9) || (x + 100 == x_9 && y == y_9) || (x - 100 == x_9 && y == y_9)) {
// If they are aligned, swap their position with property animation
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("translationX", x_9);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("translationY", y_9);
PropertyValuesHolder pvhX9 = PropertyValuesHolder.ofFloat("translationX", x);
PropertyValuesHolder pvhY9 = PropertyValuesHolder.ofFloat("translationY", y);
ObjectAnimator blockAnim = ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY);
blockAnim.setDuration(500);
blockAnim.setRepeatCount(0);
blockAnim.start();
ObjectAnimator blockAnim2 = ObjectAnimator.ofPropertyValuesHolder(imageView2, pvhX9, pvhY9);
blockAnim2.setDuration(500);
blockAnim2.setRepeatCount(0);
blockAnim2.start();
}
}
}
activity_main.xml中
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/relative"
android:background="@color/grey"
android:layout_width="400dp"
android:layout_height="400dp"
>
<ImageView
android:id="@+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/smiley1"/>
<ImageView
android:id="@+id/imageView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/smiley2"
android:translationX="100dp"/>
</RelativeLayout>
</RelativeLayout>
如何解决此问题?所有建议都受到欢迎。谢谢。
根据Nikola Milutinovic的建议,我添加了GlobalLayoutListener,如下所示
this.findViewById(R.id.relative).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
x = v.getX();
x_9 = imageView2.getX();
y = v.getY();
y_9 = imageView2.getY();
}
});
答案 0 :(得分:2)
我认为这样做的方法是通过imageViews包含的实际值将硬编码引用更改为宽度和高度。在if条件中将100更改为getHeight()或getWidth();
int height = imageView1.getHeight();
int width = imageView1.getWidth();
if((x == x_9 && y + height == y_9) || (x == x_9 && y - height == y_9) ||
(x + width == x_9 && y == y_9) || (x - width == x_9 && y == y_9)){
}
这样你就没有对px的引用。您使用的“100”值意味着100px。 hdpi设备的实际宽度或高度可能是1.5 * 100 = 150px。通过使用getWidth()和getHeight(),您将在屏幕中使用px的实际值。我希望很清楚。您将需要修改超过2个imageView的if条件,但原理是相同的。
如果你想让动画同步,最好使用AnimatorSet。
ArrayList <Animator> animations = new ArrayList<Animator>();
animations.add(ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY));
animations.add(ObjectAnimator.ofPropertyValuesHolder(imageView2, pvhX9, pvhY9));
AnimatorSet animatoreSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.setRepeatCount(0);
animatorSet.playTogether(animations);
animatorSet.start();
如果您需要添加侦听器,请执行此操作,只需添加一次。
答案 1 :(得分:0)
请参阅下面这两种方法的文档,找出最适合您的方法。 container
将是您的根布局(此顶部的RelativeLayout或ID为relative
的<)
container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
}
});
container.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
@Override
public void onDraw() {
}
});
以下是我实现此侦听器的示例。 我在里面做各种各样的事情。请看一下。
public class CustomOnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
private Context context;
private View fragment;
private float x1;
private float y1;
private float x2;
private float y2;
public CustomOnGlobalLayoutListener(Context context, View view, float x1, float y1, float x2, float y2) {
this.context = context;
this.fragment = view;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
@Override
public void onGlobalLayout() {
fragment.setX(x1);
fragment.setY(y1);
removeOnGlobalLayoutListener();
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fragment.getLayoutParams();
fragment.setLayoutParams(layoutParams);
fragment.setPivotX(0);
fragment.setPivotY(0);
fragment.setScaleX((x2 - x1) / fragment.getMeasuredWidth());
fragment.setScaleY((y2 - y1) / fragment.getMeasuredHeight());
fragment.setAlpha(0f);
PropertyValuesHolder pA = PropertyValuesHolder.ofFloat(View.ALPHA, 1f);
PropertyValuesHolder pX = PropertyValuesHolder.ofFloat(View.X, 0f);
PropertyValuesHolder pY = PropertyValuesHolder.ofFloat(View.Y, 0f);
PropertyValuesHolder pSx = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
PropertyValuesHolder pSy = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
final ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(fragment, pA, pX, pY, pSx, pSy);
animator1.setInterpolator(new AccelerateDecelerateInterpolator());
animator1.setDuration(200);
animator1.start();
}
private void removeOnGlobalLayoutListener() {
if (Build.VERSION.SDK_INT < 16) {
//noinspection deprecation
fragment.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
fragment.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
不要忘记删除全球布局的聆听者;
如果您在实现此问题时遇到任何问题,请写下来,我们会考虑一些问题:)
您还可以查看我的github repo,我实际上在这里使用它来从触摸点实现viewpager的打开片段。
https://github.com/mrnmilutinovic/HumanityTestProject
检查ImagePagerFragment
课程以查看其使用情况。
此代码是可编译的,因此您也可以运行并查看它是否有效。