zoukankan      html  css  js  c++  java
  • android仿UC墨迹天气左右拖动效果

    http://www.oschina.net/code/snippet_16_2541

    (另)http://www.eoeandroid.com/thread-48286-1-1.html(带附件)

    [代码] FlingGalleryActivity

    001 import android.app.Activity;
    002 import android.os.Bundle;
    003  
    004 import android.content.Context;
    005 import android.graphics.Color;
    006 import android.util.Log;
    007 import android.view.Gravity;
    008 import android.view.MotionEvent;
    009 import android.view.View;
    010 import android.view.ViewGroup;
    011 import android.view.View.OnClickListener;
    012 import android.widget.ArrayAdapter;
    013 import android.widget.Button;
    014 import android.widget.CheckBox;
    015 import android.widget.EditText;
    016 import android.widget.LinearLayout;
    017 import android.widget.TableLayout;
    018 import android.widget.TextView;
    019  
    020 public class FlingGalleryActivity extends Activity
    021 {
    022     private final int color_red = Color.argb(100, 200, 0, 0);
    023     private final int color_green = Color.argb(100, 0, 200, 0);
    024     private final int color_blue = Color.argb(100, 0, 0, 200);
    025     private final int color_yellow = Color.argb(100, 200, 200, 0);
    026     private final int color_purple = Color.argb(100, 200, 0, 200);
    027  
    028     private final String[] mLabelArray = {"View1", "View2", "View3", "View4", "View5"};
    029     private final int[] mColorArray = {color_red, color_green, color_blue, color_yellow, color_purple};
    030  
    031     private FlingGallery mGallery;
    032     private CheckBox mCheckBox;
    033  
    034     // Note: The following handler is critical to correct function of
    035     // the FlingGallery class. This enables the FlingGallery class to
    036     // detect when the motion event has ended by finger being lifted
    037  
    038     @Override
    039     public boolean onTouchEvent(MotionEvent event)
    040     {
    041         return mGallery.onGalleryTouchEvent(event);
    042     }
    043  
    044     public void onCreate(Bundle savedInstanceState)
    045     {
    046         super.onCreate(savedInstanceState);
    047  
    048         mGallery = new FlingGallery(this);
    049         mGallery.setPaddingWidth(5);
    050         mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, mLabelArray)
    051         {
    052             @Override
    053             public View getView(int position, View convertView, ViewGroup parent)
    054             {
    055                 Log.d("111", "count="+position);
    056 //              if (convertView != null && convertView instanceof GalleryViewItem)
    057 //                {
    058 //                  GalleryViewItem galleryView = (GalleryViewItem) convertView;
    059 //
    060 //                  galleryView.mEdit1.setText("");
    061 //                  galleryView.mText1.setText(mLabelArray[position]);
    062 //                  galleryView.mText1.setBackgroundColor(mColorArray[position]);
    063 //                  galleryView.mText2.setText(mLabelArray[position]);
    064 //                  galleryView.mText2.setBackgroundColor(mColorArray[position]);
    065 //                 
    066 //                  Log.d("111", "count="+position);
    067 //                 
    068 //                  return galleryView;
    069 //                 
    070 //                }
    071                  
    072                 return new GalleryViewItem(getApplicationContext(), position);
    073             }
    074         });
    075  
    076         LinearLayout layout = new LinearLayout(getApplicationContext());
    077         layout.setOrientation(LinearLayout.VERTICAL);
    078  
    079         LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    080                 LinearLayout.LayoutParams.MATCH_PARENT,
    081                 LinearLayout.LayoutParams.MATCH_PARENT);
    082  
    083         layoutParams.setMargins(10, 10, 10, 10);
    084         layoutParams.weight = 1.0f;
    085    
    086         layout.addView(mGallery, layoutParams);
    087          
    088         mCheckBox = new CheckBox(getApplicationContext());
    089         mCheckBox.setText("Gallery is Circular");
    090         mCheckBox.setText("Gallery is Circular");
    091         mCheckBox.setPadding(50, 10, 0, 10);
    092         mCheckBox.setTextSize(30);
    093         mCheckBox.setChecked(true);
    094         mCheckBox.setOnClickListener(new OnClickListener()
    095         {
    096             @Override
    097             public void onClick(View view)
    098             {
    099                 mGallery.setIsGalleryCircular(mCheckBox.isChecked());
    100             }
    101         });
    102  
    103         layout.addView(mCheckBox, new LinearLayout.LayoutParams(
    104                 LinearLayout.LayoutParams.MATCH_PARENT,
    105                 LinearLayout.LayoutParams.WRAP_CONTENT));
    106          
    107         setContentView(layout);
    108     }  
    109  
    110     private class GalleryViewItem extends TableLayout
    111     {
    112         private EditText mEdit1;
    113         private TextView mText1;
    114         private TextView mText2;
    115         private Button mButton1;
    116         private Button mButton2;
    117  
    118         public GalleryViewItem(Context context, int position)
    119         {
    120             super(context);
    121  
    122             this.setOrientation(LinearLayout.VERTICAL);
    123  
    124             this.setLayoutParams(new LinearLayout.LayoutParams(
    125                     LinearLayout.LayoutParams.MATCH_PARENT,
    126                     LinearLayout.LayoutParams.MATCH_PARENT));
    127              
    128             mEdit1 = new EditText(context);
    129  
    130             this.addView(mEdit1, new LinearLayout.LayoutParams(
    131                     LinearLayout.LayoutParams.MATCH_PARENT,
    132                     LinearLayout.LayoutParams.WRAP_CONTENT));
    133  
    134             mText1 = new TextView(context);
    135             mText1.setText(mLabelArray[position]);
    136             mText1.setTextSize(30);
    137             mText1.setGravity(Gravity.LEFT);
    138             mText1.setBackgroundColor(mColorArray[position]);
    139  
    140             this.addView(mText1, new LinearLayout.LayoutParams(
    141                     LinearLayout.LayoutParams.MATCH_PARENT,
    142                     LinearLayout.LayoutParams.WRAP_CONTENT));
    143  
    144             mButton1 = new Button(context);
    145             mButton1.setText("<<");
    146             mButton1.setGravity(Gravity.LEFT);
    147             mButton1.setOnClickListener(new OnClickListener()
    148             {
    149                 @Override
    150                 public void onClick(View view)
    151                 {
    152                     mGallery.movePrevious();
    153                 }
    154             });
    155              
    156             this.addView(mButton1, new LinearLayout.LayoutParams(
    157                     LinearLayout.LayoutParams.MATCH_PARENT,
    158                     LinearLayout.LayoutParams.WRAP_CONTENT));
    159  
    160             mButton2 = new Button(context);
    161             mButton2.setText(">>");
    162             mButton2.setGravity(Gravity.RIGHT);
    163             mButton2.setOnClickListener(new OnClickListener()
    164             {
    165                 @Override
    166                 public void onClick(View view)
    167                 {
    168                     mGallery.moveNext();
    169                 }
    170             });
    171              
    172             this.addView(mButton2, new LinearLayout.LayoutParams(
    173                     LinearLayout.LayoutParams.MATCH_PARENT,
    174                     LinearLayout.LayoutParams.WRAP_CONTENT));
    175  
    176             mText2 = new TextView(context);
    177             mText2.setText(mLabelArray[position]);
    178             mText2.setTextSize(30);
    179             mText2.setGravity(Gravity.RIGHT);
    180             mText2.setBackgroundColor(mColorArray[position]);
    181  
    182             this.addView(mText2, new LinearLayout.LayoutParams(
    183                     LinearLayout.LayoutParams.MATCH_PARENT,
    184                     LinearLayout.LayoutParams.MATCH_PARENT, 1));
    185         }
    186     }
    187 }

    [代码] FlingGallery

    001 import android.content.Context;
    002 import android.view.GestureDetector;
    003 import android.view.KeyEvent;
    004 import android.view.MotionEvent;
    005 import android.view.View;
    006 import android.view.animation.Animation;
    007 import android.view.animation.AnimationUtils;
    008 import android.view.animation.Interpolator;
    009 import android.view.animation.Transformation;
    010 import android.widget.Adapter;
    011 import android.widget.FrameLayout;
    012 import android.widget.LinearLayout;
    013  
    014 // TODO:
    015  
    016 // 1. In order to improve performance Cache screen bitmap and use for animation
    017 // 2. Establish superfluous memory allocations and delay or replace with reused objects
    018 //    Probably need to make sure we are not allocating objects (strings, etc.) in loops
    019  
    020 public class FlingGallery extends FrameLayout
    021 {
    022     // Constants
    023      
    024     private final int swipe_min_distance = 120;
    025     private final int swipe_max_off_path = 250;
    026     private final int swipe_threshold_veloicty = 400;
    027  
    028     // Properties
    029      
    030     private int mViewPaddingWidth = 0;
    031     private int mAnimationDuration = 250;
    032     private float mSnapBorderRatio = 0.5f;
    033     private boolean mIsGalleryCircular = true;
    034  
    035     // Members
    036  
    037     private int mGalleryWidth = 0;
    038     private boolean mIsTouched = false;
    039     private boolean mIsDragging = false;
    040     private float mCurrentOffset = 0.0f;
    041     private long mScrollTimestamp = 0;
    042     private int mFlingDirection = 0;
    043     private int mCurrentPosition = 0;
    044     private int mCurrentViewNumber = 0;
    045  
    046     private Context mContext;
    047     private Adapter mAdapter;
    048     private FlingGalleryView[] mViews;
    049     private FlingGalleryAnimation mAnimation;
    050     private GestureDetector mGestureDetector;
    051     private Interpolator mDecelerateInterpolater;
    052  
    053     public FlingGallery(Context context)
    054     {
    055         super(context);
    056  
    057         mContext = context;
    058         mAdapter = null;
    059          
    060         mViews = new FlingGalleryView[3];
    061         mViews[0] = new FlingGalleryView(0, this);
    062         mViews[1] = new FlingGalleryView(1, this);
    063         mViews[2] = new FlingGalleryView(2, this);
    064  
    065         mAnimation = new FlingGalleryAnimation();
    066         mGestureDetector = new GestureDetector(new FlingGestureDetector());
    067         mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext, android.R.anim.decelerate_interpolator);
    068     }
    069  
    070     public void setPaddingWidth(int viewPaddingWidth)
    071     {
    072         mViewPaddingWidth = viewPaddingWidth;
    073     }
    074  
    075     public void setAnimationDuration(int animationDuration)
    076     {
    077         mAnimationDuration = animationDuration;
    078     }
    079      
    080     public void setSnapBorderRatio(float snapBorderRatio)
    081     {
    082         mSnapBorderRatio = snapBorderRatio;
    083     }
    084  
    085     public void setIsGalleryCircular(boolean isGalleryCircular)
    086     {
    087         if (mIsGalleryCircular != isGalleryCircular)
    088         {
    089             mIsGalleryCircular = isGalleryCircular;
    090      
    091             if (mCurrentPosition == getFirstPosition())
    092             {
    093                 // We need to reload the view immediately to the left to change it to circular view or blank
    094                 mViews[getPrevViewNumber(mCurrentViewNumber)].recycleView(getPrevPosition(mCurrentPosition));          
    095             }
    096      
    097             if (mCurrentPosition == getLastPosition())
    098             {
    099                 // We need to reload the view immediately to the right to change it to circular view or blank
    100                 mViews[getNextViewNumber(mCurrentViewNumber)].recycleView(getNextPosition(mCurrentPosition));          
    101             }
    102         }
    103     }
    104  
    105     public int getGalleryCount()
    106     {
    107         return (mAdapter == null) ? 0 : mAdapter.getCount();
    108     }
    109  
    110     public int getFirstPosition()
    111     {
    112         return 0;
    113     }
    114  
    115     public int getLastPosition()
    116     {
    117         return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
    118     }
    119  
    120     private int getPrevPosition(int relativePosition)
    121     {
    122         int prevPosition = relativePosition - 1;
    123  
    124         if (prevPosition < getFirstPosition())
    125         {
    126             prevPosition = getFirstPosition() - 1;
    127  
    128             if (mIsGalleryCircular == true)
    129             {
    130                 prevPosition = getLastPosition();
    131             }
    132         }
    133  
    134         return prevPosition;
    135     }
    136  
    137     private int getNextPosition(int relativePosition)
    138     {
    139         int nextPosition = relativePosition + 1;
    140  
    141         if (nextPosition > getLastPosition())
    142         {
    143             nextPosition = getLastPosition() + 1;
    144  
    145             if (mIsGalleryCircular == true)
    146             {
    147                 nextPosition = getFirstPosition();
    148             }
    149         }
    150  
    151         return nextPosition;
    152     }
    153  
    154     private int getPrevViewNumber(int relativeViewNumber)
    155     {
    156         return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
    157     }
    158  
    159     private int getNextViewNumber(int relativeViewNumber)
    160     {
    161         return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
    162     }
    163      
    164     @Override
    165     protected void onLayout(boolean changed, int left, int top, int right, int bottom)
    166     {
    167         super.onLayout(changed, left, top, right, bottom);
    168  
    169         // Calculate our view width
    170         mGalleryWidth = right - left;
    171  
    172         if (changed == true)
    173         {
    174             // Position views at correct starting offsets
    175             mViews[0].setOffset(0, 0, mCurrentViewNumber);
    176             mViews[1].setOffset(0, 0, mCurrentViewNumber);
    177             mViews[2].setOffset(0, 0, mCurrentViewNumber);
    178         }
    179     }
    180  
    181     public void setAdapter(Adapter adapter)
    182     {
    183         mAdapter = adapter;
    184         mCurrentPosition = 0;
    185         mCurrentViewNumber = 0;
    186  
    187         // Load the initial views from adapter
    188         mViews[0].recycleView(mCurrentPosition);
    189         mViews[1].recycleView(getNextPosition(mCurrentPosition));
    190         mViews[2].recycleView(getPrevPosition(mCurrentPosition));
    191  
    192         // Position views at correct starting offsets
    193         mViews[0].setOffset(0, 0, mCurrentViewNumber);
    194         mViews[1].setOffset(0, 0, mCurrentViewNumber);
    195         mViews[2].setOffset(0, 0, mCurrentViewNumber);
    196     }
    197  
    198     private int getViewOffset(int viewNumber, int relativeViewNumber)
    199     {
    200         // Determine width including configured padding width
    201         int offsetWidth = mGalleryWidth + mViewPaddingWidth;
    202  
    203         // Position the previous view one measured width to left
    204         if (viewNumber == getPrevViewNumber(relativeViewNumber))
    205         {
    206             return offsetWidth;
    207         }
    208  
    209         // Position the next view one measured width to the right
    210         if (viewNumber == getNextViewNumber(relativeViewNumber))
    211         {
    212             return offsetWidth * -1;
    213         }
    214  
    215         return 0;
    216     }
    217  
    218     void movePrevious()
    219     {
    220         // Slide to previous view
    221         mFlingDirection = 1;
    222         processGesture();
    223     }
    224  
    225     void moveNext()
    226     {
    227         // Slide to next view
    228         mFlingDirection = -1;
    229         processGesture();
    230     }
    231  
    232      @Override
    233      public boolean onKeyDown(int keyCode, KeyEvent event)
    234      {
    235         switch (keyCode)
    236         {
    237         case KeyEvent.KEYCODE_DPAD_LEFT:
    238             movePrevious();
    239             return true;
    240      
    241         case KeyEvent.KEYCODE_DPAD_RIGHT:
    242             moveNext();
    243             return true;
    244      
    245         case KeyEvent.KEYCODE_DPAD_CENTER:
    246         case KeyEvent.KEYCODE_ENTER:
    247         }
    248  
    249         return super.onKeyDown(keyCode, event);
    250     }
    251  
    252     public boolean onGalleryTouchEvent(MotionEvent event)
    253     {
    254         boolean consumed = mGestureDetector.onTouchEvent(event);
    255          
    256         if (event.getAction() == MotionEvent.ACTION_UP)
    257         {
    258             if (mIsTouched || mIsDragging)
    259             {
    260                 processScrollSnap();
    261                 processGesture();
    262             }
    263         }
    264          
    265         return consumed;
    266     }
    267  
    268     void processGesture()
    269     {
    270         int newViewNumber = mCurrentViewNumber;
    271         int reloadViewNumber = 0;
    272         int reloadPosition = 0;
    273  
    274         mIsTouched = false;
    275         mIsDragging = false;
    276  
    277         if (mFlingDirection > 0)
    278         {
    279             if (mCurrentPosition > getFirstPosition() || mIsGalleryCircular == true)
    280             {
    281                 // Determine previous view and outgoing view to recycle
    282                 newViewNumber = getPrevViewNumber(mCurrentViewNumber);
    283                 mCurrentPosition = getPrevPosition(mCurrentPosition);
    284                 reloadViewNumber = getNextViewNumber(mCurrentViewNumber);
    285                 reloadPosition = getPrevPosition(mCurrentPosition);
    286             }
    287         }
    288  
    289         if (mFlingDirection < 0)
    290         {
    291             if (mCurrentPosition < getLastPosition() || mIsGalleryCircular == true)
    292             {
    293                 // Determine the next view and outgoing view to recycle
    294                 newViewNumber = getNextViewNumber(mCurrentViewNumber);
    295                 mCurrentPosition = getNextPosition(mCurrentPosition);
    296                 reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);
    297                 reloadPosition = getNextPosition(mCurrentPosition);
    298             }
    299         }
    300  
    301         if (newViewNumber != mCurrentViewNumber)
    302         {
    303             mCurrentViewNumber = newViewNumber;
    304  
    305             // Reload outgoing view from adapter in new position
    306             mViews[reloadViewNumber].recycleView(reloadPosition);
    307         }
    308  
    309         // Ensure input focus on the current view
    310         mViews[mCurrentViewNumber].requestFocus();
    311  
    312         // Run the slide animations for view transitions
    313         mAnimation.prepareAnimation(mCurrentViewNumber);
    314         this.startAnimation(mAnimation);
    315  
    316         // Reset fling state
    317         mFlingDirection = 0;
    318     }
    319  
    320     void processScrollSnap()
    321     {
    322         // Snap to next view if scrolled passed snap position
    323         float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;
    324         int rollOffset = mGalleryWidth - (int) rollEdgeWidth;
    325         int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
    326  
    327         if (currentOffset <= rollOffset * -1)
    328         {
    329             // Snap to previous view
    330             mFlingDirection = 1;
    331         }
    332  
    333         if (currentOffset >= rollOffset)
    334         {
    335             // Snap to next view
    336             mFlingDirection = -1;
    337         }
    338     }
    339  
    340     private class FlingGalleryView
    341     {
    342         private int mViewNumber;
    343         private FrameLayout mParentLayout;
    344          
    345         private FrameLayout mInvalidLayout = null;
    346         private LinearLayout mInternalLayout = null;
    347         private View mExternalView = null;
    348  
    349         public FlingGalleryView(int viewNumber, FrameLayout parentLayout)
    350         {
    351             mViewNumber = viewNumber;
    352             mParentLayout = parentLayout;
    353  
    354             // Invalid layout is used when outside gallery
    355             mInvalidLayout = new FrameLayout(mContext);
    356             mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(
    357                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    358  
    359             // Internal layout is permanent for duration
    360             mInternalLayout = new LinearLayout(mContext);
    361             mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(
    362                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    363  
    364             mParentLayout.addView(mInternalLayout);
    365         }
    366  
    367         public void recycleView(int newPosition)
    368         {
    369             if (mExternalView != null)
    370             {
    371                 mInternalLayout.removeView(mExternalView);
    372             }
    373  
    374             if (mAdapter != null)
    375             {
    376                 if (newPosition >= getFirstPosition() && newPosition <= getLastPosition())
    377                 {
    378                     mExternalView = mAdapter.getView(newPosition, mExternalView, mInternalLayout);
    379                 }
    380                 else
    381                 {
    382                     mExternalView = mInvalidLayout;
    383                 }
    384             }
    385  
    386             if (mExternalView != null)
    387             {
    388                 mInternalLayout.addView(mExternalView, new LinearLayout.LayoutParams(
    389                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    390             }
    391         }
    392  
    393         public void setOffset(int xOffset, int yOffset, int relativeViewNumber)
    394         {
    395             // Scroll the target view relative to its own position relative to currently displayed view
    396             mInternalLayout.scrollTo(getViewOffset(mViewNumber, relativeViewNumber) + xOffset, yOffset);
    397         }
    398          
    399         public int getCurrentOffset()
    400         {
    401             // Return the current scroll position
    402             return mInternalLayout.getScrollX();
    403         }
    404  
    405         public void requestFocus()
    406         {
    407             mInternalLayout.requestFocus();
    408         }
    409     }
    410  
    411     private class FlingGalleryAnimation extends Animation
    412     {
    413         private boolean mIsAnimationInProgres;
    414         private int mRelativeViewNumber;
    415         private int mInitialOffset;
    416         private int mTargetOffset;
    417         private int mTargetDistance;   
    418   
    419         public FlingGalleryAnimation()
    420         {
    421             mIsAnimationInProgres = false;
    422             mRelativeViewNumber = 0;
    423             mInitialOffset = 0;
    424             mTargetOffset = 0;
    425             mTargetDistance = 0;
    426         }
    427   
    428         public void prepareAnimation(int relativeViewNumber)
    429         {
    430             // If we are animating relative to a new view
    431             if (mRelativeViewNumber != relativeViewNumber)
    432             {
    433                 if (mIsAnimationInProgres == true)
    434                 {
    435                     // We only have three views so if requested again to animate in same direction we must snap
    436                     int newDirection = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1 : -1;
    437                     int animDirection = (mTargetDistance < 0) ? 1 : -1;
    438  
    439                     // If animation in same direction
    440                     if (animDirection == newDirection)
    441                     {
    442                         // Ran out of time to animate so snap to the target offset
    443                         mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
    444                         mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
    445                         mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);
    446                     }
    447                 }
    448      
    449                 // Set relative view number for animation
    450                 mRelativeViewNumber = relativeViewNumber;
    451             }
    452  
    453             // Note: In this implementation the targetOffset will always be zero
    454             // as we are centering the view; but we include the calculations of
    455             // targetOffset and targetDistance for use in future implementations
    456  
    457             mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();
    458             mTargetOffset = getViewOffset(mRelativeViewNumber, mRelativeViewNumber);
    459             mTargetDistance = mTargetOffset - mInitialOffset;
    460  
    461             // Configure base animation properties
    462             this.setDuration(mAnimationDuration);
    463             this.setInterpolator(mDecelerateInterpolater);
    464  
    465             // Start/continued animation
    466             mIsAnimationInProgres = true;
    467         }
    468  
    469         @Override
    470         protected void applyTransformation(float interpolatedTime, Transformation transformation)
    471         {
    472             // Ensure interpolatedTime does not over-shoot then calculate new offset
    473             interpolatedTime = (interpolatedTime > 1.0f) ? 1.0f : interpolatedTime;
    474             int offset = mInitialOffset + (int) (mTargetDistance * interpolatedTime);
    475  
    476             for (int viewNumber = 0; viewNumber < 3; viewNumber++)
    477             {
    478                 // Only need to animate the visible views as the other view will always be off-screen
    479                 if ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber)) ||
    480                     (mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber)))
    481                 {
    482                     mViews[viewNumber].setOffset(offset, 0, mRelativeViewNumber);
    483                 }
    484             }
    485         }
    486  
    487         @Override
    488         public boolean getTransformation(long currentTime, Transformation outTransformation)
    489         {
    490             if (super.getTransformation(currentTime, outTransformation) == false)
    491             {
    492                 // Perform final adjustment to offsets to cleanup animation
    493                 mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
    494                 mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
    495                 mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);
    496  
    497                 // Reached the animation target
    498                 mIsAnimationInProgres = false;
    499  
    500                 return false;
    501             }
    502   
    503             // Cancel if the screen touched
    504             if (mIsTouched || mIsDragging)
    505             {
    506                 // Note that at this point we still consider ourselves to be animating
    507                 // because we have not yet reached the target offset; its just that the
    508                 // user has temporarily interrupted the animation with a touch gesture
    509  
    510                 return false;
    511             }
    512  
    513             return true;
    514         }
    515     }
    516  
    517     private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener
    518     {
    519         @Override
    520         public boolean onDown(MotionEvent e)
    521         {
    522             // Stop animation
    523             mIsTouched = true;
    524  
    525             // Reset fling state
    526             mFlingDirection = 0;
    527             return true;
    528         }
    529  
    530         @Override
    531         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    532         {
    533             if (e2.getAction() == MotionEvent.ACTION_MOVE)
    534             {
    535                 if (mIsDragging == false)
    536                 {
    537                     // Stop animation
    538                     mIsTouched = true;
    539       
    540                     // Reconfigure scroll
    541                     mIsDragging = true;
    542                     mFlingDirection = 0;
    543                     mScrollTimestamp = System.currentTimeMillis();
    544                     mCurrentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
    545                 }
    546  
    547                 float maxVelocity = mGalleryWidth / (mAnimationDuration / 1000.0f);
    548                 long timestampDelta = System.currentTimeMillis() - mScrollTimestamp;
    549                 float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f);
    550                 float currentScrollDelta = e1.getX() - e2.getX();
    551  
    552                 if (currentScrollDelta < maxScrollDelta * -1) currentScrollDelta = maxScrollDelta * -1;
    553                 if (currentScrollDelta > maxScrollDelta) currentScrollDelta = maxScrollDelta;
    554                 int scrollOffset = Math.round(mCurrentOffset + currentScrollDelta);
    555  
    556                 // We can't scroll more than the width of our own frame layout
    557                 if (scrollOffset >= mGalleryWidth) scrollOffset = mGalleryWidth;
    558                 if (scrollOffset <= mGalleryWidth * -1) scrollOffset = mGalleryWidth * -1;
    559                  
    560                 mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);
    561                 mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);
    562                 mViews[2].setOffset(scrollOffset, 0, mCurrentViewNumber);
    563             }
    564  
    565             return false;
    566         }
    567  
    568         @Override
    569         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    570         {
    571             if (Math.abs(e1.getY() - e2.getY()) <= swipe_max_off_path)
    572             {
    573                 if (e2.getX() - e1.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)
    574                 {
    575                     movePrevious();
    576                 }
    577  
    578                 if(e1.getX() - e2.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)
    579                 {
    580                     moveNext();
    581                 }
    582             }
    583  
    584             return false;
    585         }
    586  
    587         @Override
    588         public void onLongPress(MotionEvent e)
    589         {
    590             // Finalise scrolling
    591             mFlingDirection = 0;
    592             processGesture();
    593         }
    594  
    595         @Override
    596         public void onShowPress(MotionEvent e)
    597         {
    598         }
    599  
    600         @Override
    601         public boolean onSingleTapUp(MotionEvent e)
    602         {
    603             // Reset fling state
    604             mFlingDirection = 0;
    605             return false;
    606         }
    607     }
    608 }
  • 相关阅读:
    css sprite的实现
    python的range()函数使用方法
    Codeforces Round #260 (Div. 1) 455 A. Boredom (DP)
    n个整数全排列的递归实现(C++)
    AngularJS进阶(三十一)AngularJS项目开发技巧之获取模态对话框中的组件ID
    Swift扩展(Extension)
    leetcode 88 Merge Sorted Array
    Unity3D摄像机尾随人物
    mybatis 高级映射和spring整合之与Spring整合(6)
    mybatis 高级映射和spring整合之查询缓存(5)
  • 原文地址:https://www.cnblogs.com/Greenwood/p/2079926.html
Copyright © 2011-2022 走看看