自定义android循环拖动组件

openkk 13年前

package com.sunny.pager;    import java.util.HashMap;  import java.util.Map;    import android.app.Activity;  import android.content.Context;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.graphics.Color;  import android.os.Bundle;  import android.os.Environment;  import android.util.Log;  import android.view.MotionEvent;  import android.view.View;  import android.view.View.OnTouchListener;  import android.view.ViewGroup;  import android.view.Window;  import android.view.WindowManager;  import android.view.animation.AlphaAnimation;  import android.view.animation.Animation.AnimationListener;  import android.view.animation.AnimationSet;  import android.view.animation.ScaleAnimation;  import android.widget.BaseAdapter;  import android.widget.ImageView;  import android.widget.LinearLayout;  import android.widget.TextView;  import android.widget.VideoView;    public class ViewpagertestActivity extends Activity {   private static Context mContext;   private MyFrameLayout mGallery;   int[] color = {Color.CYAN, Color.BLUE, Color.GREEN, Color.RED, Color.GRAY, Color.YELLOW, Color.DKGRAY,     Color.LTGRAY, Color.MAGENTA};   static String[] str = {"http://www.yoho.cn", "http://www.hibox.com/web/"};   private int count = 9;   /** Called when the activity is first created. */     public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);    /** 标题是属于View的,所以窗口所有的修饰部分被隐藏后标题依然有效 */    requestWindowFeature(Window.FEATURE_NO_TITLE);    Map<Integer, int[]> mapIndexs = new HashMap<Integer, int[]>();    mapIndexs.put(0, new int[]{0, 1, 2});    mapIndexs.put(1, new int[]{3, 4, 5});    mapIndexs.put(2, new int[]{6, 7, 8});    mGallery = new MyFrameLayout(this, mapIndexs);    setContentView(mGallery);      mContext = this;    // LinearLayout layout = (LinearLayout) findViewById(R.id.main_layout);      mGallery.setAdapter(baseAdapter);    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,      LinearLayout.LayoutParams.FILL_PARENT);    // layout.addView(mGallery, layoutParams);   }     @Override   public boolean onTouchEvent(MotionEvent event) {    // TODO Auto-generated method stub    //requestDisallowInterceptTouchEvent(true);    Boolean falg = mGallery.onGalleryTouchEvent(event);    return falg;   }     static class ViewHolder {    // TextView tView;    LinearLayout layout;    TextView tView;    ImageView image;    VideoView video;   }   public static Bitmap decodeSampledBitmapFromResource(String iamgePath, int reqWidth, int reqHeight) {    // First decode with inJustDecodeBounds=true to check dimensions    final BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    BitmapFactory.decodeFile(iamgePath, options);    // Calculate inSampleSize    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);    // Decode bitmap with inSampleSize set    options.inJustDecodeBounds = false;    return BitmapFactory.decodeFile(iamgePath, options);   }   public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {    // Raw height and width of image    final int height = options.outHeight;    final int width = options.outWidth;    int inSampleSize = 1;    if (height > reqHeight || width > reqWidth) {     if (width > height) {      inSampleSize = Math.round((float) height / (float) reqHeight);     } else {      inSampleSize = Math.round((float) width / (float) reqWidth);     }    }    return inSampleSize;   }     BaseAdapter baseAdapter = new BaseAdapter() {    ViewHolder holder = new ViewHolder();    @Override    public View getView(int position, View convertView, ViewGroup parent) {     holder.layout = new LinearLayout(mContext);     holder.layout.setOrientation(LinearLayout.VERTICAL);     holder.tView = new TextView(mContext);     holder.layout.addView(holder.tView);     if (position > 5) {      holder.tView.setText("第 3" + "屏 第" + (position - 5) + "页");      holder.tView.setTextSize(18);     } else if (position > 2) {      holder.tView.setText("第 2" + "屏 第" + (position - 2) + "页");      holder.tView.setTextSize(18);     } else {      holder.tView.setText("第 1" + "屏 第" + (position + 1) + "页");      holder.tView.setTextSize(18);     }       holder.image = new ImageView(mContext);       holder.image.setImageBitmap(decodeSampledBitmapFromResource(Environment.getExternalStorageDirectory()       + "/2234567.jpg", 300, 200));     if ((position + 1) % 2 == 0) {      LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(300, 200);      lp.setMargins(0, 0, 0, 0);        holder.layout.addView(holder.image, lp);      holder.video = new VideoView(mContext);      holder.video.setVideoPath("/mnt/sdcard/123456.mp4");      holder.video.start();      LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(300, 200);      lp1.setMargins(50, 220, 0, 0);      holder.layout.addView(holder.video, lp1);     } else {      LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(300, 200);      lp.setMargins(0, 0, 0, 0);      holder.layout.addView(holder.image, lp);        ImageView imageView = new ImageView(mContext);      imageView.setBackgroundColor(0xff123456);        LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(300, 200);      lp1.setMargins(0, 220, 0, 0);        /*       * imageView.setOnClickListener(new OnClickListener() {       *        * @Override public void onClick(View v) { // TODO       * Auto-generated method stub AnimationSet animation =       * getFadeInAnimation(3000, 0, null); Toast.makeText(mContext,       * "动画----开始", Toast.LENGTH_SHORT).show();       * holder.image.startAnimation(animation); } });       */      AnimationSet animation = getFadeInAnimation(3000, 100, null);      holder.image.startAnimation(animation);      imageView.setOnTouchListener(new OnTouchListener() {       public boolean onTouch(View v, MotionEvent event) {        if (event.getAction() == MotionEvent.ACTION_MOVE) {        }        if (event.getAction() == MotionEvent.ACTION_DOWN) {         AnimationSet animation = getFadeInAnimation(3000, 100, null);         holder.image.startAnimation(animation);         // Toast.makeText(mContext, "动画----开始",         // Toast.LENGTH_SHORT).show();         return false;        }                return false;       }      });      holder.layout.addView(imageView, lp1);     }     holder.layout.setBackgroundColor(color[position]);     // holder.layout.setTag(holder);     return holder.layout;    }      @Override    public long getItemId(int position) {     // TODO Auto-generated method stub     return position;    }      @Override    public Object getItem(int position) {     // TODO Auto-generated method stub     return position;    }      @Override    public int getCount() {     // TODO Auto-generated method stub     return count;    }   };     public AnimationSet getFadeInAnimation(long durationMillis, long delay, AnimationListener listener) {    AlphaAnimation alphaAnim = null;    ScaleAnimation scaleAnimation = null;    if (delay < 0)     delay = 0;    if (durationMillis <= 100)     durationMillis = 300;    AnimationSet animationSet = new AnimationSet(true);    alphaAnim = new AlphaAnimation(1.0f, 0.0f);    scaleAnimation = new ScaleAnimation(1.0f, 0.1f, 1.0f, 0.1f);    alphaAnim.setDuration(durationMillis);    scaleAnimation.setDuration(durationMillis);    alphaAnim.setStartOffset(delay);    scaleAnimation.setStartOffset(delay);    animationSet.addAnimation(alphaAnim);    animationSet.addAnimation(scaleAnimation);    animationSet.setFillAfter(true);    if (listener != null)     alphaAnim.setAnimationListener(listener);    Log.v("animationSet", "Get animationSet: "+animationSet.toString());    return animationSet;   }  }
自定义逐渐基本功能实现,现在公开源码。

