歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android FlingGallery類完美手勢拖動實現

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

先貼上幾張圖

        


FlingGalleryActivity.java 實現類:

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

FlingGallery.java 工具類

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

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