package com.droidful.flinggallery;
import android.content.Context;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
import android.widget.Adapter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
// TODO:
// 1. In order to improve performance Cache screen bitmap and use for animation
// 2. Establish superfluous memory allocations and delay or replace with reused objects
// Probably need to make sure we are not allocating objects (strings, etc.) in loops
public class FlingGallery extends FrameLayout
{
// Constants
private final int swipe_min_distance = 120;
private final int swipe_max_off_path = 250;
private final int swipe_threshold_veloicty = 400;
// Properties
private int mViewPaddingWidth = 0;
private int mAnimationDuration = 250;
private float mSnapBorderRatio = 0.5f;
private boolean mIsGalleryCircular = true;
// Members
private int mGalleryWidth = 0;
private boolean mIsTouched = false;
private boolean mIsDragging = false;
private float mCurrentOffset = 0.0f;
private long mScrollTimestamp = 0;
private int mFlingDirection = 0;
private int mCurrentPosition = 0;
private int mCurrentViewNumber = 0;
private Context mContext;
private Adapter mAdapter;
private FlingGalleryView[] mViews;
private FlingGalleryAnimation mAnimation;
private GestureDetector mGestureDetector;
private Interpolator mDecelerateInterpolater;
public FlingGallery(Context context)
{
super(context);
mContext = context;
mAdapter = null;
mViews = new FlingGalleryView[3];
mViews[0] = new FlingGalleryView(0, this);
mViews[1] = new FlingGalleryView(1, this);
mViews[2] = new FlingGalleryView(2, this);
mAnimation = new FlingGalleryAnimation();
mGestureDetector = new GestureDetector(new FlingGestureDetector());
mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext, android.R.anim.decelerate_interpolator);
}
public void setPaddingWidth(int viewPaddingWidth)
{
mViewPaddingWidth = viewPaddingWidth;
}
public void setAnimationDuration(int animationDuration)
{
mAnimationDuration = animationDuration;
}
public void setSnapBorderRatio(float snapBorderRatio)
{
mSnapBorderRatio = snapBorderRatio;
}
public void setIsGalleryCircular(boolean isGalleryCircular)
{
if (mIsGalleryCircular != isGalleryCircular)
{
mIsGalleryCircular = isGalleryCircular;
if (mCurrentPosition == getFirstPosition())
{
// We need to reload the view immediately to the left to change it to circular view or blank
mViews[getPrevViewNumber(mCurrentViewNumber)].recycleView(getPrevPosition(mCurrentPosition));
}
if (mCurrentPosition == getLastPosition())
{
// We need to reload the view immediately to the right to change it to circular view or blank
mViews[getNextViewNumber(mCurrentViewNumber)].recycleView(getNextPosition(mCurrentPosition));
}
}
}
public int getGalleryCount()
{
return (mAdapter == null) ? 0 : mAdapter.getCount();
}
public int getFirstPosition()
{
return 0;
}
public int getLastPosition()
{
return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
}
private int getPrevPosition(int relativePosition)
{
int prevPosition = relativePosition - 1;
if (prevPosition < getFirstPosition())
{
prevPosition = getFirstPosition() - 1;
if (mIsGalleryCircular == true)
{
prevPosition = getLastPosition();
}
}
return prevPosition;
}
private int getNextPosition(int relativePosition)
{
int nextPosition = relativePosition + 1;
if (nextPosition > getLastPosition())
{
nextPosition = getLastPosition() + 1;
if (mIsGalleryCircular == true)
{
nextPosition = getFirstPosition();
}
}
return nextPosition;
}
private int getPrevViewNumber(int relativeViewNumber)
{
return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
}
private int getNextViewNumber(int relativeViewNumber)
{
return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
// Calculate our view width
mGalleryWidth = right - left;
if (changed == true)
{
// Position views at correct starting offsets
mViews[0].setOffset(0, 0, mCurrentViewNumber);
mViews[1].setOffset(0, 0, mCurrentViewNumber);
mViews[2].setOffset(0, 0, mCurrentViewNumber);
}
}
public void setAdapter(Adapter adapter)
{
mAdapter = adapter;
mCurrentPosition = 0;
mCurrentViewNumber = 0;
// Load the initial views from adapter
mViews[0].recycleView(mCurrentPosition);
mViews[1].recycleView(getNextPosition(mCurrentPosition));
mViews[2].recycleView(getPrevPosition(mCurrentPosition));
// Position views at correct starting offsets
mViews[0].setOffset(0, 0, mCurrentViewNumber);
mViews[1].setOffset(0, 0, mCurrentViewNumber);
mViews[2].setOffset(0, 0, mCurrentViewNumber);
}
private int getViewOffset(int viewNumber, int relativeViewNumber)
{
// Determine width including configured padding width
int offsetWidth = mGalleryWidth + mViewPaddingWidth;
// Position the previous view one measured width to left
if (viewNumber == getPrevViewNumber(relativeViewNumber))
{
return offsetWidth;
}
// Position the next view one measured width to the right
if (viewNumber == getNextViewNumber(relativeViewNumber))
{
return offsetWidth * -1;
}
return 0;
}
void movePrevious()
{
// Slide to previous view
mFlingDirection = 1;
processGesture();
}
void moveNext()
{
// Slide to next view
mFlingDirection = -1;
processGesture();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_DPAD_LEFT:
movePrevious();
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
moveNext();
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
}
return super.onKeyDown(keyCode, event);
}
public boolean onGalleryTouchEvent(MotionEvent event)
{
boolean consumed = mGestureDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP)
{
if (mIsTouched || mIsDragging)
{
processScrollSnap();
processGesture();
}
}
return consumed;
}
void processGesture()
{
int newViewNumber = mCurrentViewNumber;
int reloadViewNumber = 0;
int reloadPosition = 0;
mIsTouched = false;
mIsDragging = false;
if (mFlingDirection > 0)
{
if (mCurrentPosition > getFirstPosition() || mIsGalleryCircular == true)
{
// Determine previous view and outgoing view to recycle
newViewNumber = getPrevViewNumber(mCurrentViewNumber);
mCurrentPosition = getPrevPosition(mCurrentPosition);
reloadViewNumber = getNextViewNumber(mCurrentViewNumber);
reloadPosition = getPrevPosition(mCurrentPosition);
}
}
if (mFlingDirection < 0)
{
if (mCurrentPosition < getLastPosition() || mIsGalleryCircular == true)
{
// Determine the next view and outgoing view to recycle
newViewNumber = getNextViewNumber(mCurrentViewNumber);
mCurrentPosition = getNextPosition(mCurrentPosition);
reloadViewNumber = getPrevViewNumber(mCurrentViewNumbe
荣华富贵8
- 粉丝: 219
- 资源: 7653
最新资源
- 424大神PHP基于MVC三层商品进销存管理系统毕业课程源码设计
- 基于springboot的玩具租赁系统源码(java毕业设计完整源码).zip
- 西门子博途HMI监控1200或1500的IO状态时做成一页,IO监控画面做在一页显示,通过下拉菜单选择,方便快捷,不用一个一个去摆放了,是HMI及PLC源程序(SCL编写)
- 机器学习赵卫东第二版答案
- 五子棋游戏 V1.1.exe-五子棋游戏 V1.1.exe
- mqtt服务器服务器搭建
- “保护环境 从我做起”教案课件宣传模板幼儿园小学.pptx
- “儿童节快乐”宣传教案课件模板小学幼儿园.pptx
- “儿童节主题活动”幼儿园小学班会教案课件模板.pptx
- “时光请慢些”父亲节宣传教案课件模板小学幼儿园.pptx
- “致童真的你”亲子活动策划方案.pptx
- 基于springboot的瑜伽体验课预约系统源码(java毕业设计完整源码).zip
- CP210x-Universal-Windows-Driver 2
- 台达,AS228T,plc程序模板和触摸屏程序模板,目前6个总线伺服,采用CANOPEN,适用于运动轴控制,程序可以在自动的时候暂停进行手动控制,适用于一些中大型设备,可以防止某个气缸超时时,处于自动
- 机械设计遮阳板螺丝自动锁附专机sw2016可编辑全套设计资料100%好用.zip
- 425大神PHP基于MVC三层学生测评管理系统毕业课程源码设计
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