1.引言
《android群英传》讲滑动效果这块,分析总结的不错,自己学习完后明显觉得很有提高,因此记录下,加深印象。
在博客开始之前,我先说下坐标系的概念。android中有俩个坐标系。一个是手机屏幕左上角。还有一个是视图坐标系。如下图所示:
一个view里面自带一些方法可以获取到自己相对于父容器的坐标,也就是以视图坐标系为坐标系的x,y坐标。下面介绍一些常见的方法:
getTop(): 获取view距离父容器的顶部的距离。
getLeft() :获取view距离父容器的左边的距离
getright() : 获取view到父容器的右边的距离
了解了这些小知识点之后,我们可以动手写一个demo了。主要功能让view跟着我们手的移动而移动。
1.自定义一个view,该view就是一个带有颜色的正方形。这里代码我就不贴了。
2.为view 添加onTouchEventListener方法,监听点击view的动作,主activity的代码如下:
MyView view;
RelativeLayout parent;
int x;
int y;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view=(MyView) findViewById(R.id.myview);
view.setOnTouchListener(this);
parent=(RelativeLayout)view.getParent();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(MainActivity.this, "触摸成功", Toast.LENGTH_SHORT).show();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
x= (int) event.getX();
y= (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
其中x,y是记录按下之后的 坐标。
下面我将介绍3中方式来实现view的拖动:
1.layout方法. 核心思想 就是在滑动的过程中 不断通过layout 来安排view在父容器中的位置。每滑动一下就执行一次,这样总体看起来就是移动,连贯的。 代码如下:
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(MainActivity.this, "触摸成功", Toast.LENGTH_SHORT).show();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
x= (int) event.getX();
y= (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int l=view.getLeft()+(int)(event.getX()-x);
int t=view.getTop()+(int)(event.getY()-y);
view.layout(l,t,l+view.getMeasuredWidth(),t+view.getMeasuredHeight());
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
效果图如下:
view最开始的位置是在 左上角这是我移动指挥的图片。
这里我说下注意的问题:
1.首先重写的onTouch方法 必须返回true,返回true 表示当前这次事件被处理了,假如返回false,或者super.onTouch 表示不处理当前事件。也就不会移动了
2.第二个问题就是:我最开始做的时候想 既然我知道 每次移动的x,y 为什么不用 这个x,y直接调用layout来布局,而非要得到view.left view.top呢? 这是因为你无法根据一个点的移动 来描绘出 view的位置。具体你们可以试试看。还有一点就是event.getx(),view.getleft()获取的距离都是px。
2.通过view 自带的offsetLeftAndRight(offset x)和 offsetTopAndBottom(offset y),通过设置偏移量 来控制view 移动。核心代码如下:
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(MainActivity.this, "触摸成功", Toast.LENGTH_SHORT).show();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
x= (int) event.getX();
y= (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int l=(int)(event.getX()-x);
int t=(int)(event.getY()-y);
view.offsetLeftAndRight(l);
view.offsetTopAndBottom(t);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
核心方法 就是Move方法里面的:offsetLeftAndRight(offset x) 和offsetTopAndBottom(offset y).
3.通过 Layoutparams 来动态改变Margin值来实现。先通过view获取到LayoutParams的值,然后再设置Margin值,就ok了。具体代码实现如下:
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(MainActivity.this, "触摸成功", Toast.LENGTH_SHORT).show();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
x= (int) event.getX();
y= (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int l=(int)(event.getX()-x)+view.getLeft();
int t=(int)(event.getY()-y)+view.getTop();
RelativeLayout.LayoutParams pm= (RelativeLayout.LayoutParams) view.getLayoutParams();
pm.leftMargin=l;
pm.topMargin=t;
view.setLayoutParams(pm);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
实现效果如上图。这几种方式真的很常见,无论是 下拉刷新,还是下拉图片变大,都能见到这几种方法的身影。
下一节 准备写下Scroller类。希望这篇博客能给你带来帮助。希望像我一样菜的人能坚持下去,总有一天我会成为大牛!