自定義android循環拖動組件

openkk 12年前發布 | 20K 次閱讀 Android Android開發 移動開發

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 = {"; 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;
}

}</pre>自定義逐漸基本功能實現,現在公開源碼。

其中點擊觸發動畫事件未能解決,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;
        }
    }

}

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!