1. 程式人生 > >左右頁面滑動

左右頁面滑動

velocity lns xtend tap utf nis desc cells context

前言

通過左右滑動屏幕來切換頁面,有4種方式:

(0) 使用ScrollLayout;

(1) 使用動畫;

(2) Activity 實現 OnTouchListener 和 OnGestureListener 接口;

(3) 使用 ViewPager;

本文將對上述各個方式逐一介紹。

(0)使用ScrollLayout

將scrolllayout 的布局方向設置為水平,當layout的水平尺寸大於手機屏幕時,即可實現左右滑動效果。有1款叫做 do it tomorrow 的應用,就是典型的代表。解壓後可以看到,其背景圖片其實是1張1280x960的圖片(如下圖),隱藏滾動條,即有水平滑動的效果。

技術分享

(1)使用動畫

這裏的動畫是指,使用Activity 中的 overridePendingTransition(,) 方法,具體能實現的動畫效果如下表:

動畫效果列表
淡入淡出效果 overridePendingTransition(R.anim.fade, R.anim.hold);
放大淡出效果 overridePendingTransition(R.anim.my_scale_action,R.anim.my_alpha_action);
轉動淡出效果 overridePendingTransition(R.anim.scale_rotate,R.anim.my_alpha_action);
轉動淡出效果 overridePendingTransition(R.anim.scale_translate_rotate,R.anim.my_alpha_action);
左上角展開淡出效果 overridePendingTransition(R.anim.scale_translate,R.anim.my_alpha_action);
壓縮變小淡出效果 overridePendingTransition(R.anim.hyperspace_in,R.anim.hyperspace_out);
右往左推出效果 overridePendingTransition(R.anim.push_left_in,R.anim.push_left_out);
下往上推出效果 overridePendingTransition(R.anim.push_up_in,R.anim.push_up_out);
左右交錯效果 overridePendingTransition(R.anim.slide_left,R.anim.slide_right);
放大淡出效果 overridePendingTransition(R.anim.wave_scale,R.anim.my_alpha_action);
縮小效果 overridePendingTransition(R.anim.zoom_enter,R.anim.zoom_exit);
上下交錯效果 overridePendingTransition(R.anim.slide_up_in,R.anim.slide_down_out);

我們以“右往左推出效果”為例,其中R.anim.slide_left 和 R.anim.slide_right 文件分別如下:

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <set xmlns:android="http://schemas.android.com/apk/res/android" >
  3. <translate android:fromXDelta="0%p" android:toXDelta="-100%p"
  4. android:duration="500" />
  5. </set>

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <set xmlns:android="http://schemas.android.com/apk/res/android" >
  3. <translate android:fromXDelta="100%p" android:toXDelta="0%p"
  4. android:duration="500" />
  5. </set>

上述xml文件中,有3個值需要解釋:fromXDelta 是指頁面滑動的起點,toXDelta 是指頁面滑動的終點,duration 是指滑動耗時,單位為毫秒(1/1000 秒)。可以實現AnimLeftActivity 和 AnimRightActivity 之間的左右滑動。具體手機屏幕和 x 軸、y 軸的關系見下圖:

技術分享


