View的滑动原理和多种滑动方法
参考链接:
http://blog.csdn.net/chunqiuwei/article/details/50679568#
http://blog.csdn.net/zly921112/article/details/50436538
view滑动种类:
1.根据layout()方法来产生滑动
xml代码 (下面的布局也是这个一样的)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <study.view.com.viewstudy.DragView android:id="@+id/dv" android:layout_width="200dp" android:layout_height="200dp" android:background="#000" /> </LinearLayout>
java部分(包含计算出偏移量)
1 package study.view.com.viewstudy;
2
3 import android.content.Context;
4 import android.util.AttributeSet;
5 import android.view.MotionEvent;
6 import android.view.View;
7
8
9 public class DragView extends View {
10
11
12 public DragView(Context context) {
13 this(context, null);
14 }
15
16 public DragView(Context context, AttributeSet attrs) {
17 this(context, attrs, 0);
18 }
19
20 public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
21 super(context, attrs, defStyleAttr);
22 init(context);
23 }
24
25 private void init(Context context) {
26 }
27
28
29 private int startX;
30 private int startY;
31
32 @Override
33 public boolean onTouchEvent(MotionEvent event) {
34 int x = (int) event.getX();//表示相对于当前View的x
35 int y = (int) event.getY();//表示相对于当前View的y
36 switch (event.getAction()) {
37 /**
38 *
39 MotionEvent中的方法
40 getX()获取点击位置距离当前View左边的距离
41 getY()获取点击位置距离当前View上边的距离
42 getRawX()获取点击位置距离屏幕左边的距离
43 getRawY()获取点击位置距离屏幕上边的距离
44 */
45 case MotionEvent.ACTION_DOWN:
46 startX = x;
47 startY = y;
48 break;
49 case MotionEvent.ACTION_MOVE:
50 int distanceX = x - startX;
51 int distanceY = y - startY;
52 /**
53 layout()中的方法
54 getTop()获取到的是View自身顶边到父布局顶边的距离
55 getBottom()获取到的是View自身底边到父布局顶边的距离
56 getLeft()获取到的是View自身左边到父布局左边的距离
57 getRight()获取到的是View自身右边到父布局左边的距离
58 */
59 layout(
60 getLeft()+distanceX,
61 getTop()+distanceY,
62 getRight()+distanceX,
63 getBottom()+distanceY
64 );
65 break;
66 case MotionEvent.ACTION_UP:
67
68
69 break;
70 }
71 return true;
72 }
73
74
75 }
2.offsetLeftAndRight(),offsetTopAndBottom()实现
计算出偏移量后只需要下面代码即可
offsetLeftAndRight(distanceX);
offsetTopAndBottom(distanceY);
3.view本身是不滑动的,滑动的是view的内容。view利用其view类内自带的方法scrollTo和ScrollBy来实现滑动
scrollTo()移动到某点,scrollBy()移动的偏移量 (把View位置看成固定的,内容移动,并且他的坐标系正好跟我们平时的坐标系相反)
1 public void scrollTo(int x, int y) { 2 if (mScrollX != x || mScrollY != y) { 3 int oldX = mScrollX; 4 int oldY = mScrollY; 5 //记录滑动的位置 6 mScrollX = x; 7 mScrollY = y; 8 invalidateParentCaches(); 9 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 10 if (!awakenScrollBars()) { 11 postInvalidateOnAnimation(); 12 } 13 } 14 } 15 16 public void scrollBy(int x, int y) { 17 scrollTo(mScrollX + x, mScrollY + y);
java部分
1 package study.view.com.viewstudy; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.MotionEvent; 6 import android.view.View; 7 8 9 public class DragView extends View { 10 11 12 public DragView(Context context) { 13 this(context, null); 14 } 15 16 public DragView(Context context, AttributeSet attrs) { 17 this(context, attrs, 0); 18 } 19 20 public DragView(Context context, AttributeSet attrs, int defStyleAttr) { 21 super(context, attrs, defStyleAttr); 22 init(context); 23 } 24 25 private void init(Context context) { 26 } 27 28 29 private int startX; 30 private int startY; 31 32 @Override 33 public boolean onTouchEvent(MotionEvent event) { 34 int x = (int) event.getX();//表示相对于当前View的x 35 int y = (int) event.getY();//表示相对于当前View的y 36 switch (event.getAction()) { 37 /** 38 * 39 MotionEvent中的方法 40 getX()获取点击位置距离当前View左边的距离 41 getY()获取点击位置距离当前View上边的距离 42 getRawX()获取点击位置距离屏幕左边的距离 43 getRawY()获取点击位置距离屏幕上边的距离 44 */ 45 case MotionEvent.ACTION_DOWN: 46 startX = x; 47 startY = y; 48 break; 49 case MotionEvent.ACTION_MOVE: 50 int distanceX = x - startX; 51 int distanceY = y - startY; 52 //修改的地方 53 ((View)getParent()).scrollBy(-distanceX,-distanceY); 54 break; 55 case MotionEvent.ACTION_UP: 56 57 58 break; 59 } 60 return true; 61 } 62 63 64 }
4.利用动画,让view产生滑动效果
java代码部分
1 package study.view.com.viewstudy; 2 3 import android.animation.ObjectAnimator; 4 import android.support.v7.app.AppCompatActivity; 5 import android.os.Bundle; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.TextView; 9 10 public class MainActivity extends AppCompatActivity { 11 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.activity_main); 16 17 Button bt = (Button) findViewById(R.id.bt); 18 final TextView tv = (TextView) findViewById(R.id.tv); 19 bt.setOnClickListener(new View.OnClickListener() { 20 @Override 21 public void onClick(View v) { 22 ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv,"translationX",300); 23 objectAnimator.setDuration(2000).start(); 24 25 26 } 27 }); 28 } 29 }
xml部分
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:gravity="center" 7 android:orientation="vertical" 8 tools:context=".MainActivity"> 9 10 <TextView 11 android:id="@+id/tv" 12 android:layout_width="200dp" 13 android:layout_height="200dp" 14 android:background="#f00" /> 15 16 <Button 17 android:id="@+id/bt" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:text="点我" /> 21 22 </LinearLayout>
5.通过动态的修改LayoutParams的margin等属性让View来产生滑动
计算出偏移量(下面有计算代码)
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams(); lp.topMargin = getTop()+distanceY; lp.leftMargin = getLeft() + distanceX; setLayoutParams(lp);
6.Scroller实现(Scroller是将一次较长的滑动,按一定时间分成多次较小的滑动实现视觉上的弹性滑动)
基于上面代码
1 package study.view.com.viewstudy; 2 3 import android.annotation.SuppressLint; 4 import android.content.Context; 5 import android.util.AttributeSet; 6 import android.view.MotionEvent; 7 import android.view.View; 8 import android.widget.Scroller; 9 import android.widget.TextView; 10 11 12 @SuppressLint("AppCompatCustomView") 13 public class DragView extends TextView { 14 15 16 private Scroller scroller; 17 18 public DragView(Context context) { 19 this(context, null); 20 } 21 22 public DragView(Context context, AttributeSet attrs) { 23 this(context, attrs, 0); 24 } 25 26 public DragView(Context context, AttributeSet attrs, int defStyleAttr) { 27 super(context, attrs, defStyleAttr); 28 init(context); 29 } 30 31 private void init(Context context) { 32 scroller = new Scroller(context); 33 } 34 35 @Override 36 public void computeScroll() { 37 super.computeScroll(); 38 if(scroller.computeScrollOffset()){ 39 ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY()); 40 invalidate();//这里不断的递归修改坐标形成视觉上的弹性滑动 41 } 42 } 43 44 private int startX; 45 private int startY; 46 47 @Override 48 public boolean onTouchEvent(MotionEvent event) { 49 int x = (int) event.getX();//表示相对于当前view的x 50 int y = (int) event.getY(); 51 switch (event.getAction()) { 52 case MotionEvent.ACTION_DOWN: 53 startX = x; 54 startY = y; 55 break; 56 case MotionEvent.ACTION_MOVE: 57 int distanceX = x - startX; 58 int distanceY = y - startY; 59 ((View)getParent()).scrollBy(-distanceX, -distanceY); 60 61 62 63 break; 64 case MotionEvent.ACTION_UP: 65 View parent = (View) getParent(); 66 scroller.startScroll( 67 parent.getScrollX(), 68 parent.getScrollY(), 69 -parent.getScrollX(), 70 -parent.getScrollY()); 71 invalidate();//这里调用了就会触发ondraw()然后会调用computeScroll()方法 72 break; 73 } 74 return true; 75 } 76 77 78 }