`
v5browser
  • 浏览: 1137642 次
社区版块
存档分类
最新评论

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

}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics