歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android FlingGallery類完美手勢拖動實現

Android FlingGallery類完美手勢拖動實現

日期:2017/3/1 10:11:00   编辑:Linux編程

網上找了很多關於FlingGallery類拖動的例子,還是很不錯的,但是感覺不是很完美,拖動的只能是界面一致的布局,很不靈活,我覺得如果能夠拖動不同的布局頁面,就是拖動一下換一個頁面布局,那就很完美了,於是我就在原有的基礎上修改了一點點代碼,最終被我給解決了這個問題。下面我就給大家看看我修改後的代碼:

先貼上幾張圖



FlingGalleryActivity.java 實現類:

  1. package com.droidful.flinggallery;
  2. import Android.app.Activity;
  3. import android.content.Context;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.view.MotionEvent;
  7. import android.view.View;
  8. import android.view.View.OnClickListener;
  9. import android.view.ViewGroup;
  10. import android.widget.ArrayAdapter;
  11. import android.widget.CheckBox;
  12. import android.widget.LinearLayout;
  13. import android.widget.TableLayout;
  14. import android.widget.TextView;
  15. import android.widget.Toast;
  16. public class FlingGalleryActivity extends Activity
  17. {
  18. private final String[] mLabelArray = {"View1", "View2", "View3", "View4"};
  19. private FlingGallery mGallery;
  20. private CheckBox mCheckBox;
  21. private TextView t1;
  22. // Note: The following handler is critical to correct function of
  23. // the FlingGallery class. This enables the FlingGallery class to
  24. // detect when the motion event has ended by finger being lifted
  25. @Override
  26. public boolean onTouchEvent(MotionEvent event)
  27. {
  28. return mGallery.onGalleryTouchEvent(event);
  29. }
  30. public void onCreate(Bundle savedInstanceState)
  31. {
  32. super.onCreate(savedInstanceState);
  33. mGallery = new FlingGallery(this);
  34. mGallery.setPaddingWidth(5);
  35. mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, mLabelArray)
  36. {
  37. @Override
  38. public View getView(int position, View convertView, ViewGroup parent)
  39. {
  40. Log.d("msg", "count="+position);
  41. // if (convertView != null && convertView instanceof GalleryViewItem)
  42. // {
  43. // GalleryViewItem galleryView = (GalleryViewItem) convertView;
  44. //
  45. // galleryView.mEdit1.setText("");
  46. // galleryView.mText1.setText(mLabelArray[position]);
  47. // galleryView.mText1.setBackgroundColor(mColorArray[position]);
  48. // galleryView.mText2.setText(mLabelArray[position]);
  49. // galleryView.mText2.setBackgroundColor(mColorArray[position]);
  50. // Log.d("msg", "count="+position);
  51. // return galleryView;
  52. // }
  53. return new GalleryViewItem(getApplicationContext(), position);
  54. }
  55. });
  56. LinearLayout layout = new LinearLayout(getApplicationContext());
  57. layout.setOrientation(LinearLayout.VERTICAL);
  58. LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
  59. LinearLayout.LayoutParams.MATCH_PARENT,
  60. LinearLayout.LayoutParams.MATCH_PARENT);
  61. //layoutParams.setMargins(10, 10, 10, 10);
  62. layoutParams.weight = 1.0f;
  63. layout.addView(mGallery, layoutParams);
  64. mCheckBox = new CheckBox(getApplicationContext());
  65. mCheckBox.setText("Gallery is Circular");
  66. mCheckBox.setPadding(50, 10, 0, 10);
  67. mCheckBox.setTextSize(30);
  68. mCheckBox.setChecked(true);
  69. mCheckBox.setOnClickListener(new OnClickListener()
  70. {
  71. @Override
  72. public void onClick(View view)
  73. {
  74. mGallery.setIsGalleryCircular(mCheckBox.isChecked());
  75. }
  76. });
  77. layout.addView(mCheckBox, new LinearLayout.LayoutParams(
  78. LinearLayout.LayoutParams.MATCH_PARENT,
  79. LinearLayout.LayoutParams.WRAP_CONTENT));
  80. setContentView(layout);
  81. }
  82. private class GalleryViewItem extends TableLayout
  83. {
  84. public GalleryViewItem(Context context, int position)
  85. {
  86. super(context);
  87. this.setOrientation(LinearLayout.VERTICAL);
  88. this.setLayoutParams(new LinearLayout.LayoutParams(
  89. LinearLayout.LayoutParams.WRAP_CONTENT,
  90. LinearLayout.LayoutParams.WRAP_CONTENT));
  91. if(position==0){
  92. View view = (View)getLayoutInflater().inflate(R.layout.main01,null);
  93. //給裡面控件設置事件監聽
  94. t1 = (TextView)view.findViewById(R.id.main_view01);
  95. t1.setOnClickListener(new OnClickListener() {
  96. @Override
  97. public void onClick(View v) {
  98. Toast.makeText(getApplicationContext(), t1.getText().toString(), Toast.LENGTH_SHORT).show();
  99. }
  100. });
  101. this.addView(view,new LinearLayout.LayoutParams(
  102. LinearLayout.LayoutParams.FILL_PARENT,
  103. LinearLayout.LayoutParams.FILL_PARENT));
  104. }else if(position==1){
  105. View view = (View)getLayoutInflater().inflate(R.layout.main02,null);
  106. this.addView(view,new LinearLayout.LayoutParams(
  107. LinearLayout.LayoutParams.FILL_PARENT,
  108. LinearLayout.LayoutParams.FILL_PARENT));
  109. }else if(position==2){
  110. View view = (View)getLayoutInflater().inflate(R.layout.main03,null);
  111. this.addView(view,new LinearLayout.LayoutParams(
  112. LinearLayout.LayoutParams.FILL_PARENT,
  113. LinearLayout.LayoutParams.FILL_PARENT));
  114. }else if(position==3){
  115. View view = (View)getLayoutInflater().inflate(R.layout.main04,null);
  116. this.addView(view,new LinearLayout.LayoutParams(
  117. LinearLayout.LayoutParams.FILL_PARENT,
  118. LinearLayout.LayoutParams.FILL_PARENT));
  119. }
  120. }
  121. }
  122. }

FlingGallery.java 工具類

  1. package com.droidful.flinggallery;
  2. import android.content.Context;
  3. import android.view.GestureDetector;
  4. import android.view.KeyEvent;
  5. import android.view.MotionEvent;
  6. import android.view.View;
  7. import android.view.animation.Animation;
  8. import android.view.animation.AnimationUtils;
  9. import android.view.animation.Interpolator;
  10. import android.view.animation.Transformation;
  11. import android.widget.Adapter;
  12. import android.widget.FrameLayout;
  13. import android.widget.LinearLayout;
  14. // TODO:
  15. // 1. In order to improve performance Cache screen bitmap and use for animation
  16. // 2. Establish superfluous memory allocations and delay or replace with reused objects
  17. // Probably need to make sure we are not allocating objects (strings, etc.) in loops
  18. //為了提高性能,使用緩存屏幕圖動畫
  19. //建立多余的內存分配和延遲或替換為重用對象可能需要確保我們不分配對象(字符串,等等。)在循環
  20. public class FlingGallery extends FrameLayout
  21. {
  22. // Constants 常量
  23. private final int swipe_min_distance = 120;
  24. private final int swipe_max_off_path = 250;
  25. private final int swipe_threshold_veloicty = 400;
  26. // Properties 屬性
  27. private int mViewPaddingWidth = 0;
  28. private int mAnimationDuration = 250;
  29. private float mSnapBorderRatio = 0.5f;
  30. private boolean mIsGalleryCircular = true;
  31. // Members 成員
  32. private int mGalleryWidth = 0;
  33. private boolean mIsTouched = false;
  34. private boolean mIsDragging = false;
  35. private float mCurrentOffset = 0.0f;
  36. private long mScrollTimestamp = 0;
  37. private int mFlingDirection = 0;
  38. private int mCurrentPosition = 0;
  39. private int mCurrentViewNumber = 0;
  40. private Context mContext;
  41. private Adapter mAdapter;
  42. private FlingGalleryView[] mViews;
  43. private FlingGalleryAnimation mAnimation;
  44. private GestureDetector mGestureDetector;
  45. private Interpolator mDecelerateInterpolater;
  46. public FlingGallery(Context context)
  47. {
  48. super(context);
  49. mContext = context;
  50. mAdapter = null;
  51. mViews = new FlingGalleryView[3];
  52. mViews[0] = new FlingGalleryView(0, this);
  53. mViews[1] = new FlingGalleryView(1, this);
  54. mViews[2] = new FlingGalleryView(2, this);
  55. mAnimation = new FlingGalleryAnimation();
  56. mGestureDetector = new GestureDetector(new FlingGestureDetector());
  57. mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext, android.R.anim.decelerate_interpolator);
  58. }
  59. public void setPaddingWidth(int viewPaddingWidth)
  60. {
  61. mViewPaddingWidth = viewPaddingWidth;
  62. }
  63. public void setAnimationDuration(int animationDuration)
  64. {
  65. mAnimationDuration = animationDuration;
  66. }
  67. public void setSnapBorderRatio(float snapBorderRatio)
  68. {
  69. mSnapBorderRatio = snapBorderRatio;
  70. }
  71. public void setIsGalleryCircular(boolean isGalleryCircular)
  72. {
  73. if (mIsGalleryCircular != isGalleryCircular)
  74. {
  75. mIsGalleryCircular = isGalleryCircular;
  76. if (mCurrentPosition == getFirstPosition())
  77. {
  78. // We need to reload the view immediately to the left to change it to circular view or blank
  79. //我們需要重新加載視圖立即到左邊來改變它圓視圖或空白
  80. mViews[getPrevViewNumber(mCurrentViewNumber)].recycleView(getPrevPosition(mCurrentPosition));
  81. }
  82. if (mCurrentPosition == getLastPosition())
  83. {
  84. // We need to reload the view immediately to the right to change it to circular view or blank
  85. //我們需要重新加載視圖立即向右改變它圓視圖或空白
  86. mViews[getNextViewNumber(mCurrentViewNumber)].recycleView(getNextPosition(mCurrentPosition));
  87. }
  88. }
  89. }
  90. public int getGalleryCount()
  91. {
  92. return (mAdapter == null) ? 0 : mAdapter.getCount();
  93. }
  94. public int getFirstPosition()
  95. {
  96. return 0;
  97. }
  98. public int getLastPosition()
  99. {
  100. return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
  101. }
  102. private int getPrevPosition(int relativePosition)
  103. {
  104. int prevPosition = relativePosition - 1;
  105. if (prevPosition < getFirstPosition())
  106. {
  107. prevPosition = getFirstPosition() - 1;
  108. if (mIsGalleryCircular == true)
  109. {
  110. prevPosition = getLastPosition();
  111. }
  112. }
  113. return prevPosition;
  114. }
  115. private int getNextPosition(int relativePosition)
  116. {
  117. int nextPosition = relativePosition + 1;
  118. if (nextPosition > getLastPosition())
  119. {
  120. nextPosition = getLastPosition() + 1;
  121. if (mIsGalleryCircular == true)
  122. {
  123. nextPosition = getFirstPosition();
  124. }
  125. }
  126. return nextPosition;
  127. }
  128. private int getPrevViewNumber(int relativeViewNumber)
  129. {
  130. return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
  131. }
  132. private int getNextViewNumber(int relativeViewNumber)
  133. {
  134. return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
  135. }
  136. @Override
  137. protected void onLayout(boolean changed, int left, int top, int right, int bottom)
  138. {
  139. super.onLayout(changed, left, top, right, bottom);
  140. // Calculate our view width 計算我們的視圖的寬度
  141. mGalleryWidth = right - left;
  142. if (changed == true)
  143. {
  144. // Position views at correct starting offsets 在正確的開始偏移位置的觀點
  145. mViews[0].setOffset(0, 0, mCurrentViewNumber);
  146. mViews[1].setOffset(0, 0, mCurrentViewNumber);
  147. mViews[2].setOffset(0, 0, mCurrentViewNumber);
  148. }
  149. }
  150. public void setAdapter(Adapter adapter)
  151. {
  152. mAdapter = adapter;
  153. mCurrentPosition = 0;
  154. mCurrentViewNumber = 0;
  155. // Load the initial views from adapter 加載初始視圖從適配器
  156. mViews[0].recycleView(mCurrentPosition);
  157. mViews[1].recycleView(getNextPosition(mCurrentPosition));
  158. mViews[2].recycleView(getPrevPosition(mCurrentPosition));
  159. // Position views at correct starting offsets 在正確的開始偏移位置的觀點
  160. mViews[0].setOffset(0, 0, mCurrentViewNumber);
  161. mViews[1].setOffset(0, 0, mCurrentViewNumber);
  162. mViews[2].setOffset(0, 0, mCurrentViewNumber);
  163. }
  164. private int getViewOffset(int viewNumber, int relativeViewNumber)
  165. {
  166. // Determine width including configured padding width 確定寬度包括配置填充寬度
  167. int offsetWidth = mGalleryWidth + mViewPaddingWidth;
  168. // Position the previous view one measured width to left 位置之前的觀點一個測量寬度到左
  169. if (viewNumber == getPrevViewNumber(relativeViewNumber))
  170. {
  171. return offsetWidth;
  172. }
  173. // Position the next view one measured width to the right 位置下一個視圖向右一個測量寬度
  174. if (viewNumber == getNextViewNumber(relativeViewNumber))
  175. {
  176. return offsetWidth * -1;
  177. }
  178. return 0;
  179. }
  180. void movePrevious()
  181. {
  182. // Slide to previous view 滑到上一個視圖
  183. mFlingDirection = 1;
  184. processGesture();
  185. }
  186. void moveNext()
  187. {
  188. // Slide to next view 滑到下一個視圖
  189. mFlingDirection = -1;
  190. processGesture();
  191. }
  192. @Override
  193. public boolean onKeyDown(int keyCode, KeyEvent event)
  194. {
  195. switch (keyCode)
  196. {
  197. case KeyEvent.KEYCODE_DPAD_LEFT:
  198. movePrevious();
  199. return true;
  200. case KeyEvent.KEYCODE_DPAD_RIGHT:
  201. moveNext();
  202. return true;
  203. case KeyEvent.KEYCODE_DPAD_CENTER:
  204. case KeyEvent.KEYCODE_ENTER:
  205. }
  206. return super.onKeyDown(keyCode, event);
  207. }
  208. public boolean onGalleryTouchEvent(MotionEvent event)
  209. {
  210. boolean consumed = mGestureDetector.onTouchEvent(event);
  211. if (event.getAction() == MotionEvent.ACTION_UP)
  212. {
  213. if (mIsTouched || mIsDragging)
  214. {
  215. processScrollSnap();
  216. processGesture();
  217. }
  218. }
  219. return consumed;
  220. }
  221. void processGesture()
  222. {
  223. int newViewNumber = mCurrentViewNumber;
  224. int reloadViewNumber = 0;
  225. int reloadPosition = 0;
  226. mIsTouched = false;
  227. mIsDragging = false;
  228. if (mFlingDirection > 0)
  229. {
  230. if (mCurrentPosition > getFirstPosition() || mIsGalleryCircular == true)
  231. {
  232. // Determine previous view and outgoing view to recycle 確定之前的觀點和外向視圖回收
  233. newViewNumber = getPrevViewNumber(mCurrentViewNumber);
  234. mCurrentPosition = getPrevPosition(mCurrentPosition);
  235. reloadViewNumber = getNextViewNumber(mCurrentViewNumber);
  236. reloadPosition = getPrevPosition(mCurrentPosition);
  237. }
  238. }
  239. if (mFlingDirection < 0)
  240. {
  241. if (mCurrentPosition < getLastPosition() || mIsGalleryCircular == true)
  242. {
  243. // Determine the next view and outgoing view to recycle 確定下一個視圖和外向視圖回收
  244. newViewNumber = getNextViewNumber(mCurrentViewNumber);
  245. mCurrentPosition = getNextPosition(mCurrentPosition);
  246. reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);
  247. reloadPosition = getNextPosition(mCurrentPosition);
  248. }
  249. }
  250. if (newViewNumber != mCurrentViewNumber)
  251. {
  252. mCurrentViewNumber = newViewNumber;
  253. // Reload outgoing view from adapter in new position 重新加載外向視圖從適配器在新位置
  254. mViews[reloadViewNumber].recycleView(reloadPosition);
  255. }
  256. // Ensure input focus on the current view 確保輸入關注當前視圖
  257. mViews[mCurrentViewNumber].requestFocus();
  258. // Run the slide animations for view transitions 運行這個幻燈片動畫視圖轉換
  259. mAnimation.prepareAnimation(mCurrentViewNumber);
  260. this.startAnimation(mAnimation);
  261. // Reset fling state 重置扔狀態
  262. mFlingDirection = 0;
  263. }
  264. void processScrollSnap()
  265. {
  266. // Snap to next view if scrolled passed snap position 對齊到下一個視圖如果滾動通過快速的位置
  267. float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;
  268. int rollOffset = mGalleryWidth - (int) rollEdgeWidth;
  269. int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
  270. if (currentOffset <= rollOffset * -1)
  271. {
  272. // Snap to previous view
  273. mFlingDirection = 1;
  274. }
  275. if (currentOffset >= rollOffset)
  276. {
  277. // Snap to next view
  278. mFlingDirection = -1;
  279. }
  280. }
  281. private class FlingGalleryView
  282. {
  283. private int mViewNumber;
  284. private FrameLayout mParentLayout;
  285. private FrameLayout mInvalidLayout = null;
  286. private LinearLayout mInternalLayout = null;
  287. private View mExternalView = null;
  288. public FlingGalleryView(int viewNumber, FrameLayout parentLayout)
  289. {
  290. mViewNumber = viewNumber;
  291. mParentLayout = parentLayout;
  292. // Invalid layout is used when outside gallery 無效的布局時,使用的是畫廊外
  293. mInvalidLayout = new FrameLayout(mContext);
  294. mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(
  295. LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
  296. // Internal layout is permanent for duration 內部布局是永久的持續時間
  297. mInternalLayout = new LinearLayout(mContext);
  298. mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(
  299. LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
  300. mParentLayout.addView(mInternalLayout);
  301. }
  302. public void recycleView(int newPosition)
  303. {
  304. if (mExternalView != null)
  305. {
  306. mInternalLayout.removeView(mExternalView);
  307. }
  308. if (mAdapter != null)
  309. {
  310. if (newPosition >= getFirstPosition() && newPosition <= getLastPosition())
  311. {
  312. mExternalView = mAdapter.getView(newPosition, mExternalView, mInternalLayout);
  313. }
  314. else
  315. {
  316. mExternalView = mInvalidLayout;
  317. }
  318. }
  319. if (mExternalView != null)
  320. {
  321. mInternalLayout.addView(mExternalView, new LinearLayout.LayoutParams(
  322. LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
  323. }
  324. }
  325. public void setOffset(int xOffset, int yOffset, int relativeViewNumber)
  326. {
  327. // Scroll the target view relative to its own position relative to currently displayed view
  328. //滾動目標視圖相對於自己的位置相對於當前顯示視圖
  329. mInternalLayout.scrollTo(getViewOffset(mViewNumber, relativeViewNumber) + xOffset, yOffset);
  330. }
  331. public int getCurrentOffset()
  332. {
  333. // Return the current scroll position
  334. //返回當前滾動位置
  335. return mInternalLayout.getScrollX();
  336. }
  337. public void requestFocus()
  338. {
  339. mInternalLayout.requestFocus();
  340. }
  341. }
  342. private class FlingGalleryAnimation extends Animation
  343. {
  344. private boolean mIsAnimationInProgres;
  345. private int mRelativeViewNumber;
  346. private int mInitialOffset;
  347. private int mTargetOffset;
  348. private int mTargetDistance;
  349. public FlingGalleryAnimation()
  350. {
  351. mIsAnimationInProgres = false;
  352. mRelativeViewNumber = 0;
  353. mInitialOffset = 0;
  354. mTargetOffset = 0;
  355. mTargetDistance = 0;
  356. }
  357. public void prepareAnimation(int relativeViewNumber)
  358. {
  359. // If we are animating relative to a new view 如果我們是相對於一個新視圖動畫
  360. if (mRelativeViewNumber != relativeViewNumber)
  361. {
  362. if (mIsAnimationInProgres == true)
  363. {
  364. // We only have three views so if requested again to animate in same direction we must snap
  365. int newDirection = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1 : -1;
  366. int animDirection = (mTargetDistance < 0) ? 1 : -1;
  367. // If animation in same direction
  368. if (animDirection == newDirection)
  369. {
  370. // Ran out of time to animate so snap to the target offset
  371. mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
  372. mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
  373. mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);
  374. }
  375. }
  376. // Set relative view number for animation
  377. mRelativeViewNumber = relativeViewNumber;
  378. }
  379. // Note: In this implementation the targetOffset will always be zero
  380. // as we are centering the view; but we include the calculations of
  381. // targetOffset and targetDistance for use in future implementations
  382. mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();
  383. mTargetOffset = getViewOffset(mRelativeViewNumber, mRelativeViewNumber);
  384. mTargetDistance = mTargetOffset - mInitialOffset;
  385. // Configure base animation properties
  386. this.setDuration(mAnimationDuration);
  387. this.setInterpolator(mDecelerateInterpolater);
  388. // Start/continued animation
  389. mIsAnimationInProgres = true;
  390. }
  391. @Override
  392. protected void applyTransformation(float interpolatedTime, Transformation transformation)
  393. {
  394. // Ensure interpolatedTime does not over-shoot then calculate new offset
  395. interpolatedTime = (interpolatedTime > 1.0f) ? 1.0f : interpolatedTime;
  396. int offset = mInitialOffset + (int) (mTargetDistance * interpolatedTime);
  397. for (int viewNumber = 0; viewNumber < 3; viewNumber++)
  398. {
  399. // Only need to animate the visible views as the other view will always be off-screen
  400. if ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber)) ||
  401. (mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber)))
  402. {
  403. mViews[viewNumber].setOffset(offset, 0, mRelativeViewNumber);
  404. }
  405. }
  406. }
  407. @Override
  408. public boolean getTransformation(long currentTime, Transformation outTransformation)
  409. {
  410. if (super.getTransformation(currentTime, outTransformation) == false)
  411. {
  412. // Perform final adjustment to offsets to cleanup animation
  413. mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
  414. mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
  415. mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);
  416. // Reached the animation target
  417. mIsAnimationInProgres = false;
  418. return false;
  419. }
  420. // Cancel if the screen touched
  421. if (mIsTouched || mIsDragging)
  422. {
  423. // Note that at this point we still consider ourselves to be animating
  424. // because we have not yet reached the target offset; its just that the
  425. // user has temporarily interrupted the animation with a touch gesture
  426. return false;
  427. }
  428. return true;
  429. }
  430. }
  431. private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener
  432. {
  433. @Override
  434. public boolean onDown(MotionEvent e)
  435. {
  436. // Stop animation
  437. mIsTouched = true;
  438. // Reset fling state
  439. mFlingDirection = 0;
  440. return true;
  441. }
  442. @Override
  443. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
  444. {
  445. if (e2.getAction() == MotionEvent.ACTION_MOVE)
  446. {
  447. if (mIsDragging == false)
  448. {
  449. // Stop animation
  450. mIsTouched = true;
  451. // Reconfigure scroll
  452. mIsDragging = true;
  453. mFlingDirection = 0;
  454. mScrollTimestamp = System.currentTimeMillis();
  455. mCurrentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
  456. }
  457. float maxVelocity = mGalleryWidth / (mAnimationDuration / 1000.0f);
  458. long timestampDelta = System.currentTimeMillis() - mScrollTimestamp;
  459. float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f);
  460. float currentScrollDelta = e1.getX() - e2.getX();
  461. if (currentScrollDelta < maxScrollDelta * -1) currentScrollDelta = maxScrollDelta * -1;
  462. if (currentScrollDelta > maxScrollDelta) currentScrollDelta = maxScrollDelta;
  463. int scrollOffset = Math.round(mCurrentOffset + currentScrollDelta);
  464. // We can't scroll more than the width of our own frame layout
  465. if (scrollOffset >= mGalleryWidth) scrollOffset = mGalleryWidth;
  466. if (scrollOffset <= mGalleryWidth * -1) scrollOffset = mGalleryWidth * -1;
  467. mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);
  468. mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);
  469. mViews[2].setOffset(scrollOffset, 0, mCurrentViewNumber);
  470. }
  471. return false;
  472. }
  473. @Override
  474. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
  475. {
  476. if (Math.abs(e1.getY() - e2.getY()) <= swipe_max_off_path)
  477. {
  478. if (e2.getX() - e1.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)
  479. {
  480. movePrevious();
  481. }
  482. if(e1.getX() - e2.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)
  483. {
  484. moveNext();
  485. }
  486. }
  487. return false;
  488. }
  489. @Override
  490. public void onLongPress(MotionEvent e)
  491. {
  492. // Finalise scrolling
  493. mFlingDirection = 0;
  494. processGesture();
  495. }
  496. @Override
  497. public void onShowPress(MotionEvent e)
  498. {
  499. }
  500. @Override
  501. public boolean onSingleTapUp(MotionEvent e)
  502. {
  503. // Reset fling state
  504. mFlingDirection = 0;
  505. return false;
  506. }
  507. }
  508. }

main01.xml文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/main"
  4. android:orientation="vertical"
  5. android:layout_width="fill_parent"
  6. android:layout_height="fill_parent"
  7. android:background="#FF9820"
  8. android:gravity="center"
  9. >
  10. <TextView
  11. android:id="@+id/main_view01"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:gravity="center"
  15. android:text="View1"
  16. android:textSize="20dp"
  17. android:textColor="#FFFFFF"
  18. />
  19. </LinearLayout>

main02.xml文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/main"
  4. android:orientation="vertical"
  5. android:layout_width="fill_parent"
  6. android:layout_height="fill_parent"
  7. android:background="#ee4520"
  8. android:gravity="center"
  9. >
  10. <TextView
  11. android:id="@+id/main_view01"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:gravity="center"
  15. android:text="View1"
  16. android:textSize="20dp"
  17. android:textColor="#FFFFFF"
  18. />
  19. </LinearLayout>

main03.xml文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/main"
  4. android:orientation="vertical"
  5. android:layout_width="fill_parent"
  6. android:layout_height="fill_parent"
  7. android:background="#aacc20"
  8. android:gravity="center"
  9. >
  10. <TextView
  11. android:id="@+id/main_view01"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:gravity="center"
  15. android:text="View3"
  16. android:textSize="20dp"
  17. android:textColor="#FFFFFF"
  18. />
  19. </LinearLayout>

main04.xml文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/main"
  4. android:orientation="vertical"
  5. android:layout_width="fill_parent"
  6. android:layout_height="fill_parent"
  7. android:background="#ddeeff"
  8. android:gravity="center"
  9. >
  10. <TextView
  11. android:id="@+id/main_view01"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:gravity="center"
  15. android:text="View4"
  16. android:textSize="20dp"
  17. android:textColor="#FFFFFF"
  18. />
  19. </LinearLayout>

如果大家有更好的解決方法,望大家提出來一起交流!

Copyright © Linux教程網 All Rights Reserved