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;
}
}
}

本文介绍了一个自定义的视图翻页组件实现方案,通过继承FrameLayout并结合自定义动画实现平滑翻页效果。该组件支持水平和垂直方向翻页,并能够通过触摸手势进行翻页操作。
4471

被折叠的 条评论
为什么被折叠?



