Android拖动效果图

转载至:http://iaiai.iteye.com/blog/1580587

先来看效果图:



就两个文件,新建一个项目把下面两个文件放进去,设置好启动activity就行了

FlingGallery.java

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

import android.content.Context;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
import android.widget.Adapter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

// TODO: 
// 1. In order to improve performance Cache screen bitmap and use for animation 
// 2. Establish superfluous memory allocations and delay or replace with reused objects 
// Probably need to make sure we are not allocating objects (strings, etc.) in loops 
/**
 * 
 * <p>
 * Title: FlingGallery.java
 * </p>
 * <p>
 * E-Mail: 176291935@qq.com
 * </p>
 * <p>
 * QQ: 176291935
 * </p>
 * <p>
 * Http: iaiai.iteye.com
 * </p>
 * <p>
 * Create time: 2012-7-7 上午10:18:53
 * </p>
 * 
 * @author 丸子
 * @version 0.0.1
 */
public class FlingGallery extends FrameLayout {
	// Constants

	private final int swipe_min_distance = 120;
	private final int swipe_max_off_path = 250;
	private final int swipe_threshold_veloicty = 400;

	// Properties
	private int mViewPaddingWidth = 0;
	private int mAnimationDuration = 250;
	private float mSnapBorderRatio = 0.5f;
	private boolean mIsGalleryCircular = true;

	// Members
	private int mGalleryWidth = 0;
	private boolean mIsTouched = false;
	private boolean mIsDragging = false;
	private float mCurrentOffset = 0.0f;
	private long mScrollTimestamp = 0;
	private int mFlingDirection = 0;
	private int mCurrentPosition = 0;
	private int mCurrentViewNumber = 0;

	private Context mContext;
	private Adapter mAdapter;
	private FlingGalleryView[] mViews;
	private FlingGalleryAnimation mAnimation;
	private GestureDetector mGestureDetector;
	private Interpolator mDecelerateInterpolater;

