如果想要将View在X轴和Y轴上正方向移动100px,有如下几种方法:
- layout
- offsetLeftAndRight,offsetTopAndBottom
- setLayoutParams
- scrollTo,scrollBy
- 属性动画
- 位移动画
1.layout
layout(getLeft() + 100, getTop() + 100, getRight() + 100, getBottom() + 100);
此方法是完完全全移动View的位置,View的x、y、left、top、right、bottom都会相应的增加100px。难道还有不是完完全全移动View的吗?答案是:对的!为什么呢?继续往下看。
2.offsetLeftAndRight,offsetTopAndBottom
offsetLeftAndRight(100);
offsetTopAndBottom(100);
此方法和layout一样,都是完完全全移动View的位置。
3.setLayoutParams
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
lp.leftMargin = getLeft() + 100;
lp.topMargin = getTop() + 100;
setLayoutParams(lp);
此方法同样也是完完全全移动View的位置。
4.scrollTo,scrollBy
// scrollTo(-100, -100);
((View) getParent()).scrollTo(-100, -100);
((View) getParent()).scrollBy(-100, -100);
注意1:
直接用scrollTo是不行的,应该调用父控件的scrollTo。scrollTo移动的是View的Content,如果是TextView,则会发现TextView的文字移动了,但是TextView本身并没有移动。
注意2:
值为什么是负的?
那是因为 移动计算值 = 最开始点坐标 – 最后移动到的坐标。
注意3:
x、y、left、top、right、bottom都没有变。
因为x、y、left、top、right、bottom是相对于父控件而言的,父控件也一起移动了,所以没有变。
5.属性动画
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(this, "translationX", 100),
ObjectAnimator.ofFloat(this, "translationY", 100)
);
animatorSet.start();
移动之后,x、y的值改变了,但是left、top、right、bottom值没有改变。
这边也许有疑问,x和left为什么不一样?
查看getX()方法的源码:
getX() {
return mLeft + getTranslationX();
}
发现确实x和left不是一样的。
6.位移动画
TranslateAnimation anim = new TranslateAnimation(0, 100, 0, 100);
anim.setFillAfter(true);
startAnimation(anim);
位移动画过后,x、y、left、top、right、bottom都没有变。
这就是为什么位移动画过后,View的点击事件没有效果的原因,因为View的属性没有变。这也是属性动画应运而生的原因之一。
最后附上代码,这是一个自定义的View,可以通过Log来查看移动前后x、y、left、top、right、bottom的值。
移动过后的log加了延迟,因为View的移动需要时间。
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("CustomTextView", "Before X:" + getX() + " Y:" + getY()
+ " Left:" + getLeft() + " Top:" + getTop()
+ " Right:" + getRight() + " Bottom:" + getBottom());
// layout
// layout(getLeft() + 100, getTop() + 100, getRight() + 100, getBottom() + 100);
// offsetLeftAndRight、offsetTopAndBottom
// offsetLeftAndRight(100);
// offsetTopAndBottom(100);
// setLayoutParams
// ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
// lp.leftMargin = getLeft() + 100;
// lp.topMargin = getTop() + 100;
// setLayoutParams(lp);
// scrollTo scrollBy
// scrollTo(-100, -100);
// ((View) getParent()).scrollTo(-100, -100);
// ((View) getParent()).scrollBy(-100, -100);
// 属性动画
// AnimatorSet animatorSet = new AnimatorSet();
// animatorSet.playTogether(
// ObjectAnimator.ofFloat(this, "translationX", 100),
// ObjectAnimator.ofFloat(this, "translationY", 100)
// );
// animatorSet.start();
// 位移动画
// TranslateAnimation anim = new TranslateAnimation(0, 100, 0, 100);
// anim.setFillAfter(true);
// startAnimation(anim);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.i("CustomTextView", "After X:" + getX() + " Y:" + getY()
+ " Left:" + getLeft() + " Top:" + getTop() + " Right:" + getRight() + " Bottom:" + getBottom());
}
}, 3000);
break;
}
return false;
}}