任何app无论功能的多少,最终都会落实到与用户交互上,在这里咱们就一起去看看与用户交互最深切感受的滑动。
滑动无非就是view自己在parent中的移动,再者就是parent移动(view形式上的滑动,其实只是隐形的欺骗了一下用户的眼睛)。这里谈到友好交互,就不再大批量的文字让你看的作呕。
一:view自己滑动
1.设置margin
public class LayoutParamsSSS extends LinearLayout {
public LayoutParamsSSS(Context context) {
this(context, null, 0);
}
public LayoutParamsSSS(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LayoutParamsSSS(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed,l,t,r,b);
}
private int lastX;
private int lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
//设置它的LayoutParams(这里用了一个巧方式,因为任何ViewGroup都有MarginLayoutParams)
ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
// setLayoutParams(layoutParams);//和requestLayout()方法一样
requestLayout();
//重新设置初始坐标
lastX = rawX;
lastY = rawY;
break;
}
return super.onTouchEvent(event);
}
}
2.设置layout
//在当前left、top、right、bottom的基础上加上偏移量
layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom() + offsetY);
3.设置View所在矩阵Rect
//设置X和Y上的偏移量
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
4.使用属性动画
public class AnimatorSSS extends View {
private Scroller mScroller;
public AnimatorSSS(Context context) {
this(context, null, 0);
}
public AnimatorSSS(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AnimatorSSS(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScroller = new Scroller(context, new BounceInterpolator());
}
private float lastX = 0;
private float lastY = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
float firstX = event.getRawX();
float firstY = event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
ViewHelper.setTranslationX(this, ViewHelper.getTranslationX(this) + firstX - lastX);
ViewHelper.setTranslationY(this, ViewHelper.getTranslationY(this) + firstY - lastY);
break;
case MotionEvent.ACTION_UP:
smoothScrollTo(100, 100);
break;
default:
break;
}
lastX = firstX;
lastY = firstY;
return super.onTouchEvent(event);
}
private int lastTranslationX = 0;
private int lastTranslationY = 0;
private void smoothScrollTo(int desX, int desY) {
mScroller.startScroll(lastTranslationX - desX, lastTranslationY - desY, (int) ViewHelper
.getTranslationX(this) - lastTranslationX, (int) ViewHelper.getTranslationY(this) -
lastTranslationY);
lastTranslationX = (int) ViewHelper.getTranslationX(this);
lastTranslationY = (int) ViewHelper.getTranslationY(this);
invalidate();
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
}
二:parent移动
1.scrollTo和scrollBy
public class ScrollBySSS extends LinearLayout {
public ScrollBySSS(Context context) {
this(context, null, 0);
}
public ScrollBySSS(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollBySSS(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed,l,t,r,b);
((View)getParent()).getLocationOnScreen(mm);
}
private int[] mm = new int[2];
// private int lastX;
// private int lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
// lastX = rawX;
// lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
// int offsetX = rawX - lastX;
// int offsetY = rawY - lastY;
//设置它的LayoutParams(这里用了一个巧方式,因为任何ViewGroup都有MarginLayoutParams)
// ((View)getParent()).scrollBy(-offsetX,-offsetY);
((View)getParent()).scrollTo(-rawX + mm[0], -rawY + mm[1]);
//重新设置初始坐标
// lastX = rawX;
// lastY = rawY;
break;
}
return super.onTouchEvent(event);
}
}
2.scroller类
public class ScrollerSSS extends LinearLayout {
private Scroller mScroller;
public ScrollerSSS(Context context) {
this(context, null, 0);
}
public ScrollerSSS(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollerSSS(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScroller = new Scroller(context,new BounceInterpolator());
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
private int lastX;
private int lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
((View)getParent()).scrollBy(-offsetX,-offsetY);
//重新设置初始坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_UP:
//手指离开,回弹
View parent = (View) getParent();
mScroller.startScroll(parent.getScrollX(),parent.getScrollY(),-parent.getScrollX(),-parent.getScrollY(),1000);
invalidate();
break;
}
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
//判断Scroller是否执行完毕
if (mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
//通过重绘来不断调用computeScroll
invalidate();
}
}
}
ok了,暂时就这么多,坐标还真难调!!!!!!!!!!