自定义View的Demo,这是一个可以拖动的View.
代码
/**
* Created by shixi_tianrui1 on 16-10-5.
* 可以拖动的View
*/
public class DragView extends View {
private static final String TAG = "DragView";
private float mLastX = 0;
private float mLastY = 0;
private int mWidth;
private int mHeight;
private Paint mPaint;
private static final int DEFAULT_WIDTH = 200;
private static final int DEFAULT_HEIGHT = 200;
private static final int DEFAULT_RECT_WIDTH = 100;
private static final int DEFAULT_RECT_HEIGHT = 100;
public DragView(Context context) {
this(context, null);
}
public DragView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(getResources().getColor(R.color.colorPrimary));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 处理wrap_content的情况
int width = resolveSize(DEFAULT_WIDTH, widthMeasureSpec);
int height = resolveSize(DEFAULT_HEIGHT, heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = event.getX();
mLastY = event.getY();
postInvalidate();
return true;
case MotionEvent.ACTION_MOVE:
mLastX = event.getX();
mLastY = event.getY();
postInvalidate();
break;
case MotionEvent.ACTION_UP:
mLastX = event.getX();
mLastY = event.getY();
break;
}
return super.onTouchEvent(event);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int rectWidth = DEFAULT_RECT_WIDTH;
int rectHeight = DEFAULT_RECT_HEIGHT;
Log.d(TAG, "onDraw: mLastX: " + mLastX + " mLastY: " + mLastY);
canvas.drawRect(mLastX, mLastY, rectWidth + mLastX, rectHeight + mLastY, mPaint);
}
}
使用scroll 实现DragView
Android 针对View 提供了scrollBy()
,scrollTo()
者两种滑动方法,但者两种方法均是针对View中的内容进行滑动.
下图中,灰色表示View中的内容区域,移动只是针对内容区域而言.
获取View的父布局,然后进行相对滑动,这样也就实现了滑动的效果
((View) getParent()).scrollBy(-offsetX, -offsetY);
但是使用
// 使View本身开始移动
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
可以针对当前View本身进行滑动
代码
/**
* Created by shixi_tianrui1 on 16-10-5.
* <p>
* 使用ScrollBy实现DragView
*/
public class DragView2 extends View implements View.OnClickListener {
private static final String TAG = "DragView";
private float mLastX;
private float mLastY;
public DragView2(Context context) {
this(context, null);
}
public DragView2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DragView2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setBackgroundColor(getResources().getColor(R.color.colorPrimary));
Log.d(TAG, "DragView2: ");
setOnClickListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int offsetX = (int) (event.getX() - mLastX);
int offsetY = (int) (event.getY() - mLastY);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// 使用父容器向相反的方向移动,即可产生移动效果
// ((View) getParent()).scrollBy(-offsetX, -offsetY);
// 使View本身开始移动
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
case MotionEvent.ACTION_UP:
mLastX = event.getX();
mLastY = event.getY();
break;
}
return super.onTouchEvent(event);
}
@Override
public void onClick(View v) {
Log.d(TAG, "onClick: ");
Toast.makeText(getContext(), "onClick", Toast.LENGTH_SHORT).show();
}
}
ScrollTo ScrollBy 详解
成员变量
mScrollX:表示离视图起始位置的x水平方向的偏移量
mScrollY:表示离视图起始位置的y垂直方向的偏移量
分别通过getScrollX()
和getScrollY()
方法获得。
注意:mScrollX和mScrollY指的并不是坐标,而是偏移量。
scrollTo(int x,int y):
如果偏移位置发生了改变,就会给mScrollX和mScrollY赋新值,改变当前位置。
注意:x,y代表的不是坐标点,而是偏移量。
例如:
我要移动view到坐标点(100,100),那么我的偏移量就是(0,,0) - (100,100) = (-100 ,-100) ,我就要执行view.scrollTo(-100,-100),达到这个效果。
scrollBy(int x,int y):
从源码中看出,它实际上是调用了scrollTo(mScrollX + x, mScrollY + y);
mScrollX + x和mScrollY + y,即表示在原先偏移的基础上在发生偏移,通俗的说就是相对我们当前位置偏移。
根据父类VIEW里面移动,如果移动到了超出的地方,就不会显示。