其中点击触发动画事件未能解决,ontouch 的down 事件响应,但是动画就是不播放,长安才能在首页播放,希望高手给点建议:

 

 

源码:

package com.sunny.pager;    import java.util.ArrayList;  import java.util.Map;  import java.util.Set;    import android.R.integer;  import android.content.Context;  import android.database.DataSetObserver;  import android.util.Log;  import android.view.GestureDetector;  import android.view.Gravity;  import android.view.KeyEvent;  import android.view.MotionEvent;  import android.view.View;  import android.view.ViewGroup;  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;  import android.widget.Toast;    // 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    public class MyFrameLayout extends FrameLayout {   // Constants     private final int swipe_min_distance = 120;   private final int swipe_max_off_path = 250;   private final int swipe_threshold_veloicty = 350;     // Properties     private int mViewPaddingWidth = 0;   private int mAnimationDuration = 250;   private float mSnapBorderRatio = 0.5f;   private boolean mIsGalleryCircular = true;     // Members     private int mGalleryWidth = 0;   private int mGalleryHeight = 0;   private boolean mIsTouched = false;   private boolean mIsDragging = false;   private int[] mCurrentOffset = new int[2];   private long mScrollTimestamp = 0;   private int mFlingDirection = 0;   private int mCurrentPosition = 0;   public int mCurrentViewNumber = 0;     private Context mContext;   private Adapter mAdapter;   private FlingGalleryView[] mViews;   private FlingGalleryAnimation mAnimation;   private GestureDetector mGestureDetector;   private Interpolator mDecelerateInterpolater;   Map<Integer, int[]> mapIndexs;   private static final int MOVE_UP_DOWN = 0;   private static final int MOVE_LEFT_RIGHT = 1;   private int MoveStyle = -1;   private boolean direction = true;      //private int h_viewnumber;   //private int v_viewnumber;   private ArrayList<Integer> _xViewNumbers=new ArrayList<Integer>();   private ArrayList<Integer> _yViewNumbers=new ArrayList<Integer>();   public MyFrameLayout(Context context, Map<Integer, int[]> mapIndexs) {    super(context);    this.mapIndexs = mapIndexs;    mContext = context;    mAdapter = null;      mViews = new FlingGalleryView[5];    _xViewNumbers.add(1);    _xViewNumbers.add(0);    _xViewNumbers.add(2);    _yViewNumbers.add(3);    _yViewNumbers.add(0);    _yViewNumbers.add(4);    mViews[0] = new FlingGalleryView(0, this);    mViews[1] = new FlingGalleryView(1, this);    mViews[2] = new FlingGalleryView(2, this);    mViews[3] = new FlingGalleryView(3, this);    mViews[4] = new FlingGalleryView(4, 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_RL()) {      // We need to reload the view immediately to the left to change      // it to circular view or blank      mViews[getPrevViewNumber_RL(mCurrentViewNumber)].recycleView(getPrevPosition_RL(mCurrentPosition));     }       if (mCurrentPosition == getLastPosition_RL()) {      // We need to reload the view immediately to the right to change      // it to circular view or blank      mViews[getNextViewNumber_RL(mCurrentViewNumber)].recycleView(getNextPosition_RL(mCurrentPosition));     }       if (mCurrentPosition == getFirstPosition_UD()) {      mViews[getPrevViewNumber_UD(mCurrentViewNumber)].recycleView(getPrevPosition_UD(mCurrentPosition));     }     if (mCurrentPosition == getLastPosition_UD()) {      mViews[getNextViewNumber_UD(mCurrentViewNumber)].recycleView(getPrevPosition_UD(mCurrentPosition));     }    }   }     public int getGalleryCount() {    return (mAdapter == null) ? 0 : mAdapter.getCount();   }   private int[] getXindexAndYindex(int value){    Set<Integer> set=mapIndexs.keySet();    int x_index=-1;    for(Integer i : set){     x_index++;     int[] temp=mapIndexs.get(i);     int y_index=-1;     for(int j :temp){      y_index++;      if(j==value)       return new int[]{x_index,y_index};     }    }    return new int[]{0,0};       }   public int getFirstPosition_RL() {    return 0;   }     public int getLastPosition_RL() {    Integer[] vs = mapIndexs.keySet().toArray(new Integer[0]);    return vs[vs.length - 1];   }     public int getLastPosition_All() {    return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;   }     public int getFirstPosition_UD() {    int x_index=getXindexAndYindex(mCurrentPosition)[0];    return mapIndexs.get(x_index)[0];   }     public int getLastPosition_UD() {    int x_index=getXindexAndYindex(mCurrentPosition)[0];    return mapIndexs.get(x_index)[mapIndexs.get(x_index).length - 1];   }     private int getPrevPosition_RL(int relativePosition) {    int length = mapIndexs.keySet().size();    int lastindex = length - 1;    int x_index=getXindexAndYindex(relativePosition)[0];    x_index--;    if (x_index < 0) {     return mapIndexs.get(lastindex)[0];    } else {     return mapIndexs.get(x_index)[0];    }   }     private int getPrevPosition_UD(int relativePosition) {    int x_index=getXindexAndYindex(relativePosition)[0];    int y_index=getXindexAndYindex(relativePosition)[1];    int length = mapIndexs.get(x_index).length;    int lastindex = length - 1;    y_index--;    if (y_index < 0) {     return mapIndexs.get(x_index)[lastindex];    } else {     return mapIndexs.get(x_index)[y_index];    }   }     private int getNextPosition_RL(int relativePosition) {    int length = mapIndexs.keySet().size();    int x_index=getXindexAndYindex(relativePosition)[0];    int lastindex = length - 1;    x_index++;    if (x_index > lastindex) {     return mapIndexs.get(0)[0];    } else {     return mapIndexs.get(x_index)[0];    }   }     private int getNextPosition_UD(int relativePosition) {    int x_index=getXindexAndYindex(relativePosition)[0];    int y_index=getXindexAndYindex(relativePosition)[1];    int length = mapIndexs.get(x_index).length;    int lastindex = length - 1;    y_index++;    if (y_index > lastindex) {     return mapIndexs.get(x_index)[0];    } else {     return mapIndexs.get(x_index)[y_index];    }   }     private int getPrevViewNumber_RL(int relativeViewNumber) {    int index=_xViewNumbers.indexOf(relativeViewNumber);    index=(index == 0) ? 2 : index - 1;    return _xViewNumbers.get(index);       }     private int getNextViewNumber_RL(int relativeViewNumber) {        int index=_xViewNumbers.indexOf(relativeViewNumber);    index=(index == 2) ? 0: index + 1;    return _xViewNumbers.get(index);    // return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;   }     private int getPrevViewNumber_UD(int relativeViewNumber) {    int index=_yViewNumbers.indexOf(relativeViewNumber);    index=(index == 0) ? 2 : index - 1;    Log.v("index-------------", index+"");    return _yViewNumbers.get(index);         }     private int getNextViewNumber_UD(int relativeViewNumber) {        int index=_yViewNumbers.indexOf(relativeViewNumber);    index=(index == 2) ? 0: index + 1;    return _yViewNumbers.get(index);   }     @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);    mGalleryHeight = (bottom - top);    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);     mViews[3].setOffset(0, 0, mCurrentViewNumber);     mViews[4].setOffset(0, 0, mCurrentViewNumber);    }   }     DataSetObserver observer = new DataSetObserver() {    public void onChanged() {     // mCurrentPosition = 0;     // mCurrentViewNumber = 0;     // Load the initial views from adapter     mViews[0].recycleView(0);     mViews[1].recycleView(getNextPosition_RL(0));     mViews[2].recycleView(getPrevPosition_RL(0));     mViews[3].recycleView(getNextPosition_UD(0));     mViews[4].recycleView(getPrevPosition_UD(0));     // Position views at correct starting offsets     mViews[0].setOffset(0, 0, 0);     mViews[1].setOffset(0, 0, 0);     mViews[2].setOffset(0, 0, 0);     mViews[3].setOffset(0, 0, 0);     mViews[4].setOffset(0, 0, 0);     mViews[mCurrentViewNumber].requestFocus();    }   };     public void setAdapter(Adapter adapter) {    if (null != mAdapter && adapter != null && mAdapter.equals(adapter)) {     mAdapter.unregisterDataSetObserver(observer);    }    mAdapter = adapter;      mAdapter.registerDataSetObserver(observer);      mCurrentPosition = 0;    mCurrentViewNumber = 0;      // Load the initial views from adapter    mViews[0].recycleView(mCurrentPosition);    mViews[1].recycleView(getPrevPosition_RL(mCurrentPosition));    mViews[2].recycleView(getNextPosition_RL(mCurrentPosition));    mViews[3].recycleView(getPrevPosition_UD(mCurrentPosition));    mViews[4].recycleView(getNextPosition_UD(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);    mViews[3].setOffset(0, 0, mCurrentViewNumber);    mViews[4].setOffset(0, 0, mCurrentViewNumber);   }     private int getViewOffset(int viewNumber, int relativeViewNumber) {                int offsetWidth = mGalleryWidth + mViewPaddingWidth;    // Position the previous view one measured width to left    if (viewNumber == getPrevViewNumber_RL(relativeViewNumber)) {     return offsetWidth;    }    // Position the next view one measured width to the right    if (viewNumber == getNextViewNumber_RL(relativeViewNumber)) {     return offsetWidth * -1;    }    int offsetHeight = mGalleryHeight + mViewPaddingWidth;    // Position the previous view one measured width to left    if (viewNumber == (getPrevViewNumber_UD(relativeViewNumber))) {     return offsetHeight;    }    // Position the next view one measured width to the right    int num = getNextViewNumber_UD(relativeViewNumber);    if (viewNumber == (num)) {     return offsetHeight * -1;    }    return 0;   }     public void movePrevious_RL() {    // Slide to previous view    mFlingDirection = 1;    processGesture();   }     public void moveNext_RL() {    // Slide to next view    mFlingDirection = -1;    processGesture();   }     public void movePrevious_UD() {    // Slide to previous view    mFlingDirection = 2;    processGesture();   }     public void moveNext_UD() {    // Slide to next view    mFlingDirection = -2;    processGesture();   }     @Override   public boolean onKeyDown(int keyCode, KeyEvent event) {    switch (keyCode) {     case KeyEvent.KEYCODE_DPAD_LEFT :      movePrevious_RL();      MoveStyle = MOVE_LEFT_RIGHT;      return true;       case KeyEvent.KEYCODE_DPAD_RIGHT :      moveNext_RL();      MoveStyle = MOVE_LEFT_RIGHT;      return true;     case KeyEvent.KEYCODE_DPAD_UP :      movePrevious_UD();      MoveStyle = MOVE_UP_DOWN;      return true;       case KeyEvent.KEYCODE_DPAD_DOWN :      moveNext_UD();      MoveStyle = MOVE_UP_DOWN;      return true;       case KeyEvent.KEYCODE_DPAD_CENTER :     case KeyEvent.KEYCODE_ENTER :    }      return super.onKeyDown(keyCode, event);   }     public boolean onGalleryTouchEvent(MotionEvent event) {    // TODO Auto-generated method stub    switch (event.getAction()) {     case MotionEvent.ACTION_DOWN : {      mLastMotionX = event.getX();      mLastMotionY = event.getY();      break;     }     case MotionEvent.ACTION_MOVE : {      final float x = event.getX();;      final float dx = x - mLastMotionX;      final float xDiff = Math.abs(dx);      final float y = event.getY();      final float yDiff = Math.abs(y - mLastMotionY);      if (xDiff > yDiff) {       MoveStyle = MOVE_LEFT_RIGHT;      } else {       if (yDiff > xDiff) {        MoveStyle = MOVE_UP_DOWN;       }      }      break;     }    }    boolean consumed=false;    if(direction){     consumed = mGestureDetector.onTouchEvent(event);    }    if (event.getAction() == MotionEvent.ACTION_UP) {     //Toast.makeText(mContext, "ACTION_UP", Toast.LENGTH_SHORT).show();     if (mIsTouched || mIsDragging) {            direction = false;      processScrollSnap();      processGesture();      Toast.makeText(mContext, "processGesture", Toast.LENGTH_SHORT).show();      Log.v("ViewNumbers", "_xViewNumbers :"+ _xViewNumbers.get(0)+ _xViewNumbers.get(1)+ _xViewNumbers.get(2)+         "_yViewNumbers :"+ _yViewNumbers.get(0)+ _yViewNumbers.get(1)+ _yViewNumbers.get(2)  );     }    }    //Toast.makeText(mContext, "consumed : "+consumed, Toast.LENGTH_SHORT).show();    return consumed;   }   int recyclePositon;   int recycleViewNumber;     void processGesture() {    int newViewNumber = mCurrentViewNumber;    int reloadViewNumber = 0;    int reloadPosition = 0;    int reloadViewNumber_up = 0;    int reloadPosition_up = 0;    int reloadViewNumber_down = 0;    int reloadPosition_down = 0;      int reloadViewNumber_r = 0;    int reloadPosition_r = 0;    int reloadViewNumber_l = 0;    int reloadPosition_l = 0;    mIsTouched = false;    mIsDragging = false;      if (mFlingDirection == 1) {     if (mCurrentPosition > getFirstPosition_RL() || mIsGalleryCircular == true) {      // Determine previous view and outgoing view to recycle      newViewNumber = getPrevViewNumber_RL(mCurrentViewNumber);      mCurrentPosition = getPrevPosition_RL(mCurrentPosition);            recycleViewNumber=mCurrentViewNumber;      recyclePositon=getNextPosition_RL(mCurrentPosition);            reloadViewNumber = getNextViewNumber_RL(mCurrentViewNumber);      reloadPosition = getPrevPosition_RL(mCurrentPosition);        reloadPosition_up = getPrevPosition_UD(mCurrentPosition);      reloadViewNumber_up = getPrevViewNumber_UD(mCurrentViewNumber);        reloadPosition_down = getNextPosition_UD(mCurrentPosition);      reloadViewNumber_down = getNextViewNumber_UD(mCurrentViewNumber);            int pre=getPrevViewNumber_RL(newViewNumber);      int next=getNextViewNumber_RL(newViewNumber);            _xViewNumbers.set(0, pre);      _xViewNumbers.set(1, newViewNumber);      _xViewNumbers.set(2, next);      _yViewNumbers.set(1, newViewNumber);     }    }    if (mFlingDirection == 2) {     if (mCurrentPosition > getFirstPosition_UD() || mIsGalleryCircular == true) {      // Determine previous view and outgoing view to recycle      newViewNumber = getPrevViewNumber_UD(mCurrentViewNumber);      mCurrentPosition = getPrevPosition_UD(mCurrentPosition);      reloadViewNumber = getNextViewNumber_UD(mCurrentViewNumber);      reloadPosition = getPrevPosition_UD(mCurrentPosition);        reloadPosition_r = getPrevPosition_RL(mCurrentPosition);      reloadViewNumber_r = getPrevViewNumber_RL(mCurrentViewNumber);        reloadPosition_l = getNextPosition_RL(mCurrentPosition);      reloadViewNumber_l = getNextViewNumber_RL(mCurrentViewNumber);                  int pre=getPrevViewNumber_UD(newViewNumber);      int next=getNextViewNumber_UD(newViewNumber);            _yViewNumbers.set(0, pre);      _yViewNumbers.set(1, newViewNumber);      _yViewNumbers.set(2, next);      _xViewNumbers.set(1, newViewNumber);     }    }      if (mFlingDirection == -1) {     if (mCurrentPosition < getLastPosition_RL() || mIsGalleryCircular == true) {      // Determine the next view and outgoing view to recycle      newViewNumber = getNextViewNumber_RL(mCurrentViewNumber);      mCurrentPosition = getNextPosition_RL(mCurrentPosition);            recycleViewNumber=mCurrentViewNumber;      recyclePositon=getPrevPosition_RL(mCurrentPosition);            reloadViewNumber = getPrevViewNumber_RL(mCurrentViewNumber);      reloadPosition = getNextPosition_RL(mCurrentPosition);        reloadPosition_up = getPrevPosition_UD(mCurrentPosition);      reloadViewNumber_up =getPrevViewNumber_UD(mCurrentViewNumber) ;        reloadPosition_down = getNextPosition_UD(mCurrentPosition);      reloadViewNumber_down = getNextViewNumber_UD(mCurrentViewNumber);            int pre=getPrevViewNumber_RL(newViewNumber);      int next=getNextViewNumber_RL(newViewNumber);            _xViewNumbers.set(0, pre);      _xViewNumbers.set(1, newViewNumber);      _xViewNumbers.set(2, next);      _yViewNumbers.set(1, newViewNumber);             }    }      if (mFlingDirection == -2) {     if (mCurrentPosition < getLastPosition_UD() || mIsGalleryCircular == true) {      // Determine the next view and outgoing view to recycle      newViewNumber = getNextViewNumber_UD(mCurrentViewNumber);      mCurrentPosition = getNextPosition_UD(mCurrentPosition);            reloadViewNumber = getPrevViewNumber_UD(mCurrentViewNumber);      reloadPosition = getNextPosition_UD(mCurrentPosition);        reloadPosition_r = getPrevPosition_RL(mCurrentPosition);      reloadViewNumber_r = getPrevViewNumber_RL(mCurrentViewNumber);        reloadPosition_l = getNextPosition_RL(mCurrentPosition);      reloadViewNumber_l = getNextViewNumber_RL(mCurrentViewNumber);            int pre=getPrevViewNumber_UD(newViewNumber);      int next=getNextViewNumber_UD(newViewNumber);            _yViewNumbers.set(0, pre);      _yViewNumbers.set(1, newViewNumber);      _yViewNumbers.set(2, next);      _xViewNumbers.set(1, newViewNumber);     }    }      if (newViewNumber != mCurrentViewNumber) {     mCurrentViewNumber = newViewNumber;     // Reload outgoing view from adapter in new position     if (MoveStyle == MOVE_LEFT_RIGHT) {      mViews[reloadViewNumber].recycleView(reloadPosition);      mViews[reloadViewNumber_up].recycleView(reloadPosition_up);      mViews[reloadViewNumber_down].recycleView(reloadPosition_down);     } else if (MoveStyle == MOVE_UP_DOWN) {      mViews[reloadViewNumber].recycleView(reloadPosition);      mViews[reloadViewNumber_r].recycleView(reloadPosition_r);      mViews[reloadViewNumber_l].recycleView(reloadPosition_l);     }    }      // 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    if (MoveStyle == MOVE_LEFT_RIGHT) {     float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;     int rollOffset = mGalleryWidth - (int) rollEdgeWidth;     int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset()[0];     if (currentOffset <= rollOffset * -1) {      // Snap to previous view      mFlingDirection = 1;     }     if (currentOffset >= rollOffset) {      // Snap to next view      mFlingDirection = -1;     }    } else if (MoveStyle == MOVE_UP_DOWN) {       float rollEdgeHeight = mGalleryHeight * mSnapBorderRatio;     int rollOffset_Y = mGalleryHeight - (int) rollEdgeHeight;     int currentOffset_Y = mViews[mCurrentViewNumber].getCurrentOffset()[1];     if (currentOffset_Y <= rollOffset_Y * -1) {      // Snap to previous view      mFlingDirection = 2;     }     if (currentOffset_Y >= rollOffset_Y) {      // Snap to next view      mFlingDirection = -2;     }    }   }     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);     LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,       LayoutParams.FILL_PARENT);     lp.gravity = Gravity.CENTER;     mInvalidLayout.setLayoutParams(lp);       // Internal layout is permanent for duration     mInternalLayout = new LinearLayout(mContext);       mInternalLayout.setLayoutParams(lp);     mInternalLayout.setPersistentDrawingCache(ViewGroup.PERSISTENT_ALL_CACHES);     mParentLayout.addView(mInternalLayout, lp);    }      public void recycleView(int newPosition) {     if (mExternalView != null) {      mInternalLayout.removeView(mExternalView);     }       if (mAdapter != null) {      if (newPosition >= 0 && newPosition <= getLastPosition_All()) {       mExternalView = mAdapter.getView(newPosition, mExternalView, mInternalLayout);      } else {       mExternalView = mInvalidLayout;      }     }       if (mExternalView != null) {      mInternalLayout.addView(mExternalView, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,        LayoutParams.FILL_PARENT));     }    }      public void setOffset(int xOffset, int yOffset, int relativeViewNumber) {     // Scroll the target view relative to its own position relative to     // currently displayed view     int distance = getViewOffset(mViewNumber, relativeViewNumber);     int x=mGalleryWidth + mViewPaddingWidth;     int y=mGalleryHeight + mViewPaddingWidth;     if(Math.abs(distance)==x){      mInternalLayout.scrollTo(distance + xOffset, yOffset);     }else if(Math.abs(distance)==y){      mInternalLayout.scrollTo(xOffset, distance + yOffset);     }else if(Math.abs(distance)==0){      mInternalLayout.scrollTo(xOffset, yOffset);     }     Log.v("Position", "mViewNumber: " + mViewNumber + " mCurrentViewNumber: " + mCurrentViewNumber+ " distance: " + distance);      }      public int[] getCurrentOffset() {     // Return the current scroll position     return new int[]{mInternalLayout.getScrollX(), mInternalLayout.getScrollY()};    }      public void requestFocus() {     mInternalLayout.setFocusable(true);     mInternalLayout.setFocusableInTouchMode(true);     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;    }          @Override    public boolean getFillAfter() {     // TODO Auto-generated method stub     mViews[recycleViewNumber].recycleView(recyclePositon);     direction = true;     boolean falg=super.getFillAfter();     return falg;    }        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=0;       int animDirection = (mTargetDistance < 0) ? 1 : -1;       if (MoveStyle == MOVE_LEFT_RIGHT) {         newDirection = (relativeViewNumber == getPrevViewNumber_RL(mRelativeViewNumber)) ? 1 : -1;        // If animation in same direction        if (animDirection == newDirection) {         // Ran out of time to animate so snap to the target         // offset         mViews[_xViewNumbers.get(0)].setOffset(mTargetOffset, 0, mRelativeViewNumber);         mViews[_xViewNumbers.get(1)].setOffset(mTargetOffset, 0, mRelativeViewNumber);         mViews[_xViewNumbers.get(2)].setOffset(mTargetOffset, 0, mRelativeViewNumber);        }       } else if (MoveStyle == MOVE_UP_DOWN) {        newDirection = (relativeViewNumber == getPrevViewNumber_UD(mRelativeViewNumber)) ? 1 : -1;        if (animDirection == newDirection) {         // Ran out of time to animate so snap to the target         // offset         mViews[_yViewNumbers.get(0)].setOffset(0, mTargetOffset, mRelativeViewNumber);         mViews[_yViewNumbers.get(1)].setOffset(0, mTargetOffset, mRelativeViewNumber);         mViews[_yViewNumbers.get(2)].setOffset(0, mTargetOffset, 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     if (MoveStyle == MOVE_LEFT_RIGHT) {      mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset()[0];     } else if (MoveStyle == MOVE_UP_DOWN) {      mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset()[1];     }     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 < 5; viewNumber++) {      // Only need to animate the visible views as the other view will      // always be off-screen        if (MoveStyle == MOVE_LEFT_RIGHT) {       if ((mTargetDistance > 0 && viewNumber != getNextViewNumber_RL(mRelativeViewNumber))         || (mTargetDistance < 0 && viewNumber != getPrevViewNumber_RL(mRelativeViewNumber))) {        mViews[viewNumber].setOffset(offset, 0, mRelativeViewNumber);       }      } else if (MoveStyle == MOVE_UP_DOWN ) {       if ((mTargetDistance > 0 && viewNumber != getNextViewNumber_UD(mRelativeViewNumber))         || (mTargetDistance < 0 && viewNumber != getPrevViewNumber_UD(mRelativeViewNumber))) {        mViews[viewNumber].setOffset(0, offset, mRelativeViewNumber);       }      }     }    }      @Override    public boolean getTransformation(long currentTime, Transformation outTransformation) {     if (super.getTransformation(currentTime, outTransformation) == false) {      // Perform final adjustment to offsets to cleanup animation      Log.v("mTargetOffset", "mTargetOffset: " + mTargetOffset);      if (MoveStyle == MOVE_LEFT_RIGHT) {              mViews[_xViewNumbers.get(0)].setOffset(mTargetOffset, 0, mRelativeViewNumber);       mViews[_xViewNumbers.get(1)].setOffset(mTargetOffset, 0, mRelativeViewNumber);       mViews[_xViewNumbers.get(2)].setOffset(mTargetOffset, 0, mRelativeViewNumber);             } else if (MoveStyle == MOVE_UP_DOWN) {       mViews[_yViewNumbers.get(0)].setOffset(0, mTargetOffset, mRelativeViewNumber);       mViews[_yViewNumbers.get(1)].setOffset(0, mTargetOffset, mRelativeViewNumber);       mViews[_yViewNumbers.get(2)].setOffset(0, mTargetOffset, 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;    }   }     float mLastMotionX = 0;   float mLastMotionY = 0;     // int firstx = 0;   private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener {    @Override    public boolean onDown(MotionEvent e) {     // firstx = (int) e.getX();     // Stop animation     //mIsTouched = true;     // Reset fling state     mFlingDirection = 0;     return true;    }      @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {     // int scrollOffset = 0;     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;        if (MoveStyle == MOVE_LEFT_RIGHT) {       float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f);       float currentScrollDelta = e1.getRawX() - e2.getRawX();         if (currentScrollDelta < maxScrollDelta * -1)        currentScrollDelta = maxScrollDelta * -1;       if (currentScrollDelta > maxScrollDelta)        currentScrollDelta = maxScrollDelta;       int scrollOffset = Math.round(mCurrentOffset[0] + currentScrollDelta);         // We can't scroll more than the width of our own       // framelayout       if (scrollOffset >= mGalleryWidth)        scrollOffset = mGalleryWidth;       if (scrollOffset <= mGalleryWidth * -1)        scrollOffset = mGalleryWidth * -1;       mViews[_xViewNumbers.get(0)].setOffset(scrollOffset, 0, mCurrentViewNumber);       mViews[_xViewNumbers.get(1)].setOffset(scrollOffset, 0, mCurrentViewNumber);       mViews[_xViewNumbers.get(2)].setOffset(scrollOffset, 0, mCurrentViewNumber);       // h_viewnumber=mCurrentViewNumber;      }        if (MoveStyle == MOVE_UP_DOWN) {         float maxVelocity_Y = mGalleryHeight / (mAnimationDuration / 1000.0f);       float maxScrollDelta_Y = maxVelocity_Y * (timestampDelta / 1000.0f);       float currentScrollDelta_Y = e1.getRawY() - e2.getRawY();       if (currentScrollDelta_Y < maxScrollDelta_Y * -1)        currentScrollDelta_Y = maxScrollDelta_Y * -1;       if (currentScrollDelta_Y > maxScrollDelta_Y)        currentScrollDelta_Y = maxScrollDelta_Y;       int scrollOffset_Y = Math.round(mCurrentOffset[1] + currentScrollDelta_Y);       if (scrollOffset_Y >= mGalleryHeight)        scrollOffset_Y = mGalleryHeight;       if (scrollOffset_Y <= mGalleryHeight * -1)        scrollOffset_Y = mGalleryHeight * -1;       mViews[_yViewNumbers.get(0)].setOffset(0, scrollOffset_Y, mCurrentViewNumber);       mViews[_yViewNumbers.get(1)].setOffset(0, scrollOffset_Y, mCurrentViewNumber);       mViews[_yViewNumbers.get(2)].setOffset(0, scrollOffset_Y, 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_RL();      }      if (e1.getX() - e2.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty) {       // moveNext_RL();      }      if (e2.getY() - e1.getY() > swipe_min_distance && Math.abs(velocityY) > swipe_threshold_veloicty) {       // movePrevious_UD();      }      if (e1.getY() - e2.getY() > swipe_min_distance && Math.abs(velocityY) > swipe_threshold_veloicty) {       // moveNext_UD();      }       }       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     return false;    }   }    }