《Android 开发艺术探索》随手笔记——第三章View的事件体系


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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值