android中的左右滑动

本文介绍了FlingGallery类的实现细节,用于在Android中创建左右滑动的应用。通过使用观察者模式,实现滑动页面时改变标题的功能,并提供了自定义适配器以展示动态内容。同时,解释了如何在不同屏幕尺寸下优化滑动手势体验,以及如何将其嵌入到TabActivity中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iphone中有很多应用都能够左右滑动,非常cool,关键是实现起来非常简单。android比起来就差远了,网上有不少帖子。 我在这边重新分享下自己的经验吧,将实现细节详细解释下。

FlingGallery这个类摘自网上,有少许修改。
Java代码  收藏代码
  1. package com.nuomi.ui;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.Set;  
  5.   
  6. import android.content.Context;  
  7. import android.view.GestureDetector;  
  8. import android.view.KeyEvent;  
  9. import android.view.MotionEvent;  
  10. import android.view.View;  
  11. import android.view.animation.Animation;  
  12. import android.view.animation.AnimationUtils;  
  13. import android.view.animation.Interpolator;  
  14. import android.view.animation.Transformation;  
  15. import android.widget.Adapter;  
  16. import android.widget.FrameLayout;  
  17. import android.widget.LinearLayout;  
  18.   
  19.   
  20. public class FlingGallery extends FrameLayout  
  21. {  
  22.       
  23.     private Set<OnGalleryChangeListener> listeners;  
  24.     private final int swipe_min_distance = 120;  
  25.     private final int swipe_max_off_path = 250;  
  26.     private final int swipe_threshold_veloicty = 400;  
  27.   
  28.     private int mViewPaddingWidth = 0;  
  29.     private int mAnimationDuration = 250;  
  30.     private float mSnapBorderRatio = 0.5f;  
  31.     private boolean mIsGalleryCircular = true;  
  32.   
  33.     private int mGalleryWidth = 0;  
  34.     private boolean mIsTouched = false;  
  35.     private boolean mIsDragging = false;  
  36.     private float mCurrentOffset = 0.0f;  
  37.     private long mScrollTimestamp = 0;  
  38.     private int mFlingDirection = 0;  
  39.     private int mCurrentPosition = 0;  
  40.     private int mCurrentViewNumber = 0;  
  41.   
  42.     private Context mContext;  
  43.     private Adapter mAdapter;  
  44.     private FlingGalleryView[] mViews;  
  45.     private FlingGalleryAnimation mAnimation;  
  46.     private GestureDetector mGestureDetector;  
  47.     private Interpolator mDecelerateInterpolater;  
  48.   
  49.     public FlingGallery(Context context)  
  50.     {  
  51.         super(context);  
  52.   
  53.         listeners = new HashSet<OnGalleryChangeListener>();  
  54.           
  55.         mContext = context;  
  56.         mAdapter = null;  
  57.           
  58.         mViews = new FlingGalleryView[3];  
  59.         mViews[0] = new FlingGalleryView(0this);  
  60.         mViews[1] = new FlingGalleryView(1this);  
  61.         mViews[2] = new FlingGalleryView(2this);  
  62.   
  63.         mAnimation = new FlingGalleryAnimation();  
  64.         mGestureDetector = new GestureDetector(new FlingGestureDetector());  
  65.         mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext, android.R.anim.decelerate_interpolator);  
  66.     }  
  67.   
  68.     public void addGalleryChangeListener(OnGalleryChangeListener listener){  
  69.         listeners.add(listener);  
  70.     }  
  71.       
  72.     public void setPaddingWidth(int viewPaddingWidth)  
  73.     {  
  74.         mViewPaddingWidth = viewPaddingWidth;  
  75.     }  
  76.   
  77.     public void setAnimationDuration(int animationDuration)  
  78.     {  
  79.         mAnimationDuration = animationDuration;  
  80.     }  
  81.       
  82.     public void setSnapBorderRatio(float snapBorderRatio)  
  83.     {  
  84.         mSnapBorderRatio = snapBorderRatio;  
  85.     }  
  86.   
  87.     public void setIsGalleryCircular(boolean isGalleryCircular)   
  88.     {  
  89.         if (mIsGalleryCircular != isGalleryCircular)  
  90.         {  
  91.             mIsGalleryCircular = isGalleryCircular;  
  92.       
  93.             if (mCurrentPosition == getFirstPosition())  
  94.             {  
  95.                 // We need to reload the view immediately to the left to change it to circular view or blank  
  96.                 mViews[getPrevViewNumber(mCurrentViewNumber)].recycleView(getPrevPosition(mCurrentPosition));             
  97.             }  
  98.       
  99.             if (mCurrentPosition == getLastPosition())  
  100.             {  
  101.                 // We need to reload the view immediately to the right to change it to circular view or blank  
  102.                 mViews[getNextViewNumber(mCurrentViewNumber)].recycleView(getNextPosition(mCurrentPosition));             
  103.             }  
  104.         }  
  105.     }  
  106.   
  107.     public int getGalleryCount()  
  108.     {  
  109.         return (mAdapter == null) ? 0 : mAdapter.getCount();  
  110.     }  
  111.   
  112.     public int getFirstPosition()  
  113.     {  
  114.         return 0;  
  115.     }  
  116.   
  117.     public int getLastPosition()  
  118.     {  
  119.         return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;  
  120.     }  
  121.   
  122.     private int getPrevPosition(int relativePosition)  
  123.     {  
  124.         int prevPosition = relativePosition - 1;  
  125.   
  126.         if (prevPosition < getFirstPosition())  
  127.         {  
  128.             prevPosition = getFirstPosition() - 1;  
  129.   
  130.             if (mIsGalleryCircular == true)  
  131.             {  
  132.                 prevPosition = getLastPosition();  
  133.             }  
  134.         }  
  135.         NotifyGalleryChange();  
  136.         return prevPosition;  
  137.     }  
  138.   
  139.     private int getNextPosition(int relativePosition)  
  140.     {  
  141.         int nextPosition = relativePosition + 1;  
  142.   
  143.         if (nextPosition > getLastPosition())  
  144.         {  
  145.             nextPosition = getLastPosition() + 1;  
  146.   
  147.             if (mIsGalleryCircular == true)  
  148.             {  
  149.                 nextPosition = getFirstPosition();  
  150.             }  
  151.         }  
  152.         NotifyGalleryChange();  
  153.         return nextPosition;  
  154.     }  
  155.   
  156.     //  
  157.     private void NotifyGalleryChange() {  
  158.         for (OnGalleryChangeListener listener :listeners) {  
  159.             listener.onGalleryChange(mCurrentPosition);  
  160.         }  
  161.     }  
  162.   
  163.     private int getPrevViewNumber(int relativeViewNumber)  
  164.     {  
  165.         return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;  
  166.     }  
  167.   
  168.     private int getNextViewNumber(int relativeViewNumber)  
  169.     {  
  170.         return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;  
  171.     }  
  172.       
  173.     @Override  
  174.     protected void onLayout(boolean changed, int left, int top, int right, int bottom)  
  175.     {  
  176.         super.onLayout(changed, left, top, right, bottom);  
  177.   
  178.         // Calculate our view width  
  179.         mGalleryWidth = right - left;  
  180.   
  181.         if (changed)  
  182.         {  
  183.             // Position views at correct starting offsets  
  184.             mViews[0].setOffset(00, mCurrentViewNumber);  
  185.             mViews[1].setOffset(00, mCurrentViewNumber);  
  186.             mViews[2].setOffset(00, mCurrentViewNumber);  
  187.         }  
  188.     }  
  189.   
  190.     public void setAdapter(Adapter adapter)  
  191.     {  
  192.         mAdapter = adapter;  
  193.         mCurrentPosition = 0;  
  194.         mCurrentViewNumber = 0;  
  195.   
  196.         // Load the initial views from adapter  
  197.         mViews[0].recycleView(mCurrentPosition);  
  198.         mViews[1].recycleView(getNextPosition(mCurrentPosition));  
  199.         mViews[2].recycleView(getPrevPosition(mCurrentPosition));  
  200.   
  201.         // Position views at correct starting offsets  
  202.         mViews[0].setOffset(00, mCurrentViewNumber);  
  203.         mViews[1].setOffset(00, mCurrentViewNumber);  
  204.         mViews[2].setOffset(00, mCurrentViewNumber);  
  205.     }  
  206.   
  207.     private int getViewOffset(int viewNumber, int relativeViewNumber)  
  208.     {  
  209.         // Determine width including configured padding width  
  210.         int offsetWidth = mGalleryWidth + mViewPaddingWidth;  
  211.   
  212.         // Position the previous view one measured width to left  
  213.         if (viewNumber == getPrevViewNumber(relativeViewNumber))  
  214.         {  
  215.             return offsetWidth;  
  216.         }  
  217.   
  218.         // Position the next view one measured width to the right  
  219.         if (viewNumber == getNextViewNumber(relativeViewNumber))  
  220.         {  
  221.             return offsetWidth * -1;  
  222.         }  
  223.   
  224.         return 0;  
  225.     }  
  226.   
  227.     void movePrevious()  
  228.     {  
  229.         // Slide to previous view  
  230.         mFlingDirection = 1;  
  231.         processGesture();  
  232.     }  
  233.   
  234.     void moveNext()  
  235.     {  
  236.         // Slide to next view  
  237.         mFlingDirection = -1;  
  238.         processGesture();  
  239.     }  
  240.   
  241.      @Override  
  242.      public boolean onKeyDown(int keyCode, KeyEvent event)  
  243.      {  
  244.         switch (keyCode)  
  245.         {  
  246.         case KeyEvent.KEYCODE_DPAD_LEFT:  
  247.             movePrevious();  
  248.             return true;  
  249.       
  250.         case KeyEvent.KEYCODE_DPAD_RIGHT:  
  251.             moveNext();  
  252.             return true;  
  253.       
  254.         case KeyEvent.KEYCODE_DPAD_CENTER:  
  255.         case KeyEvent.KEYCODE_ENTER:  
  256.         }  
  257.   
  258.         return super.onKeyDown(keyCode, event);  
  259.     }  
  260.   
  261.     public boolean onGalleryTouchEvent(MotionEvent event)  
  262.     {  
  263.         boolean consumed = mGestureDetector.onTouchEvent(event);  
  264.           
  265.         if (event.getAction() == MotionEvent.ACTION_UP)  
  266.         {  
  267.             if (mIsTouched || mIsDragging)  
  268.             {  
  269.                 processScrollSnap();  
  270.                 processGesture();  
  271.             }  
  272.         }  
  273.           
  274.         return consumed;  
  275.     }  
  276.   
  277.     void processGesture()  
  278.     {  
  279.         int newViewNumber = mCurrentViewNumber;  
  280.         int reloadViewNumber = 0;  
  281.         int reloadPosition = 0;  
  282.   
  283.         mIsTouched = false;  
  284.         mIsDragging = false;  
  285.   
  286.         if (mFlingDirection > 0)  
  287.         {  
  288.             if (mCurrentPosition > getFirstPosition() || mIsGalleryCircular == true)  
  289.             {  
  290.                 // Determine previous view and outgoing view to recycle  
  291.                 newViewNumber = getPrevViewNumber(mCurrentViewNumber);  
  292.                 mCurrentPosition = getPrevPosition(mCurrentPosition);  
  293.                 reloadViewNumber = getNextViewNumber(mCurrentViewNumber);   
  294.                 reloadPosition = getPrevPosition(mCurrentPosition);  
  295.             }  
  296.         }  
  297.   
  298.         if (mFlingDirection < 0)  
  299.         {  
  300.             if (mCurrentPosition < getLastPosition() || mIsGalleryCircular == true)  
  301.             {  
  302.                 // Determine the next view and outgoing view to recycle  
  303.                 newViewNumber = getNextViewNumber(mCurrentViewNumber);  
  304.                 mCurrentPosition = getNextPosition(mCurrentPosition);  
  305.                 reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);  
  306.                 reloadPosition = getNextPosition(mCurrentPosition);  
  307.             }  
  308.         }  
  309.   
  310.         if (newViewNumber != mCurrentViewNumber)  
  311.         {  
  312.             mCurrentViewNumber = newViewNumber;   
  313.   
  314.             // Reload outgoing view from adapter in new position  
  315.             mViews[reloadViewNumber].recycleView(reloadPosition);  
  316.         }  
  317.   
  318.         // Ensure input focus on the current view  
  319.         mViews[mCurrentViewNumber].requestFocus();  
  320.   
  321.         // Run the slide animations for view transitions  
  322.         mAnimation.prepareAnimation(mCurrentViewNumber);  
  323.         this.startAnimation(mAnimation);  
  324.   
  325.         // Reset fling state  
  326.         mFlingDirection = 0;  
  327.     }  
  328.   
  329.     void processScrollSnap()  
  330.     {  
  331.         // Snap to next view if scrolled passed snap position  
  332.         float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;  
  333.         int rollOffset = mGalleryWidth - (int) rollEdgeWidth;  
  334.         int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();  
  335.   
  336.         if (currentOffset <= rollOffset * -1)  
  337.         {  
  338.             // Snap to previous view  
  339.             mFlingDirection = 1;  
  340.         }  
  341.   
  342.         if (currentOffset >= rollOffset)  
  343.         {  
  344.             // Snap to next view  
  345.             mFlingDirection = -1;  
  346.         }  
  347.     }  
  348.   
  349.     private class FlingGalleryView  
  350.     {  
  351.         private int mViewNumber;  
  352.         private FrameLayout mParentLayout;  
  353.           
  354.         private FrameLayout mInvalidLayout = null;  
  355.         private LinearLayout mInternalLayout = null;  
  356.         private View mExternalView = null;  
  357.   
  358.         public FlingGalleryView(int viewNumber, FrameLayout parentLayout)  
  359.         {  
  360.             mViewNumber = viewNumber;  
  361.             mParentLayout = parentLayout;  
  362.   
  363.             // Invalid layout is used when outside gallery  
  364.             mInvalidLayout = new FrameLayout(mContext);  
  365.             mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(   
  366.                     LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
  367.   
  368.             // Internal layout is permanent for duration  
  369.             mInternalLayout = new LinearLayout(mContext);  
  370.             mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(   
  371.                     LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
  372.   
  373.             mParentLayout.addView(mInternalLayout);  
  374.         }  
  375.   
  376.         public void recycleView(int newPosition)  
  377.         {  
  378.             if (mExternalView != null)  
  379.             {  
  380.                 mInternalLayout.removeView(mExternalView);  
  381.             }  
  382.   
  383.             if (mAdapter != null)  
  384.             {  
  385.                 if (newPosition >= getFirstPosition() && newPosition <= getLastPosition())  
  386.                 {  
  387.                     mExternalView = mAdapter.getView(newPosition, mExternalView, mInternalLayout);  
  388.                 }  
  389.                 else  
  390.                 {  
  391.                     mExternalView = mInvalidLayout;  
  392.                 }  
  393.             }  
  394.   
  395.             if (mExternalView != null)  
  396.             {  
  397.                 mInternalLayout.addView(mExternalView, new LinearLayout.LayoutParams(   
  398.                     LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
  399.             }  
  400.         }  
  401.   
  402.         public void setOffset(int xOffset, int yOffset, int relativeViewNumber)  
  403.         {  
  404.             // Scroll the target view relative to its own position relative to currently displayed view  
  405.             mInternalLayout.scrollTo(getViewOffset(mViewNumber, relativeViewNumber) + xOffset, yOffset);  
  406.         }  
  407.           
  408.         public int getCurrentOffset()  
  409.         {  
  410.             // Return the current scroll position  
  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.     }  
  618.   
  619.     public GestureDetector getMGestureDetector() {  
  620.         return mGestureDetector;  
  621.     }  
  622.       
  623. }  


由于我需要在滑动页面时,改动title中的文字,这里采用了观察者模式,加了个OnGalleryChangeListener,有同样需求的同学可以参考下。
Java代码  收藏代码
  1. public interface OnGalleryChangeListener {  
  2.       
  3.     public void onGalleryChange(int currentItem);  
  4. }  

在Activity中,
Java代码  收藏代码
  1. FlingGallery gallery = new FlingGallery(this);  
  2.   
  3.         gallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(),  
  4.                 android.R.layout.simple_list_item_1, new String[xxxx]) {  
  5.             public View getView(int position, View convertView, ViewGroup parent) {  
  6.                                // 返回滑动的deal  
  7.                 return dealViews[position];  
  8.             }  
  9.         });  
  10.         gallery.addGalleryChangeListener(new OnGalleryChangeListener() {  
  11.   
  12.             @Override  
  13.             public void onGalleryChange(int currentItem) {  
  14.                 // 干些想干的事件  
  15.   
  16.             }  
  17.   
  18.         });  

将gallery加到Activity中的最终需要显示的类中。
Adapter中的getView方法中,将需要用来滑动的view添加进来。在GalleryChangeListener中,可以干一些自己想要的滑动后的事情。我在这里改动了标题的文字,进行了我的view中图片的lazyloading。
这里提一下另一个问题。我的这个类,最终嵌入到了tab中,需要在你的tabActivity中dispatchKeyEvent一下,将按键事件分发下去。
最开始,我的滑动的view写得比较通用,所以包含了ScrollView来满足比较长的屏幕,导致手势监听会出一些问题,会出现抖动。当时的解决方案是针对不同屏幕尽量保证一屏能够显示,在res目录下,增加layout-800x480之类的目录,针对每个不同屏幕设计单独的layout,放弃上下滑动,效果也不错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值