FlingGalleryActivity

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

from: 点击打开链接

更多相关文章

  1. Android 链接https出现 javax.net.ssl.SSLException: hostname i
  2. android中用Spannable在TextView中设置超链接、颜色、字体
  3. 识别链接,可以点击TextView
  4. 通过超链接打开一些常见app(android:scheme运用)
  5. Android market:// 链接到Google Play 商店
  6. Android淘宝客链接自动跳转淘宝APP问题
  7. Android文档不同Tab页之间无法自由链接的问题
  8. Android 给TextView 中 部分文字加下划线 并加入超链接(可点击)

随机推荐

  1. Android RxJava:基础介绍与使用
  2. Android画图方式
  3. android中如何创建Service
  4. Android(安卓)Service之bindService()
  5. Android(安卓)kernel x86 编译方法
  6. Android之父:后乔布斯时代的苹果依然会很
  7. Android Framework architecture -- blue
  8. Android adb功能使用方法
  9. Android开发学习1 - Android架构
  10. 值得推荐的Android App (一)