本文转载自师兄一篇博客:http://blog.csdn.net/yayun0516/article/details/52254818
觉得跟之前的模拟小火箭很相似,又有学习的地方,能作为知识补充。所以转载一起学习。大家也可以关注他的文章哦。
也就是,用户可以随心所欲的拖动控件,布局文件很简单就是一个Button控件:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/id_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /></RelativeLayout>
MainActivity.java:
package com.example.administrator.followview; public class MainActivity extends Activity implements View.OnTouchListener { private Button mButton; private ViewGroup mViewGroup; private int xDelta; private int yDelta; public static final String TAG = "YAYUN"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mViewGroup = (ViewGroup) findViewById(R.id.root); mButton = (Button) findViewById(R.id.id_text); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.leftMargin = 50; layoutParams.topMargin = 50; mButton.setLayoutParams(layoutParams); mButton.setOnTouchListener(this); } @Override public boolean onTouch(View view, MotionEvent event) { final int x = (int) event.getRawX(); final int y = (int) event.getRawY(); Log.d(TAG, "onTouch: x= " + x + "y=" + y); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view .getLayoutParams(); xDelta = x - params.leftMargin; yDelta = y - params.topMargin; Log.d(TAG, "ACTION_DOWN: xDelta= " + xDelta + "yDelta=" + yDelta); break; case MotionEvent.ACTION_MOVE: RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view .getLayoutParams(); int xDistance = x - xDelta; int yDistance = y - yDelta; Log.d(TAG, "ACTION_MOVE: xDistance= " + xDistance + "yDistance=" + yDistance); layoutParams.leftMargin = xDistance; layoutParams.topMargin = yDistance; view.setLayoutParams(layoutParams); break; } mViewGroup.invalidate(); return true; }}
MainActivity实现了OnTouchListener接口,覆写了onTouch方法,每次回调这个方法通过x和y变量记录当前的坐标。
ACTION_DOWN是在按下的时候调用(没抬起来只调用一次),通过xDelta和yDelta来记录第一次按下的点相对于控件左上角的位置,也就是相对距离。
ACTION_MOVE移动的时候不断调用,通过xDistance和yDistance来记录移动的相对距离作为leftMargin和topMargin再动态设置给控件。
最后,调用invalidate方法更新控件位置。
解释起来不容易解释,理解起来也不容易理解,我们可以看一下Log,帮助理解:
按下的时候,首先打印当前的坐标为(131,75),由于在onCreate方法中设置了初始的leftMargin和topMargin都为50,所以此时xDelta的值为131-50=81,yDelta的值为75-50=25。第一个ACTION_MOVE的xDistance为132-81=51,yDistance的值为80-25=55,同理,后面都是循环调用了。
这里主要要注意相对的概念,计算的都是相对距离。
这个效果直接用到的场景不多,但是里面的处理思路都是在开发中经常会用到的,onTouch方法也是控件交互经常会用到的方法,这方面要很熟悉。
希望这个简单的实例可以给大家带来思维的碰撞。