public class AnimLeftActivity extends Activity {

[java] view plain copy
  1. private Button btnStart = null;
  2. @Override
  3. public void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. // 移除Title
  6. requestWindowFeature(Window.FEATURE_NO_TITLE);
  7. setContentView(R.layout.left_layout);
  8. // 開始按鈕
  9. btnStart = (Button) findViewById(R.id.btn_anim_left);
  10. /**
  11. * 開始測試按鈕 的監聽函數
  12. *
  13. * */
  14. btnStart.setOnClickListener(new View.OnClickListener() {
  15. public void onClick(View view) {
  16. Intent i = new Intent(getApplicationContext(), AnimRightActivity.class);
  17. startActivity(i);
  18. // 設置切換動畫,從右邊進入,左邊退出
  19. overridePendingTransition(R.anim.right_activity_enter_from_right, R.anim.left_activity_out_to_left);
  20. finish();
  21. }
  22. );
  23. }
[java] view plain copy
  1. public class AnimRightActivity extends Activity {
  2. private Button btnStart = null;
  3. public void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. // 移除Title
  6. requestWindowFeature(Window.FEATURE_NO_TITLE);
  7. setContentView(R.layout.right_layout);
  8. // 開始按鈕
  9. btnStart = (Button) findViewById(R.id.btn_anim_right);
  10. /**
  11. * 開始測試按鈕 的監聽函數
  12. *
  13. * */
  14. btnStart.setOnClickListener(new View.OnClickListener() {
  15. public void onClick(View view) {
  16. Intent i = new Intent(getApplicationContext(), AnimLeftActivity.class);
  17. startActivity(i);
  18. // 設置切換動畫,從右邊進入,左邊退出
  19. overridePendingTransition(R.anim.left_activity_enter_from_left, R.anim.right_activity_out_to_left);
  20. finish(); }
  21. });
  22. }
  23. }

(2)Activity 實現 OnTouchListener 和 OnGestureListener 接口

[java] view plain copy
  1. public class GestureLeftActivity extends Activity implements OnTouchListener, OnGestureListener {
  2. // 按鈕
  3. private Button btnStart = null;
  4. // 監聽左劃動作
  5. private RelativeLayout rlLeft = null;
  6. private GestureDetector gd = null;
  7. // 最小的水平有效劃動距離和速度,超過該距離和速度才觸發劃動事件
  8. private int slideMinDistance = 20;
  9. private int slideMinVelocity = 0;
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. // 移除Title
  14. requestWindowFeature(Window.FEATURE_NO_TITLE);
  15. setContentView(R.layout.left_layout);
  16. btnStart = (Button) findViewById(R.id.btn_anim_left);
  17. btnStart.setText("");
  18. btnStart.setOnClickListener(new View.OnClickListener() {
  19. public void onClick(View v) {
  20. Toast.makeText(GestureLeftActivity.this, "請向左滑動", Toast.LENGTH_SHORT).show();
  21. }
  22. });
  23. // 處理左劃事件
  24. gd = new GestureDetector((OnGestureListener) this);
  25. rlLeft = (RelativeLayout) findViewById(R.id.rl_left);
  26. rlLeft.setOnTouchListener(this);
  27. rlLeft.setLongClickable(true);
  28. }
  29. /**
  30. * 滑動到手寫頁面
  31. * @Title: slideToAnalyser
  32. * @Description: TODO
  33. * @param
  34. * @return void
  35. * @throws
  36. */
  37. private void slideToGestureRightActivity() {
  38. Intent i = new Intent(getApplicationContext(), GestureRightActivity.class);
  39. startActivity(i);
  40. // 設置切換動畫,從右邊進入,左邊退出
  41. overridePendingTransition(R.anim.right_activity_enter_from_right, R.anim.left_activity_out_to_left);
  42. finish();
  43. }
  44. /*
  45. * <p>Title: onDown</p>
  46. * <p>Description: </p>
  47. * @param arg0
  48. * @return
  49. * @see android.view.GestureDetector.OnGestureListener#onDown(android.view.MotionEvent)
  50. */
  51. public boolean onDown(MotionEvent arg0) {
  52. // TODO Auto-generated method stub
  53. return false;
  54. }
  55. /*
  56. * <p>Title: onFling</p>
  57. * <p>Description: </p>
  58. * @param e1
  59. * @param e2
  60. * @param velocityX
  61. * @param velocityY
  62. * @return
  63. * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)
  64. */
  65. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  66. if (((e1.getX() - e2.getX()) > slideMinDistance) && Math.abs(velocityX) > slideMinVelocity) {
  67. // 切換Activity
  68. slideToGestureRightActivity();
  69. Toast.makeText(this, "向左手勢", Toast.LENGTH_SHORT).show();
  70. } else if (e2.getX() - e1.getX() > slideMinDistance && Math.abs(velocityX) > slideMinVelocity) {
  71. // 切換Activity
  72. // Intent intent = new Intent(ViewSnsActivity.this, UpdateStatusActivity.class);
  73. // startActivity(intent);
  74. Toast.makeText(this, "向右手勢", Toast.LENGTH_SHORT).show();
  75. }
  76. return false;
  77. }
  78. /*
  79. * <p>Title: onLongPress</p>
  80. * <p>Description: </p>
  81. * @param e
  82. * @see android.view.GestureDetector.OnGestureListener#onLongPress(android.view.MotionEvent)
  83. */
  84. public void onLongPress(MotionEvent e) {
  85. // TODO Auto-generated method stub
  86. }
  87. /*
  88. * <p>Title: onScroll</p>
  89. * <p>Description: </p>
  90. * @param e1
  91. * @param e2
  92. * @param distanceX
  93. * @param distanceY
  94. * @return
  95. * @see android.view.GestureDetector.OnGestureListener#onScroll(android.view.MotionEvent, android.view.MotionEvent, float, float)
  96. */
  97. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  98. // TODO Auto-generated method stub
  99. return false;
  100. }
  101. /*
  102. * <p>Title: onShowPress</p>
  103. * <p>Description: </p>
  104. * @param e
  105. * @see android.view.GestureDetector.OnGestureListener#onShowPress(android.view.MotionEvent)
  106. */
  107. public void onShowPress(MotionEvent e) {
  108. // TODO Auto-generated method stub
  109. }
  110. /*
  111. * <p>Title: onSingleTapUp</p>
  112. * <p>Description: </p>
  113. * @param e
  114. * @return
  115. * @see android.view.GestureDetector.OnGestureListener#onSingleTapUp(android.view.MotionEvent)
  116. */
  117. public boolean onSingleTapUp(MotionEvent e) {
  118. // TODO Auto-generated method stub
  119. return false;
  120. }
  121. /*
  122. * <p>Title: onTouch</p>
  123. * <p>Description: </p>
  124. * @param v
  125. * @param event
  126. * @return
  127. * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
  128. */
  129. public boolean onTouch(View v, MotionEvent event) {
  130. // TODO Auto-generated method stub
  131. return gd.onTouchEvent(event);
  132. }
  133. public boolean dispatchTouchEvent(MotionEvent ev) {
  134. gd.onTouchEvent(ev);
  135. // scroll.onTouchEvent(ev);
  136. return super.dispatchTouchEvent(ev);
  137. }
  138. }


