各位好,小弟最近在学习Animation相关的东西,遇到了这样一个问题。
我新建了一个ViewGroup,里面放了数个image,想实现这样的功能,点一下ViewGroup,这数个image的位置就会发生变化。
变化主要有两种:
1.由环形排列变成普通的排列(每行4个);
2.由普通排列(每行4个)变成环形排列;
问题是,我的 onLayout方法里每个image的坐标和performAnimation方法里起始坐标/终止坐标是一样的,但在模拟器上实际显示起来的位置确是不同的,这是为什么呢?
主要代码如下:
- Java code
@Override protected void onLayout(boolean arg0, int l, int t, int r, int b) { Log.i(TAG, "OnLayout()"); if (isCircleLayout()) { // circle layout 如果要排成环形 int childCount = getChildCount(); if (childCount < 1) { Log.w(TAG, "Not enough childs"); return; } final double angle = Math.PI / childCount * 2; final int radius = 150; for (int i = 0; i < childCount; i++) { View child = getChildAt(i); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); int left = (int) (centerX + radius * Math.cos(angle * i) - width / 2); int top = (int) (centerY + radius * Math.sin(angle * i) - height / 2); int right = left + width; int bottom = top + height; Log.i(TAG, "Child " + i + " circle POINT{"); // 这里打了一下log看了下 Log.i(TAG, "left = " + left); Log.i(TAG, "top = " + top); Log.i(TAG, "right = " + right); Log.i(TAG, "bottom = " + bottom); Log.i(TAG, "}"); child.layout(left, top, right, bottom); } } else { // square layout 如果是普通的排列(每行4个) int childCount = getChildCount(); // int childEveryLine = (int) Math.sqrt(childCount); int childEveryLine = 4; Log.i(TAG, "We put >" + childEveryLine + "< childs every line"); if (childEveryLine == 0) { // no need to layout if there isn't any child Log.w(TAG, "No childs found"); return; } // begin layout from left-top area int startX = 0; int startY = 0; for (int i = 0; i < childCount; i++) { View child = getChildAt(i); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); // put {childEveryLine} childs every line if (i != 0 && i % childEveryLine == 0) { startX = 0; startY += height; } child.layout(startX, startY, startX + width, startY + height); Log.i(TAG, "Child " + i + " square POINT{"); Log.i(TAG, "left = " + startX); Log.i(TAG, "top = " + startY); Log.i(TAG, "right = " + (startX + width)); Log.i(TAG, "bottom = " + (startY + height)); Log.i(TAG, "}"); startX += width; } } } private Handler mHandler = new Handler(); public void performAnimation(boolean fromCircleToSquare) { Log.i(TAG, "PerformAnimation() {"); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); Log.i(TAG, "Location" + i + ": (" + child.getLeft() + ", " + child.getTop() + ")"); final double radius = 150; //排列成半径是150的圆,和上面的半径是一样一样的 final double angle = Math.PI / childCount * 2; final int width = child.getMeasuredWidth(); final int height = child.getMeasuredHeight(); final int childEveryLine = 4; AnimationRunnable mRunnable = null; if (fromCircleToSquare) { /* from circle to square */ // make translate animation int fromX = (int) (centerX + radius * Math.cos(angle * i) - width / 2); int fromY = (int) (centerY + radius * Math.sin(angle * i) - height / 2); int toX = (i % childEveryLine) * width; int toY = (int) (i / childEveryLine) * height; // make rotate animation int fromDegrees = 360 / childCount * i; int toDegrees = 0; Log.i(TAG, "Child " + i + " {"); // 这里又打了下log,确认和上边的坐标是一样的 Log.i(TAG, "fromX = " + fromX); Log.i(TAG, "fromY = " + fromY); Log.i(TAG, "toX = " + toX); Log.i(TAG, "toY = " + toY); // Log.i(TAG, "fromDegrees = " + fromDegrees); // Log.i(TAG, "toDegrees = " + toDegrees); Log.i(TAG, "}"); mRunnable = new AnimationRunnable(child, fromX, fromY, toX, toY, fromDegrees, toDegrees, 5000); } else { /* from square to circle */ // make translate animation int fromX = (i % childEveryLine) * width; int fromY = (int) (i / childEveryLine) * height; int toX = (int) (centerX + radius * Math.cos(angle * i) - width / 2); int toY = (int) (centerY + radius * Math.sin(angle * i) - height / 2); // make rotate animation int fromDegrees = 0; int toDegrees = 360 / childCount * i; Log.i(TAG, "Child " + i + " {"); Log.i(TAG, "fromX = " + fromX); Log.i(TAG, "fromY = " + fromY); Log.i(TAG, "toX = " + toX); Log.i(TAG, "toY = " + toY); // Log.i(TAG, "fromDegrees = " + fromDegrees); // Log.i(TAG, "toDegrees = " + toDegrees); Log.i(TAG, "}"); mRunnable = new AnimationRunnable(child, fromX, fromY, toX, toY, fromDegrees, toDegrees, 5000); } if (mRunnable != null) { mHandler.post(mRunnable); } } Log.i(TAG, "}"); }// 这个类是专门用来start animation的 class AnimationRunnable implements Runnable { private View mView; private Animation mTrans; private Animation mRotate; private int mDuration; public AnimationRunnable(View v, int fromX, int fromY, int toX, int toY, int fromDegrees, int toDegrees, int duration) { mView = v; mTrans = new TranslateAnimation(fromX, toX, fromY, toY); // mRotate = new RotateAnimation(fromDegrees, toDegrees, // Animation.RELATIVE_TO_SELF, 0.5F, // Animation.RELATIVE_TO_SELF, 0.5F); mDuration = duration; } @Override public void run() { AnimationSet set = new AnimationSet(true); set.setDuration(mDuration); set.addAnimation(mTrans); // set.addAnimation(mRotate); mView.startAnimation(set); } }; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.i(TAG, "OnMeasure()"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); } getCenter(); // 这人方法是用来得到屏幕中心点的 }