	public FlingGallery(Context context) {
		super(context);
		mContext = context;
		mAdapter = null;

		mViews = new FlingGalleryView[3];
		mViews[0] = new FlingGalleryView(0, this);
		mViews[1] = new FlingGalleryView(1, this);
		mViews[2] = new FlingGalleryView(2, this);
		mAnimation = new FlingGalleryAnimation();
		mGestureDetector = new GestureDetector(new FlingGestureDetector());
		mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext,
				android.R.anim.decelerate_interpolator);
	}

	public void setPaddingWidth(int viewPaddingWidth) {
		mViewPaddingWidth = viewPaddingWidth;
	}

	public void setAnimationDuration(int animationDuration) {
		mAnimationDuration = animationDuration;
	}

	public void setSnapBorderRatio(float snapBorderRatio) {
		mSnapBorderRatio = snapBorderRatio;
	}

	public void setIsGalleryCircular(boolean isGalleryCircular) {

		if (mIsGalleryCircular != isGalleryCircular) {
			mIsGalleryCircular = isGalleryCircular;
			if (mCurrentPosition == getFirstPosition()) {
				// We need to reload the view immediately to the left to change
				// it to circular view or blank
				mViews[getPrevViewNumber(mCurrentViewNumber)]
						.recycleView(getPrevPosition(mCurrentPosition));
			}

			if (mCurrentPosition == getLastPosition()) {
				// We need to reload the view immediately to the right to change
				// it to circular view or blank
				mViews[getNextViewNumber(mCurrentViewNumber)]
						.recycleView(getNextPosition(mCurrentPosition));
			}
		}
	}

	public int getGalleryCount() {
		return (mAdapter == null) ? 0 : mAdapter.getCount();
	}

	public int getFirstPosition() {
		return 0;
	}

	public int getLastPosition() {
		return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
	}

	private int getPrevPosition(int relativePosition) {
		int prevPosition = relativePosition - 1;

		if (prevPosition < getFirstPosition()) {
			prevPosition = getFirstPosition() - 1;
			if (mIsGalleryCircular == true) {
				prevPosition = getLastPosition();
			}
		}

		return prevPosition;
	}

	private int getNextPosition(int relativePosition) {
		int nextPosition = relativePosition + 1;
		if (nextPosition > getLastPosition()) {
			nextPosition = getLastPosition() + 1;

			if (mIsGalleryCircular == true) {
				nextPosition = getFirstPosition();
			}
		}

		return nextPosition;
	}

	private int getPrevViewNumber(int relativeViewNumber) {
		return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
	}

	private int getNextViewNumber(int relativeViewNumber) {
		return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);

		// Calculate our view width
		mGalleryWidth = right - left;
		if (changed == true) {

			// Position views at correct starting offsets
			mViews[0].setOffset(0, 0, mCurrentViewNumber);
			mViews[1].setOffset(0, 0, mCurrentViewNumber);
			mViews[2].setOffset(0, 0, mCurrentViewNumber);
		}
	}

	public void setAdapter(Adapter adapter) {
		mAdapter = adapter;
		mCurrentPosition = 0;
		mCurrentViewNumber = 0;

		// Load the initial views from adapter
		mViews[0].recycleView(mCurrentPosition);
		mViews[1].recycleView(getNextPosition(mCurrentPosition));
		mViews[2].recycleView(getPrevPosition(mCurrentPosition));

		// Position views at correct starting offsets
		mViews[0].setOffset(0, 0, mCurrentViewNumber);
		mViews[1].setOffset(0, 0, mCurrentViewNumber);
		mViews[2].setOffset(0, 0, mCurrentViewNumber);
	}

	private int getViewOffset(int viewNumber, int relativeViewNumber) {

		// Determine width including configured padding width
		int offsetWidth = mGalleryWidth + mViewPaddingWidth;

		// Position the previous view one measured width to left
		if (viewNumber == getPrevViewNumber(relativeViewNumber)) {
			return offsetWidth;
		}

		// Position the next view one measured width to the right
		if (viewNumber == getNextViewNumber(relativeViewNumber)) {
			return offsetWidth * -1;
		}

		return 0;
	}

	void movePrevious() {
		// Slide to previous view
		mFlingDirection = 1;
		processGesture();
	}

	void moveNext() {
		// Slide to next view
		mFlingDirection = -1;
		processGesture();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_DPAD_LEFT:
			movePrevious();
			return true;
		case KeyEvent.KEYCODE_DPAD_RIGHT:
			moveNext();
			return true;

		case KeyEvent.KEYCODE_DPAD_CENTER:
		case KeyEvent.KEYCODE_ENTER:
		}

		return super.onKeyDown(keyCode, event);
	}

	public boolean onGalleryTouchEvent(MotionEvent event) {
		boolean consumed = mGestureDetector.onTouchEvent(event);
		if (event.getAction() == MotionEvent.ACTION_UP) {
			if (mIsTouched || mIsDragging) {
				processScrollSnap();
				processGesture();
			}
		}

		return consumed;
	}

	void processGesture() {
		int newViewNumber = mCurrentViewNumber;
		int reloadViewNumber = 0;
		int reloadPosition = 0;

		mIsTouched = false;
		mIsDragging = false;

		if (mFlingDirection > 0) {
			if (mCurrentPosition > getFirstPosition()
					|| mIsGalleryCircular == true) {
				// Determine previous view and outgoing view to recycle
				newViewNumber = getPrevViewNumber(mCurrentViewNumber);
				mCurrentPosition = getPrevPosition(mCurrentPosition);
				reloadViewNumber = getNextViewNumber(mCurrentViewNumber);
				reloadPosition = getPrevPosition(mCurrentPosition);
			}
		}

		if (mFlingDirection < 0) {
			if (mCurrentPosition < getLastPosition()
					|| mIsGalleryCircular == true) {
				// Determine the next view and outgoing view to recycle
				newViewNumber = getNextViewNumber(mCurrentViewNumber);
				mCurrentPosition = getNextPosition(mCurrentPosition);
				reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);
				reloadPosition = getNextPosition(mCurrentPosition);
			}
		}

		if (newViewNumber != mCurrentViewNumber) {
			mCurrentViewNumber = newViewNumber;
			// Reload outgoing view from adapter in new position
			mViews[reloadViewNumber].recycleView(reloadPosition);
		}

		// Ensure input focus on the current view
		mViews[mCurrentViewNumber].requestFocus();
		// Run the slide animations for view transitions
		mAnimation.prepareAnimation(mCurrentViewNumber);
		this.startAnimation(mAnimation);
		// Reset fling state
		mFlingDirection = 0;
	}

	void processScrollSnap() {
		// Snap to next view if scrolled passed snap position
		float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;
		int rollOffset = mGalleryWidth - (int) rollEdgeWidth;
		int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
		if (currentOffset <= rollOffset * -1) {
			// Snap to previous view
			mFlingDirection = 1;
		}

		if (currentOffset >= rollOffset) {
			// Snap to next view
			mFlingDirection = -1;
		}
	}

	private class FlingGalleryView {
		private int mViewNumber;
		private FrameLayout mParentLayout;
		private FrameLayout mInvalidLayout = null;
		private LinearLayout mInternalLayout = null;
		private View mExternalView = null;

		public FlingGalleryView(int viewNumber, FrameLayout parentLayout) {
			mViewNumber = viewNumber;
			mParentLayout = parentLayout;
			// Invalid layout is used when outside gallery
			mInvalidLayout = new FrameLayout(mContext);
			mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(
					LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

			// Internal layout is permanent for duration
			mInternalLayout = new LinearLayout(mContext);
			mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(
					LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
			mParentLayout.addView(mInternalLayout);
		}

		public void recycleView(int newPosition) {
			if (mExternalView != null) {
				mInternalLayout.removeView(mExternalView);
			}

			if (mAdapter != null) {
				if (newPosition >= getFirstPosition()
						&& newPosition <= getLastPosition()) {
					mExternalView = mAdapter.getView(newPosition,
							mExternalView, mInternalLayout);
				} else {
					mExternalView = mInvalidLayout;
				}
			}

			if (mExternalView != null) {
				mInternalLayout.addView(mExternalView,
						new LinearLayout.LayoutParams(
								LayoutParams.MATCH_PARENT,
								LayoutParams.MATCH_PARENT));
			}
		}

		public void setOffset(int xOffset, int yOffset, int relativeViewNumber) {
			// Scroll the target view relative to its own position relative to
			// currently displayed view
			mInternalLayout.scrollTo(
					getViewOffset(mViewNumber, relativeViewNumber) + xOffset,
					yOffset);
		}

		public int getCurrentOffset() {
			// Return the current scroll position
			return mInternalLayout.getScrollX();
		}

		public void requestFocus() {
			mInternalLayout.requestFocus();
		}
	}

	private class FlingGalleryAnimation extends Animation {
		private boolean mIsAnimationInProgres;
		private int mRelativeViewNumber;
		private int mInitialOffset;
		private int mTargetOffset;
		private int mTargetDistance;

		public FlingGalleryAnimation() {
			mIsAnimationInProgres = false;
			mRelativeViewNumber = 0;
			mInitialOffset = 0;
			mTargetOffset = 0;
			mTargetDistance = 0;
		}

		public void prepareAnimation(int relativeViewNumber) {
			// If we are animating relative to a new view
			if (mRelativeViewNumber != relativeViewNumber) {
				if (mIsAnimationInProgres == true) {
					// We only have three views so if requested again to animate
					// in same direction we must snap
					int newDirection = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1
							: -1;

					int animDirection = (mTargetDistance < 0) ? 1 : -1;
					// If animation in same direction
					if (animDirection == newDirection) {
						// Ran out of time to animate so snap to the target
						// offset
						mViews[0].setOffset(mTargetOffset, 0,
								mRelativeViewNumber);
						mViews[1].setOffset(mTargetOffset, 0,
								mRelativeViewNumber);
						mViews[2].setOffset(mTargetOffset, 0,
								mRelativeViewNumber);
					}
				}

				// Set relative view number for animation
				mRelativeViewNumber = relativeViewNumber;
			}
			// Note: In this implementation the targetOffset will always be zero
			// as we are centering the view; but we include the calculations of
			// targetOffset and targetDistance for use in future implementations
			mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();
			mTargetOffset = getViewOffset(mRelativeViewNumber,
					mRelativeViewNumber);
			mTargetDistance = mTargetOffset - mInitialOffset;
			// Configure base animation properties
			this.setDuration(mAnimationDuration);
			this.setInterpolator(mDecelerateInterpolater);

			// Start/continued animation
			mIsAnimationInProgres = true;
		}

		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation transformation) {
			// Ensure interpolatedTime does not over-shoot then calculate new
			// offset
			interpolatedTime = (interpolatedTime > 1.0f) ? 1.0f
					: interpolatedTime;
			int offset = mInitialOffset
					+ (int) (mTargetDistance * interpolatedTime);

			for (int viewNumber = 0; viewNumber < 3; viewNumber++) {
				// Only need to animate the visible views as the other view will
				// always be off-screen
				if ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber))
						|| (mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber))) {
					mViews[viewNumber]
							.setOffset(offset, 0, mRelativeViewNumber);
				}
			}

		}

		@Override
		public boolean getTransformation(long currentTime,
				Transformation outTransformation) {
			if (super.getTransformation(currentTime, outTransformation) == false) {
				// Perform final adjustment to offsets to cleanup animation
				mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
				mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
				mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);

				// Reached the animation target
				mIsAnimationInProgres = false;

				return false;
			}

			// Cancel if the screen touched
			if (mIsTouched || mIsDragging) {
				// Note that at this point we still consider ourselves to be
				// animating
				// because we have not yet reached the target offset; its just
				// that the
				// user has temporarily interrupted the animation with a touch
				// gesture

				return false;
			}
			return true;
		}
	}

	private class FlingGestureDetector extends
			GestureDetector.SimpleOnGestureListener {

		@Override
		public boolean onDown(MotionEvent e) {
			// Stop animation
			mIsTouched = true;

			// Reset fling state
			mFlingDirection = 0;
			return true;
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			if (e2.getAction() == MotionEvent.ACTION_MOVE) {
				if (mIsDragging == false) {
					// Stop animation
					mIsTouched = true;

					// Reconfigure scroll
					mIsDragging = true;
					mFlingDirection = 0;
					mScrollTimestamp = System.currentTimeMillis();
					mCurrentOffset = mViews[mCurrentViewNumber]
							.getCurrentOffset();
				}

				float maxVelocity = mGalleryWidth
						/ (mAnimationDuration / 1000.0f);
				long timestampDelta = System.currentTimeMillis()
						- mScrollTimestamp;
				float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f);
				float currentScrollDelta = e1.getX() - e2.getX();
				if (currentScrollDelta < maxScrollDelta * -1)
					currentScrollDelta = maxScrollDelta * -1;
				if (currentScrollDelta > maxScrollDelta)
					currentScrollDelta = maxScrollDelta;
				int scrollOffset = Math.round(mCurrentOffset
						+ currentScrollDelta);

				// We can't scroll more than the width of our own frame layout
				if (scrollOffset >= mGalleryWidth)
					scrollOffset = mGalleryWidth;
				if (scrollOffset <= mGalleryWidth * -1)
					scrollOffset = mGalleryWidth * -1;
				mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);
				mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);
				mViews[2].setOffset(scrollOffset, 0, mCurrentViewNumber);
			}

			return false;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			if (Math.abs(e1.getY() - e2.getY()) <= swipe_max_off_path) {
				if (e2.getX() - e1.getX() > swipe_min_distance
						&& Math.abs(velocityX) > swipe_threshold_veloicty) {
					movePrevious();
				}

				if (e1.getX() - e2.getX() > swipe_min_distance
						&& Math.abs(velocityX) > swipe_threshold_veloicty) {
					moveNext();
				}
			}

			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// Finalise scrolling
			mFlingDirection = 0;
			processGesture();
		}

		@Override
		public void onShowPress(MotionEvent e) {
		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// Reset fling state
			mFlingDirection = 0;
			return false;
		}
	}
}



