import android.app.Activity;import android.os.Bundle;import android.content.Context;import android.graphics.Color;import android.util.Log;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.View.OnClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.CheckBox;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.TableLayout;import android.widget.TextView;public class FlingGalleryActivity extends Activity{private final int color_red = Color.argb(100, 200, 0, 0);private final int color_green = Color.argb(100, 0, 200, 0);private final int color_blue = Color.argb(100, 0, 0, 200);private final int color_yellow = Color.argb(100, 200, 200, 0);private final int color_purple = Color.argb(100, 200, 0, 200);    private final String[] mLabelArray = {"View1", "View2", "View3", "View4", "View5"};    private final int[] mColorArray = {color_red, color_green, color_blue, color_yellow, color_purple};private FlingGallery mGallery;private CheckBox mCheckBox;    // Note: The following handler is critical to correct function of    // the FlingGallery class. This enables the FlingGallery class to    // detect when the motion event has ended by finger being lifted    @Override    public boolean onTouchEvent(MotionEvent event){        return mGallery.onGalleryTouchEvent(event);    }    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        mGallery = new FlingGallery(this);        mGallery.setPaddingWidth(5);        mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, mLabelArray)        {        @Override        public View getView(int position, View convertView, ViewGroup parent)        {        Log.d("111", "count="+position);//            if (convertView != null && convertView instanceof GalleryViewItem)//                {//            GalleryViewItem galleryView = (GalleryViewItem) convertView;////            galleryView.mEdit1.setText("");//            galleryView.mText1.setText(mLabelArray[position]);//            galleryView.mText1.setBackgroundColor(mColorArray[position]);//            galleryView.mText2.setText(mLabelArray[position]);//            galleryView.mText2.setBackgroundColor(mColorArray[position]);//            //            Log.d("111", "count="+position);//            //            return galleryView;//            //                }                        return new GalleryViewItem(getApplicationContext(), position);        }        });        LinearLayout layout = new LinearLayout(getApplicationContext());        layout.setOrientation(LinearLayout.VERTICAL);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);layoutParams.setMargins(10, 10, 10, 10);layoutParams.weight = 1.0f;          layout.addView(mGallery, layoutParams);            mCheckBox = new CheckBox(getApplicationContext());        mCheckBox.setText("Gallery is Circular");        mCheckBox.setText("Gallery is Circular");        mCheckBox.setPadding(50, 10, 0, 10);        mCheckBox.setTextSize(30);        mCheckBox.setChecked(true);        mCheckBox.setOnClickListener(new OnClickListener()        {@Overridepublic void onClick(View view){mGallery.setIsGalleryCircular(mCheckBox.isChecked());}        });        layout.addView(mCheckBox, new LinearLayout.LayoutParams(    LinearLayout.LayoutParams.MATCH_PARENT,    LinearLayout.LayoutParams.WRAP_CONTENT));            setContentView(layout);    }private class GalleryViewItem extends TableLayout{private EditText mEdit1;private TextView mText1;private TextView mText2;private Button mButton1;private Button mButton2;public GalleryViewItem(Context context, int position){super(context);this.setOrientation(LinearLayout.VERTICAL);    this.setLayoutParams(new LinearLayout.LayoutParams(    LinearLayout.LayoutParams.MATCH_PARENT,    LinearLayout.LayoutParams.MATCH_PARENT));        mEdit1 = new EditText(context);    this.addView(mEdit1, new LinearLayout.LayoutParams(            LinearLayout.LayoutParams.MATCH_PARENT,            LinearLayout.LayoutParams.WRAP_CONTENT));             mText1 = new TextView(context);            mText1.setText(mLabelArray[position]);            mText1.setTextSize(30);            mText1.setGravity(Gravity.LEFT);            mText1.setBackgroundColor(mColorArray[position]);    this.addView(mText1, new LinearLayout.LayoutParams(            LinearLayout.LayoutParams.MATCH_PARENT,            LinearLayout.LayoutParams.WRAP_CONTENT));             mButton1 = new Button(context);            mButton1.setText("<<");            mButton1.setGravity(Gravity.LEFT);            mButton1.setOnClickListener(new OnClickListener()            {@Overridepublic void onClick(View view){mGallery.movePrevious();}            });                        this.addView(mButton1, new LinearLayout.LayoutParams(            LinearLayout.LayoutParams.MATCH_PARENT,            LinearLayout.LayoutParams.WRAP_CONTENT));             mButton2 = new Button(context);            mButton2.setText(">>");            mButton2.setGravity(Gravity.RIGHT);            mButton2.setOnClickListener(new OnClickListener()            {@Overridepublic void onClick(View view){mGallery.moveNext();}            });                        this.addView(mButton2, new LinearLayout.LayoutParams(            LinearLayout.LayoutParams.MATCH_PARENT,            LinearLayout.LayoutParams.WRAP_CONTENT));             mText2 = new TextView(context);            mText2.setText(mLabelArray[position]);    mText2.setTextSize(30);    mText2.setGravity(Gravity.RIGHT);    mText2.setBackgroundColor(mColorArray[position]);    this.addView(mText2, new LinearLayout.LayoutParams(            LinearLayout.LayoutParams.MATCH_PARENT,            LinearLayout.LayoutParams.MATCH_PARENT, 1)); }}}
   
   

.[代码]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 loopspublic class FlingGallery extends FrameLayout{// Constantsprivate 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;}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom){super.onLayout(changed, left, top, right, bottom);// Calculate our view widthmGalleryWidth = 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 widthint offsetWidth = mGalleryWidth + mViewPaddingWidth;// Position the previous view one measured width to leftif (viewNumber == getPrevViewNumber(relativeViewNumber)){return offsetWidth;}// Position the next view one measured width to the rightif (viewNumber == getNextViewNumber(relativeViewNumber)){return offsetWidth * -1;}return 0;}void movePrevious(){// Slide to previous viewmFlingDirection = 1;processGesture();}void moveNext(){// Slide to next viewmFlingDirection = -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 recyclenewViewNumber = 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 recyclenewViewNumber = getNextViewNumber(mCurrentViewNumber);mCurrentPosition = getNextPosition(mCurrentPosition);reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);reloadPosition = getNextPosition(mCurrentPosition);}}if (newViewNumber != mCurrentViewNumber){mCurrentViewNumber = newViewNumber; // Reload outgoing view from adapter in new positionmViews[reloadViewNumber].recycleView(reloadPosition);}// Ensure input focus on the current viewmViews[mCurrentViewNumber].requestFocus();// Run the slide animations for view transitionsmAnimation.prepareAnimation(mCurrentViewNumber);this.startAnimation(mAnimation);// Reset fling statemFlingDirection = 0;}void processScrollSnap(){// Snap to next view if scrolled passed snap positionfloat rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;int rollOffset = mGalleryWidth - (int) rollEdgeWidth;int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();if (currentOffset <= rollOffset * -1){// Snap to previous viewmFlingDirection = 1;}if (currentOffset >= rollOffset){// Snap to next viewmFlingDirection = -1;}}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 gallerymInvalidLayout = new FrameLayout(mContext);mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));// Internal layout is permanent for durationmInternalLayout = new LinearLayout(mContext);mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));mParentLayout.addView(mInternalLayout);}public void recycleView(int newPosition){if (mExternalView != null){mInternalLayout.removeView(mExternalView);}if (mAdapter != null){if (newPosition >= getFirstPosition() && newPosition <= getLastPosition()){mExternalView = mAdapter.getView(newPosition, mExternalView, mInternalLayout);}else{mExternalView = mInvalidLayout;}}if (mExternalView != null){mInternalLayout.addView(mExternalView, new LinearLayout.LayoutParams(                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));}}public void setOffset(int xOffset, int yOffset, int relativeViewNumber){// Scroll the target view relative to its own position relative to currently displayed viewmInternalLayout.scrollTo(getViewOffset(mViewNumber, relativeViewNumber) + xOffset, yOffset);}public int getCurrentOffset(){// Return the current scroll positionreturn mInternalLayout.getScrollX();}public void requestFocus(){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;    }     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 = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1 : -1;    int animDirection = (mTargetDistance < 0) ? 1 : -1;     // If animation in same direction    if (animDirection == newDirection)    {        // Ran out of time to animate so snap to the target offset        mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);mViews[2].setOffset(mTargetOffset, 0, 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 implementationsmInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();mTargetOffset = getViewOffset(mRelativeViewNumber, mRelativeViewNumber);mTargetDistance = mTargetOffset - mInitialOffset;// Configure base animation propertiesthis.setDuration(mAnimationDuration);this.setInterpolator(mDecelerateInterpolater);// Start/continued animationmIsAnimationInProgres = 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 < 3; viewNumber++){// Only need to animate the visible views as the other view will always be off-screenif ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber)) ||(mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber))){mViews[viewNumber].setOffset(offset, 0, mRelativeViewNumber);}}        }        @Override        public boolean getTransformation(long currentTime, Transformation outTransformation)        {        if (super.getTransformation(currentTime, outTransformation) == false)        {        // Perform final adjustment to offsets to cleanup animation        mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);// Reached the animation targetmIsAnimationInProgres = 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;        }    }private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener    {    @Override    public boolean onDown(MotionEvent e)    {    // Stop animation    mIsTouched = true;    // Reset fling state    mFlingDirection = 0;            return true;    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)    {    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;        float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f);         float currentScrollDelta = e1.getX() - e2.getX();        if (currentScrollDelta < maxScrollDelta * -1) currentScrollDelta = maxScrollDelta * -1;        if (currentScrollDelta > maxScrollDelta) currentScrollDelta = maxScrollDelta;        int scrollOffset = Math.round(mCurrentOffset + currentScrollDelta);        // We can't scroll more than the width of our own frame layout        if (scrollOffset >= mGalleryWidth) scrollOffset = mGalleryWidth;        if (scrollOffset <= mGalleryWidth * -1) scrollOffset = mGalleryWidth * -1;                mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);    mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);    mViews[2].setOffset(scrollOffset, 0, 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();                }                if(e1.getX() - e2.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)                {                moveNext();                }            }            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    mFlingDirection = 0;            return false;    }    }}


更多相关文章

  1. Android在代码中设置控件的drawableLeft,drawableRight,drawableTo
  2. Android随笔--短小精悍的代码段(持续更新)
  3. 随想录(一个android原生app的代码赏析)
  4. Loader和Fragment使用示例代码
  5. Eclipse中查看Android源代码
  6. Android 记忆卡片游戏 记忆力 Android游戏 Android记忆卡片游戏
  7. android 源代码在线查看和索引
  8. Android系统默认Home应用程序(Launcher)的启动过程源代码分析(3)

随机推荐

  1. android之接收和发送广播的开机可自动运
  2. Android(安卓)获取imei号码,获取手机型号
  3. Android通知的基本用法
  4. android获取wifi信号强度
  5. Android(安卓)ScrollView 内部控件 layou
  6. Android(安卓)设置让EditText不自动获取
  7. android button 上添加图片
  8. android webview
  9. Android(安卓)PureMVC
  10. android 自动化(1)