浅涉-----改变view位置的几种方式

为更好说明 代码动态改变view的方式,此处以一个随手指滑动而变化的自定义view的讲解为例


随手指而动,少不了对 onTouchEvent 方法的处理,基本思路为3步:

1.手指摁下的时候,记录当前x,y坐标

2.手指移动后未抬起的时候,获取当前手指处的x,y坐标,算出位移差,给view重新设置位置

3.手指抬起的时候,将当前x,y坐标记录下来


首先自定义 View 

@SuppressLint("ClickableViewAccessibility")
public class DragView extends View {
	
	private Context mContext;
	
	private int mLastX;//记录x坐标
	private int mLastY;<span style="font-family: Arial, Helvetica, sans-serif;">//记录Y坐标</span>
	private int mOfferX;//x位移差
	private int mOfferY;//y位移差
	
	private Scroller mScroller;

	public DragView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.mContext=context;
		
		initData();
	}
然后 重写onTouch方法:

     

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int currentX = (int) event.getX();
		int currentY = (int) event.getY();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN://在 MotionEvent.ACTION_DOWN 中记录摁下的坐标
             mLastX=currentX;
             mLastY=currentY;
			break;
		case MotionEvent.ACTION_MOVE://在 ACTION_MOVE 后算出 坐标移动差值,重新设置view的位置
            mOfferX=currentX-mLastX;
            mOfferY=currentY-mLastY;
            //当前layout上面添加偏移量
//            //第一种方式:<仅当前控件移动>
            layout(getLeft()+mOfferX, getTop()+mOfferY, getRight()+mOfferX,getBottom()+mOfferY);
//            //第二种方式:<仅当前控件移动>
			offsetLeftAndRight(mOfferX);
			offsetTopAndBottom(mOfferY);
//            //第三种方式:<整个屏幕移动>
            ((View)getParent()).scrollBy(-mOfferX, -mOfferY);//参考系不同,所以mOfferX,mOfferY为负值
			break;
		case MotionEvent.ACTION_UP://更新最后的xy坐标记录
			//重新设置坐标
            mLastX=currentX;
            mLastY=currentY;
			break;
		default:
			break;
		}
		return true;
	}

MotionEvent.ACTION_DOWN 和 MotionEvent.ACTION_UP 方法很简单,就是对down和up时的坐标做个记录,下面主要看move方法
首先看位移差的获取:mOfferX=currentX-mLastX
即是move之后的坐标和move之前的坐标差,y坐标的获取也是一样,此处不述
好,现在来看怎么设置view的新位置,view类有一个方法 layout(int l, int t, int r, int b) 来设置 view的位置
layout(getLeft()+mOfferX, getTop()+mOfferY, getRight()+mOfferX,getBottom()+mOfferY);中就是通过获得view之前的位置坐标,然后加上位移差,获得现在的view坐标位置,然后设置给view即可
下面看第二种方法:
offsetLeftAndRight(mOfferX);
offsetTopAndBottom(mOfferY);
其实是第一种方法设置的封装,代码中只需要传入x方向和y方向的位移差,使调用起来更方便
最后看第三种方式:scrollBy(int x, int y)
scrollBy(int x, int y)也为View的公开方法,从源码中可以看出 scrollBy中传入的 x,y为位移差,即代码中的mOfferX   mOfferY
但并非直接调用scrollBy 方法就行,因为 scrollBy 方法需要 view 的父 容器 调用,故为((View)getParent()).scrollBy();
当然,最让人无语的是 方法一和方法二中mOfferX mOfferY 都是直接用的,为什么到方法三 中这两个值都为负的,原因就是参考系的不同,方法一和二是以 画板为参考系,方法三是以屏幕为参考系,所以为负数,
急需注意的是:方法一和二挪动的是view本身,方法三挪动的却是整个((View)getParent()).!!!
打个简单的例子,如果 一个布局 RelativeLayout中放了 自定义 view 和一个 button,方法一和二执行的时候会只移动 view,而button不动,而方法三移动的是整个>RelativeLayout ,所以方法三执行的时候,view和 button会一起动,这是需要注意的


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值