MainActivity.java

Java代码 复制代码 收藏代码
  1. package com.iaiai.fg;   
  2.   
  3. import android.app.Activity;   
  4. import android.os.Bundle;   
  5.   
  6. import android.content.Context;   
  7. import android.graphics.Color;   
  8. import android.util.Log;   
  9. import android.view.Gravity;   
  10. import android.view.MotionEvent;   
  11. import android.view.View;   
  12. import android.view.ViewGroup;   
  13. import android.view.View.OnClickListener;   
  14. import android.widget.ArrayAdapter;   
  15. import android.widget.Button;   
  16. import android.widget.CheckBox;   
  17. import android.widget.EditText;   
  18. import android.widget.LinearLayout;   
  19. import android.widget.TableLayout;   
  20. import android.widget.TextView;   
  21.   
  22. /**  
  23.  *   
  24.  * <p>  
  25.  * Title: MainActivity.java  
  26.  * </p>  
  27.  * <p>  
  28.  * E-Mail: 176291935@qq.com  
  29.  * </p>  
  30.  * <p>  
  31.  * QQ: 176291935  
  32.  * </p>  
  33.  * <p>  
  34.  * Http: iaiai.iteye.com  
  35.  * </p>  
  36.  * <p>  
  37.  * Create time: 2012-7-7 上午10:18:53  
  38.  * </p>  
  39.  *   
  40.  * @author 丸子  
  41.  * @version 0.0.1  
  42.  */  
  43. public class MainActivity extends Activity {   
  44.     private final int color_red = Color.argb(10020000);   
  45.     private final int color_green = Color.argb(10002000);   
  46.     private final int color_blue = Color.argb(10000200);   
  47.     private final int color_yellow = Color.argb(1002002000);   
  48.     private final int color_purple = Color.argb(1002000200);   
  49.     private final String[] mLabelArray = { "View1""View2""View3""View4",   
  50.             "View5" };   
  51.     private final int[] mColorArray = { color_red, color_green, color_blue,   
  52.             color_yellow, color_purple };   
  53.   
  54.     private FlingGallery mGallery;   
  55.     private CheckBox mCheckBox;   
  56.   
  57.     // Note: The following handler is critical to correct function of   
  58.     // the FlingGallery class. This enables the FlingGallery class to   
  59.     // detect when the motion event has ended by finger being lifted   
  60.   
  61.     @Override  
  62.     public boolean onTouchEvent(MotionEvent event) {   
  63.         return mGallery.onGalleryTouchEvent(event);   
  64.     }   
  65.   
  66.     public void onCreate(Bundle savedInstanceState) {   
  67.         super.onCreate(savedInstanceState);   
  68.         mGallery = new FlingGallery(this);   
  69.         mGallery.setPaddingWidth(5);   
  70.   
  71.         mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(),   
  72.                 android.R.layout.simple_list_item_1, mLabelArray) {   
  73.   
  74.             @Override  
  75.             public View getView(int position, View convertView, ViewGroup parent) {   
  76.                 Log.d("111""count=" + position);   
  77.                 // if (convertView != null && convertView instanceof   
  78.                 // GalleryViewItem)   
  79.                 // {   
  80.                 // GalleryViewItem galleryView = (GalleryViewItem) convertView;   
  81.                 //   
  82.                 // galleryView.mEdit1.setText("");   
  83.                 // galleryView.mText1.setText(mLabelArray[position]);   
  84.                 // galleryView.mText1.setBackgroundColor(mColorArray[position]);   
  85.                 // galleryView.mText2.setText(mLabelArray[position]);   
  86.                 // galleryView.mText2.setBackgroundColor(mColorArray[position]);   
  87.                 //   
  88.                 // Log.d("111", "count="+position);   
  89.                 //   
  90.                 // return galleryView;   
  91.                 //   
  92.                 // }   
  93.   
  94.                 return new GalleryViewItem(getApplicationContext(), position);   
  95.             }   
  96.   
  97.         });   
  98.   
  99.         LinearLayout layout = new LinearLayout(getApplicationContext());   
  100.         layout.setOrientation(LinearLayout.VERTICAL);   
  101.   
  102.         LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(   
  103.                 LinearLayout.LayoutParams.MATCH_PARENT,   
  104.                 LinearLayout.LayoutParams.MATCH_PARENT);   
  105.         layoutParams.setMargins(10101010);   
  106.         layoutParams.weight = 1.0f;   
  107.         layout.addView(mGallery, layoutParams);   
  108.         mCheckBox = new CheckBox(getApplicationContext());   
  109.         mCheckBox.setText("Gallery is Circular");   
  110.         mCheckBox.setText("Gallery is Circular");   
  111.         mCheckBox.setPadding(5010010);   
  112.         mCheckBox.setTextSize(30);   
  113.         mCheckBox.setChecked(true);   
  114.         mCheckBox.setOnClickListener(new OnClickListener() {   
  115.   
  116.             @Override  
  117.             public void onClick(View view) {   
  118.                 mGallery.setIsGalleryCircular(mCheckBox.isChecked());   
  119.             }   
  120.         });   
  121.   
  122.         layout.addView(mCheckBox, new LinearLayout.LayoutParams(   
  123.                 LinearLayout.LayoutParams.MATCH_PARENT,   
  124.                 LinearLayout.LayoutParams.WRAP_CONTENT));   
  125.         setContentView(layout);   
  126.     }   
  127.   
  128.     private class GalleryViewItem extends TableLayout {   
  129.   
  130.         private EditText mEdit1;   
  131.         private TextView mText1;   
  132.         private TextView mText2;   
  133.         private Button mButton1;   
  134.         private Button mButton2;   
  135.   
  136.         public GalleryViewItem(Context context, int position) {   
  137.             super(context);   
  138.   
  139.             this.setOrientation(LinearLayout.VERTICAL);   
  140.             this.setLayoutParams(new LinearLayout.LayoutParams(   
  141.                     LinearLayout.LayoutParams.MATCH_PARENT,   
  142.                     LinearLayout.LayoutParams.MATCH_PARENT));   
  143.             mEdit1 = new EditText(context);   
  144.   
  145.             this.addView(mEdit1, new LinearLayout.LayoutParams(   
  146.                     LinearLayout.LayoutParams.MATCH_PARENT,   
  147.                     LinearLayout.LayoutParams.WRAP_CONTENT));   
  148.             mText1 = new TextView(context);   
  149.             mText1.setText(mLabelArray[position]);   
  150.             mText1.setTextSize(30);   
  151.             mText1.setGravity(Gravity.LEFT);   
  152.             mText1.setBackgroundColor(mColorArray[position]);   
  153.             this.addView(mText1, new LinearLayout.LayoutParams(   
  154.                     LinearLayout.LayoutParams.MATCH_PARENT,   
  155.                     LinearLayout.LayoutParams.WRAP_CONTENT));   
  156.             mButton1 = new Button(context);   
  157.             mButton1.setText("<<");   
  158.             mButton1.setGravity(Gravity.LEFT);   
  159.             mButton1.setOnClickListener(new OnClickListener() {   
  160.   
  161.                 @Override  
  162.                 public void onClick(View view) {   
  163.                     mGallery.movePrevious();   
  164.                 }   
  165.   
  166.             });   
  167.   
  168.             this.addView(mButton1, new LinearLayout.LayoutParams(   
  169.                     LinearLayout.LayoutParams.MATCH_PARENT,   
  170.                     LinearLayout.LayoutParams.WRAP_CONTENT));   
  171.             mButton2 = new Button(context);   
  172.             mButton2.setText(">>");   
  173.             mButton2.setGravity(Gravity.RIGHT);   
  174.             mButton2.setOnClickListener(new OnClickListener() {   
  175.   
  176.                 @Override  
  177.                 public void onClick(View view) {   
  178.                     mGallery.moveNext();   
  179.                 }   
  180.             });   
  181.   
  182.             this.addView(mButton2, new LinearLayout.LayoutParams(   
  183.                     LinearLayout.LayoutParams.MATCH_PARENT,   
  184.                     LinearLayout.LayoutParams.WRAP_CONTENT));   
  185.   
  186.             mText2 = new TextView(context);   
  187.             mText2.setText(mLabelArray[position]);   
  188.             mText2.setTextSize(30);   
  189.             mText2.setGravity(Gravity.RIGHT);   
  190.             mText2.setBackgroundColor(mColorArray[position]);   
  191.             this.addView(mText2, new LinearLayout.LayoutParams(   
  192.                     LinearLayout.LayoutParams.MATCH_PARENT,   
  193.                     LinearLayout.LayoutParams.MATCH_PARENT, 1));   
  194.         }   
  195.     }   
  196.   
  197. }  
posted @ 2012-12-25 10:25  圣诞树下的猫  阅读(110)  评论(0)    收藏  举报