各位好,小弟最近在学习Animation相关的东西,遇到了这样一个问题。我新建了一个ViewGroup,里面放了数个image,想实现这样的功能,点一下ViewGroup,这数个image的位置就会发生变化。变化主要有两种:
1.由环形排列变成普通的排列(每行4个);
2.由普通排列(每行4个)变成环形排列;问题是,我的 onLayout方法里每个image的坐标和performAnimation方法里起始坐标/终止坐标是一样的,但在模拟器上实际显示起来的位置确是不同的,这是为什么呢?主要代码如下:
@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(); // 这人方法是用来得到屏幕中心点的
}
先谢过了。

解决方案 »

  1.   

    这些图片的宽高都一样吗?
    我觉得可能是跟AVD的密度屏幕大小有关。
      

  2.   


    图片都是一样的,高宽相同。
    求教怎么个和AVD的屏幕大小有关法呢?
      

  3.   

    刚才是感觉可能和密度大小有关,后来仔细看了下,
    ”onLayout方法里每个image的坐标和performAnimation方法里起始坐标/终止坐标是一样的“
    这个并不能说明你的image就是在同一位置,主要是fromX, fromY, 和toX,toY,是不是一样。
      

  4.   


    我所说的起始坐标就是fromX,fromY,终止坐标是toX,toY,从我打出的log看来,坐标应该是正确的。刚才我又建了个小工程试了下,把一上一下放置的两个图片(紧贴),同时移动到(100,100)这个点,再移回原位,奇怪的是两个图片开始移动的时候,一上一下之间凭空出现一个大空,移动到(100,100)的时候两者也不重合,真是怪哉。
      

  5.   

    TranslateAnimation(fromX, toX, fromY, toY);
    你确定这四个参数的含义清楚了? 我查了下SDK,发现
    TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
    我觉得这个是个相对的坐标,不是绝对的
    你可以改成 TranslateAnimation(0, 100, 0, 100);试试,开始的位置应该就不会变了。