[java] view plain copy
  1. public class GestureRightActivity extends Activity implements OnTouchListener, OnGestureListener {
  2. // 按鈕
  3. private Button btnStart = null;
  4. // 監聽左劃動作
  5. private RelativeLayout rlRight = null;
  6. private GestureDetector gd = null;
  7. // 最小的水平有效劃動距離和速度,超過該距離和速度才觸發劃動事件
  8. private int slideMinDistance = 20;
  9. private int slideMinVelocity = 0;
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. // 移除Title
  14. requestWindowFeature(Window.FEATURE_NO_TITLE);
  15. setContentView(R.layout.right_layout);
  16. btnStart = (Button) findViewById(R.id.btn_anim_right);
  17. btnStart.setText("");
  18. btnStart.setOnClickListener(new View.OnClickListener() {
  19. public void onClick(View v) {
  20. Toast.makeText(GestureRightActivity.this, "請向右滑動", Toast.LENGTH_SHORT).show();
  21. }
  22. });
  23. // 處理左劃事件
  24. gd = new GestureDetector((OnGestureListener) this);
  25. rlRight = (RelativeLayout) findViewById(R.id.rl_right);
  26. rlRight.setOnTouchListener(this);
  27. rlRight.setLongClickable(true);
  28. }
  29. /**
  30. * 滑動到手寫頁面
  31. * @Title: slideToAnalyser
  32. * @Description: TODO
  33. * @param
  34. * @return void
  35. * @throws
  36. */
  37. private void slideToGestureLeftActivity() {
  38. Intent i = new Intent(getApplicationContext(), GestureLeftActivity.class);
  39. startActivity(i);
  40. // 設置切換動畫,從右邊進入,左邊退出
  41. overridePendingTransition(R.anim.left_activity_enter_from_left, R.anim.right_activity_out_to_left);
  42. finish();
  43. }
  44. /*
  45. * <p>Title: onDown</p>
  46. * <p>Description: </p>
  47. * @param arg0
  48. * @return
  49. * @see android.view.GestureDetector.OnGestureListener#onDown(android.view.MotionEvent)
  50. */
  51. public boolean onDown(MotionEvent arg0) {
  52. // TODO Auto-generated method stub
  53. return false;
  54. }
  55. /*
  56. * <p>Title: onFling</p>
  57. * <p>Description: </p>
  58. * @param e1
  59. * @param e2
  60. * @param velocityX
  61. * @param velocityY
  62. * @return
  63. * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)
  64. */
  65. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  66. if (((e1.getX() - e2.getX()) > slideMinDistance) && Math.abs(velocityX) > slideMinVelocity) {
  67. Toast.makeText(this, "向左手勢", Toast.LENGTH_SHORT).show();
  68. } else if (e2.getX() - e1.getX() > slideMinDistance && Math.abs(velocityX) > slideMinVelocity) {
  69. // 切換Activity
  70. slideToGestureLeftActivity();
  71. Toast.makeText(this, "向右手勢", Toast.LENGTH_SHORT).show();
  72. }
  73. return false;
  74. }
  75. /*
  76. * <p>Title: onLongPress</p>
  77. * <p>Description: </p>
  78. * @param e
  79. * @see android.view.GestureDetector.OnGestureListener#onLongPress(android.view.MotionEvent)
  80. */
  81. public void onLongPress(MotionEvent e) {
  82. // TODO Auto-generated method stub
  83. }
  84. /*
  85. * <p>Title: onScroll</p>
  86. * <p>Description: </p>
  87. * @param e1
  88. * @param e2
  89. * @param distanceX
  90. * @param distanceY
  91. * @return
  92. * @see android.view.GestureDetector.OnGestureListener#onScroll(android.view.MotionEvent, android.view.MotionEvent, float, float)
  93. */
  94. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  95. // TODO Auto-generated method stub
  96. return false;
  97. }
  98. /*
  99. * <p>Title: onShowPress</p>
  100. * <p>Description: </p>
  101. * @param e
  102. * @see android.view.GestureDetector.OnGestureListener#onShowPress(android.view.MotionEvent)
  103. */
  104. public void onShowPress(MotionEvent e) {
  105. // TODO Auto-generated method stub
  106. }
  107. /*
  108. * <p>Title: onSingleTapUp</p>
  109. * <p>Description: </p>
  110. * @param e
  111. * @return
  112. * @see android.view.GestureDetector.OnGestureListener#onSingleTapUp(android.view.MotionEvent)
  113. */
  114. public boolean onSingleTapUp(MotionEvent e) {
  115. // TODO Auto-generated method stub
  116. return false;
  117. }
  118. /*
  119. * <p>Title: onTouch</p>
  120. * <p>Description: </p>
  121. * @param v
  122. * @param event
  123. * @return
  124. * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
  125. */
  126. public boolean onTouch(View v, MotionEvent event) {
  127. // TODO Auto-generated method stub
  128. return gd.onTouchEvent(event);
  129. }
  130. public boolean dispatchTouchEvent(MotionEvent ev) {
  131. gd.onTouchEvent(ev);
  132. // scroll.onTouchEvent(ev);
  133. return super.dispatchTouchEvent(ev);
  134. }
  135. }


(3)使用 ViewPager

左右頁面滑動