View的坐标
Left = getLeft();
Right = getRight();
Top = getTop();
Bottom = getBottom();
x = left + translationX;
y = top + translationY;
一、以上所有坐标均是相对父类View容器来说的。
二、需要注意的是,View在平移过程中的,top 和 left 表示的是原始左上角的位置信息,其值并不会发生改变,此时发生改变的是x ,y ,translationX , translationY .。
经过测试:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
// Log.d(TAG, "move, deltaX:" + deltaX + " deltaY:" + deltaY);
int translationX = (int)ViewHelper.getTranslationX(this) + deltaX;
int translationY = (int)ViewHelper.getTranslationY(this) + deltaY;
ViewHelper.setTranslationX(this, translationX);
ViewHelper.setTranslationY(this, translationY);
Log.d(TAG, "TestButton.left=" + getLeft());
Log.d(TAG, "TestButton.x=" + getX());
Log.d(TAG, "TestButton.TranslationX=" + getTranslationX());
break;
}
case MotionEvent.ACTION_UP: {
break;
}
default:
break;
}
mLastX = x;
mLastY = y;
return true;
}
测试Log
08-01 15:50:08.128: D/TestButton(19028): TestButton.left=10
08-01 15:50:08.128: D/TestButton(19028): TestButton.x=42.0
08-01 15:50:08.128: D/TestButton(19028): TestButton.TranslationX=32.0
08-01 15:50:08.144: D/TestButton(19028): TestButton.left=10
08-01 15:50:08.145: D/TestButton(19028): TestButton.x=61.0
08-01 15:50:08.145: D/TestButton(19028): TestButton.TranslationX=51.0
08-01 15:50:08.161: D/TestButton(19028): TestButton.left=10
08-01 15:50:08.161: D/TestButton(19028): TestButton.x=75.0
08-01 15:50:08.161: D/TestButton(19028): TestButton.TranslationX=65.0
08-01 15:51:29.692: D/TestButton(19028): TestButton.left=10
08-01 15:51:29.692: D/TestButton(19028): TestButton.x=-10.0
08-01 15:51:29.693: D/TestButton(19028): TestButton.TranslationX=-20.0
08-01 15:51:29.709: D/TestButton(19028): TestButton.left=10
08-01 15:51:29.709: D/TestButton(19028): TestButton.x=-22.0
08-01 15:51:29.709: D/TestButton(19028): TestButton.TranslationX=-32.0
08-01 15:51:29.726: D/TestButton(19028): TestButton.left=10
08-01 15:51:29.726: D/TestButton(19028): TestButton.x=-33.0
08-01 15:51:29.726: D/TestButton(19028): TestButton.TranslationX=-43.0
可以看出,left值是不变的。在拖动过程中。x 和 translationX 变化。
关于实现动画的几种方法的实现及测试效果:
一、通过handler 定时发送消息,利用scrollto(); 动画。
public class TestActivity extends Activity implements OnClickListener, OnLongClickListener {
private static final String TAG = "TestActivity";
private static final int MESSAGE_SCROLL_TO = 1;
private static final int FRAME_COUNT = 30;
private static final int DELAYED_TIME = 100;
private Button mButton1;
private View mButton2;
private EditText mEditText;
private int mCount = 0;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_SCROLL_TO: {
mCount++;
if (mCount <= FRAME_COUNT) {
float fraction = mCount / (float) FRAME_COUNT;//当前mCount 值 占总值 FRAME_COUNT 的比例
int scrollX = (int) (fraction * 100); //100 PX 用fraction 比例求移动的像素
mButton1.scrollTo(-scrollX, 0); // 用的是 -scroll ,动画向X轴正方向
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME);
}
break;
}
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initView();
}
private void initView() {
mButton1 = (Button) findViewById(R.id.button1);
mButton1.setOnClickListener(this);
mButton2 = (TextView) findViewById(R.id.button2);
mButton2.setOnLongClickListener(this);
mEditText = (EditText) findViewById(R.id.editText1);
mEditText.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mButton1) {
mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME);//发送消息
}
}
}
效果:
LOG:
08-02 11:04:21.061: D/TestActivity(18106): button1.left=10
08-02 11:04:21.062: D/TestActivity(18106): button1.x=10.0
08-02 11:04:21.062: D/TestActivity(18106): button1.TranslationX=0.0
08-02 11:04:21.163: D/TestActivity(18106): button1.left=10
08-02 11:04:21.165: D/TestActivity(18106): button1.x=10.0
08-02 11:04:21.165: D/TestActivity(18106): button1.TranslationX=0.0
08-02 11:04:21.265: D/TestActivity(18106): button1.left=10
08-02 11:04:21.266: D/TestActivity(18106): button1.x=10.0
08-02 11:04:21.269: D/TestActivity(18106): button1.TranslationX=0.0
08-02 11:04:21.371: D/TestActivity(18106): button1.left=10
08-02 11:04:21.371: D/TestActivity(18106): button1.x=10.0
08-02 11:04:21.371: D/TestActivity(18106): button1.TranslationX=0.0
二、直接用scrollTo()瞬间移动
public class TestActivity extends Activity implements OnClickListener {
private static final String TAG = "TestActivity";
private Button mButton1;
private int mCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initView();
}
private void initView() {
mButton1 = (Button) findViewById(R.id.button1);
mButton1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mButton1) {
mButton1.scrollTo(-100, 0);//100为负值,所以往X轴的正方向移动100px
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
}
}
}
效果图
scrollTo 是View原生方法,其作用是专门用于View的滑动,实现滑动效果并且不影响内部元素的单击事件,但是他的缺点也是很明显。只能滑动VIew的内容,并不能滑动View本身。
三、直接利用TranslationX ,移动
public class TestActivity extends Activity implements OnClickListener {
private static final String TAG = "TestActivity";
private Button mButton1;
private int mCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initView();
}
private void initView() {
mButton1 = (Button) findViewById(R.id.button1);
mButton1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mButton1) {
mButton1.setTranslationX(100);
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
}
}
}
效果图
Log:
08-02 11:15:07.646: D/TestActivity(23677): button1.left=10
08-02 11:15:07.646: D/TestActivity(23677): button1.x=110.0
08-02 11:15:07.646: D/TestActivity(23677): button1.TranslationX=100.0
修改代码:多次点击
int i= 50;
mCount++;
mButton1.setTranslationX(i*mCount);
08-02 11:46:18.786: D/TestActivity(2546): button1.left=10
08-02 11:46:18.787: D/TestActivity(2546): button1.x=60.0
08-02 11:46:18.787: D/TestActivity(2546): button1.TranslationX=50.0
08-02 11:46:22.403: D/TestActivity(2546): button1.left=10
08-02 11:46:22.404: D/TestActivity(2546): button1.x=110.0
08-02 11:46:22.404: D/TestActivity(2546): button1.TranslationX=100.0
08-02 11:46:24.724: D/TestActivity(2546): button1.left=10
08-02 11:46:24.726: D/TestActivity(2546): button1.x=160.0
08-02 11:46:24.726: D/TestActivity(2546): button1.TranslationX=150.0
08-02 11:46:27.347: D/TestActivity(2546): button1.left=10
08-02 11:46:27.348: D/TestActivity(2546): button1.x=210.0
08-02 11:46:27.349: D/TestActivity(2546): button1.TranslationX=200.0
08-02 11:46:28.483: D/TestActivity(2546): button1.left=10
08-02 11:46:28.483: D/TestActivity(2546): button1.x=260.0
08-02 11:46:28.483: D/TestActivity(2546): button1.TranslationX=250.0
总之,通过view的LayoutParams设置margin最终影响了view的位置,这个同时会改变view的getLeft/getRight等变量。但通过setTranslationX改变view的位置,是不改变view的LayoutParams的,也即不改变getLeft等view的信息。 但他确实改变了view的位置,这一点可以通过获取其在window或screen的坐标,或通过getLocationInWindow及如下所示的api等到view的精确位置:
总结:
1,setTranslationX改变了view的位置,但没有改变view的LayoutParams里的margin属性;
2,它改变的是android:translationX 属性,也即这个参数级别是和margin平行的。
public class TestActivity extends Activity implements OnClickListener {
private static final String TAG = "TestActivity";
private Button mButton1;
private int mCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initView();
}
private void initView() {
mButton1 = (Button) findViewById(R.id.button1);
mButton1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mButton1) {
ObjectAnimator animator = new ObjectAnimator().ofFloat(mButton1, "translationX", 0, 100);
animator.setDuration(1000);
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
// TODO Auto-generated method stub
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
}
@Override
public void onAnimationRepeat(Animator arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animator arg0) {
// TODO Auto-generated method stub
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
}
@Override
public void onAnimationCancel(Animator arg0) {
// TODO Auto-generated method stub
}
});
animator.start();
}
}
}
效果图
Log:
08-02 11:19:22.386: D/TestActivity(24927): button1.left=10
08-02 11:19:22.386: D/TestActivity(24927): button1.x=10.0
08-02 11:19:22.387: D/TestActivity(24927): button1.TranslationX=0.0
08-02 11:19:23.395: D/TestActivity(24927): button1.left=10
08-02 11:19:23.395: D/TestActivity(24927): button1.x=110.0
08-02 11:19:23.396: D/TestActivity(24927): button1.TranslationX=100.0
五、修改MarginLayoutParams,实现平移
public class TestActivity extends Activity implements OnClickListener {
private static final String TAG = "TestActivity";
private Button mButton1;
private int mCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initView();
}
private void initView() {
mButton1 = (Button) findViewById(R.id.button1);
mButton1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mButton1) {
MarginLayoutParams params = (MarginLayoutParams) mButton1.getLayoutParams();
params.leftMargin += 100;
mButton1.requestLayout();
mButton1.setLayoutParams(params);
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
}
}
}
效果图:
多次点击后,效果图变化。
Log:
08-02 11:25:12.539: D/TestActivity(26801): button1.left=10
08-02 11:25:12.540: D/TestActivity(26801): button1.x=10.0
08-02 11:25:12.540: D/TestActivity(26801): button1.TranslationX=0.0
08-02 11:25:13.398: D/TestActivity(26801): button1.left=110
08-02 11:25:13.398: D/TestActivity(26801): button1.x=110.0
08-02 11:25:13.399: D/TestActivity(26801): button1.TranslationX=0.0
08-02 11:25:13.581: D/TestActivity(26801): button1.left=210
08-02 11:25:13.582: D/TestActivity(26801): button1.x=210.0
08-02 11:25:13.582: D/TestActivity(26801): button1.TranslationX=0.0
08-02 11:25:13.749: D/TestActivity(26801): button1.left=310
08-02 11:25:13.749: D/TestActivity(26801): button1.x=310.0
08-02 11:25:13.749: D/TestActivity(26801): button1.TranslationX=0.0
08-02 11:25:13.909: D/TestActivity(26801): button1.left=410
08-02 11:25:13.909: D/TestActivity(26801): button1.x=410.0
08-02 11:25:13.909: D/TestActivity(26801): button1.TranslationX=0.0
08-02 11:25:14.060: D/TestActivity(26801): button1.left=510
08-02 11:25:14.060: D/TestActivity(26801): button1.x=510.0
08-02 11:25:14.060: D/TestActivity(26801): button1.TranslationX=0.0
六、属性动画,valueAnimator 实现平移
public class TestActivity extends Activity implements OnClickListener {
private static final String TAG = "TestActivity";
private Button mButton1;
private int mCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initView();
}
private void initView() {
mButton1 = (Button) findViewById(R.id.button1);
mButton1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mButton1) {
final int startX = 0;
final int deltaX = 100;
ValueAnimator animatorValue = ValueAnimator.ofInt(0, 1).setDuration(1000);
animatorValue.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
float fraction = animator.getAnimatedFraction();
mButton1.scrollTo(startX + (int) (deltaX * fraction), 0);
Log.d(TAG, "button1.left=" + mButton1.getLeft());
Log.d(TAG, "button1.x=" + mButton1.getX());
Log.d(TAG, "button1.TranslationX=" + mButton1.getTranslationX());
}
});
animatorValue.start();
}
}
}
效果图
Log:
08-02 11:29:55.105: D/TestActivity(29132): button1.left=10
08-02 11:29:55.105: D/TestActivity(29132): button1.x=10.0
08-02 11:29:55.105: D/TestActivity(29132): button1.TranslationX=0.0
08-02 11:29:55.105: D/TestActivity(29132): button1.left=10
08-02 11:29:55.105: D/TestActivity(29132): button1.x=10.0
08-02 11:29:55.105: D/TestActivity(29132): button1.TranslationX=0.0
08-02 11:29:55.116: D/TestActivity(29132): button1.left=10
08-02 11:29:55.116: D/TestActivity(29132): button1.x=10.0
08-02 11:29:55.116: D/TestActivity(29132): button1.TranslationX=0.0