第三种方式就是通过改变LayoutParams的方式实现该效果(这种方法是整个父布局跟着一起动)
我们都知道LayoutParams保存了一个view的布局参数。因此可以在程序中,通过改变LayoutParams来动态的修改一个布局的位置参数,从而达到改变view的位置的效果,我们可以很方便的在程序中使用getLayoutParams()来获取一个view的LayoutParams。当然,计算偏移量的方法与Layout方法中计算offset也是一样的。当获取到偏移量之后,就可以通过setLayoutParams来改变其LayoutParams,代码如下所示:
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX; layoutParams.topMargin = getTop() + offsetY; setLayoutParams(layoutParams);完整代码如下:
public class DragView extends TextView { private int lastX; private int lasty; public DragView(Context context) { super(context); initView(); } public DragView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { setBackgroundColor(Color.BLUE); } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //记录触摸点的坐标 lastX = x; lasty = y; break; case MotionEvent.ACTION_MOVE: //计算偏移量 int offsetX = x - lastX; int offsetY = y - lasty; LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX; layoutParams.topMargin = getTop() + offsetY; setLayoutParams(layoutParams); break; case MotionEvent.ACTION_UP: break; } return true; } }不过这里需要注意的是,通过getLayoutParams()获取LayoutParams时,需要根据view所在父布局的类型来设置不同的类型,比如这里将view放在LinearLayout中就可以使用LinearLayout.LayoutParams.类似的,如果将view放在RelativeLayout中,就需要使用 RelativeLayout.LayoutParams当然这一切的前提是你必须要有一个父布局,不然系统无法获取LayoutParams.
在通过改变LayoutParams来改变一个view的位置时,通常改变的是这个view的Margin属性,所以出了使用布局的LayoutParams之外,还可以使用ViewGroup.MarginLayoutParams来实现这一个功能,代码如下所示:
ViewGroup.MarginLayoutParams layoutParams1 = (ViewGroup.MarginLayoutParams) getLayoutParams(); layoutParams1.leftMargin = getLeft() + offsetX; layoutParams1.topMargin = getTop() + offsetY; setLayoutParams(layoutParams1);可以发现使用ViewGroup.MarginLayoutParams更加的方便,不需要考虑父布局的类型,当然它们的本质是一样的。